Mail Archives: cygwin/2005/09/15/16:24:59
Eric Blake wrote:
>> Hello, I'm doing homework and I'm having some problems with stat()
>> failing.
>
> It's called homework for a reason, but here are some hints:
Come on, at least I just didn't post the assignment without a single line
code and waited
for someone to fix it for me like I see alot on different forums and
newsgroups. I've put effort into this and I also tried to use a readable
coding style.
>
>> Consider the following C program:
>>
>> #include <assert.h>
>> #include <errno.h>
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <string.h>
>>
>> #include <dirent.h>
>> #include <sys/stat.h>
>> #include <sys/types.h>
>>
>> static void scan_directory(const char *);
>>
>> int
>> main(int argc, char **argv)
>> {
>> if(argc == 1)
>> {
>> fprintf(stderr, "Usage: dirscan path\n");
>>
>> return EXIT_FAILURE;
>> }
>>
>> scan_directory(argv[1]);
>>
>> return EXIT_SUCCESS;
>> }
>>
>> static void
>> scan_directory(const char *path)
>> {
>> DIR *directory = NULL;
>> struct dirent *entry = NULL;
>> struct stat statbuf;
>> int return_value = 0;
>>
>> directory = opendir(path);
>>
>> if(!directory)
>> {
>> fprintf(stderr, "Directory %s could not be opened.\n", path);
>
> fprintf can clobber errno...
>
>> fprintf(stderr, "Reason: %s\n", strerror(errno));
>
> so you may be printing the wrong reason.
>
>>
>> /* Don't exit program, we may have been called recursively and
>> we want to scan what we can.
>> */ return;
>> }
>>
>> while((entry = readdir(directory)))
>
> You just ignored the possibility that readdir might set errno.
>
>> {
Ok, I can set errno to 0 before I call stat(), but I was under the
impression that if stat() fails it will overwrite the current value of errno
with a new one indicating the error. And since I determine if an error
occured by checking the return value of stat() and *then* checking errno if
the return value was != 0 instead of looking at errno directly, isn't my way
safe even if errno was nonzero before the call?
>> return_value = stat(entry->d_name, &statbuf);
>
> Hmm - think relative vs. absolute pathname, then consider where
> you invoked your command.
Ah, that's it! readdir() is looking at the directory I supplied as a command
line argument, but stat() is looking at the cwd. And in the cwd I happen to
have a files called "Makefile", ".", and, "..", respectively. but not the
other files found by readdir(). So I to change the call to stat() so it gets
the whole path to the files found by readdir(). Thanks very much!
>
>>
>> if(return_value)
>> fprintf(stderr, "stat() failed for %s. Reason: %s\n",
>> entry->d_name, strerror(errno));
>> else
>> printf("stat() called successfully on: %s\n",
>> entry->d_name); }
>>
>> return_value = closedir(directory);
>>
>> assert(!return_value); /* closedir() returns 0 on success */
>> }
>>
>> And this is what happens when I run it (first ls -al):
>> $ ls -al /c/cygwin/home/mikael/coding/cygwin/c++/read_directory/
>> total 773
>> drwxrwxrwx+ 2 mikael None 0 Sep 15 16:36 ./
>> drwxrwxrwx+ 16 mikael None 0 May 20 22:53 ../
>> -rwxrwxrwx 1 mikael None 273 Sep 15 16:36 Makefile*
>> -rwxrwxrwx 1 mikael None 792 Aug 19 2004 read_directory.cpp*
>> -rwxr-xr-x 1 mikael None 604746 Sep 15 16:36 read_directory.exe*
>> -rw-r--r-- 1 mikael None 129520 Sep 15 16:36 read_directory.o
>>
>> $ ./dirscan.exe
>> /c/cygwin/home/mikael/coding/cygwin/c++/read_directory/ stat()
>> called successfully on: .
>> stat() called successfully on: ..
>> stat() called successfully on: Makefile
>> stat() failed for read_directory.cpp. Reason: No such file or
>> directory stat() failed for read_directory.exe. Reason: No such file
>> or directory stat() failed for read_directory.o. Reason: No such
>> file or directory
>
> As a side note, Windows has the annoying habit that when a file
> is locked by another application, stat() won't get much information
> about the file, but at least it won't fail.
Interesting...I will be sure keep that in mind if I encounter other problems
with stat() being non-informative.
Thanks for the quick reply, Eric!
/ Mikael
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
- Raw text -