X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX198CcMrT1d8VRvWIpN9xQmrQ8O/GANT/U5TRSZd+0 iYztMC9Ca0iZpf From: Juan Manuel Guerrero To: djgpp-workers AT delorie DOT com Subject: What are usefull errno values produced by readdiir? Date: Tue, 17 Jun 2008 11:46:59 +0200 User-Agent: KMail/1.9.5 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200806171146.59903.juan.guerrero@gmx.de> X-Y-GMX-Trusted: 0 Reply-To: djgpp-workers AT delorie DOT com The current version of readdir() will return "Invalid argument (EINVAL)" for all files of 510 bytes of size if they are not symlinks. This error message is produced by the symlink code of readdir. readdir performs a lot of tests to characterize the current file and the last test is a symlink test that is only performed if the file size has the symlink size of 510 bytes (_SYMLINK_FILE_LEN). In this case __internal_readlink is called and this function set errno to EINVAL If the file is not a symlink. That is ok, but now readdir passes this errno to the calling function. This means that every file of _SYMLINK_FILE_LEN length that is really not a symlink triggers errno to be EINVAL. If the calling function evaluates errno after the readdir call it is clear that the calling function must probably fail. This is again a design issue of readdir that must probably solved by the original author of the code. Please note that this is not a trivial issue. My current port of findutils fails due to this readdir behaviour. For example, if I try to build the djlsr204.zip file from the checked ouf CVS sources using /distrib/mkdist.bat I get the following error message: C:\djgpp\bin/find.exe: src/libc/c99/inttypes/cvs: Invalid argument (EINVAL) The reason for this is that the last detected file in the CVS directory is Entries and has a size of exactly 510 bytes and thus is identtified as potential symlink. Because __internal_readlink detects that this is not a symlink it returns errno set to EINVAL and the whole content of the CVS directory is discarted and not printed and a confusing error message is printed instead. Of course, now that I know this I can fix findutils accordingly, but the question remains if the design of the symlink support is optimal. To make this clear here is a extract of the "offending" findutils code: dirp = opendir (dir); if (dirp == NULL) return NULL; errno = 0; [snip] while ((dp = readdir (dirp)) != NULL) { [snip] } [snip] save_errno = errno; if (CLOSEDIR (dirp) != 0) save_errno = errno; if (save_errno != 0) { free (result->buffer); free (result); errno = save_errno; return NULL; } return result; } This is probably the conventional way to use readdir to read directory entries. As can be seen if CLOSEDIR does not fail but readdir sets errno to something the function fails and returns NULL. In this particular case, this means that the function behaviour depends on the design of readdir. For the djgpp port of findutils this implies that every 510 byte size file will make find fail not printing the containt of the directory where this file lives and printing the EINVAL error message. Of course every code working similar to this one will fail too. Because I am not the original author of readdir I do not know if this behaviour is a bug or a feature. Any clarification about this will be welcome. Regards, Juan M. Guerrero