Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com X-Originating-IP: [203.12.97.91] X-Originating-Email: [dcoshea AT hotmail DOT com] From: "David O'Shea" To: "Cygwin List" Subject: Re: Cygwin doesn't show .. in all directories Date: Fri, 12 Sep 2003 01:48:15 +1000 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 Message-ID: X-OriginalArrivalTime: 11 Sep 2003 15:48:17.0782 (UTC) FILETIME=[1E668960:01C3787C] Hi all, Can anyone comment on these diffs? Apart from being messy and not properly formatted at the moment and having way too many calls to syscall_printf(), are they okay? Also, where it says "/* FIXME: what is supposed to happen if lasterr == ERROR_NO_MORE_FILES??? */", I am wondering if I noticed a bug, in that if lasterr happened to have that value (which it might never have with current versions of Windows - Windows XP at least seems to return ERROR_FILE_NOT_FOUND if the directory is emtpy which is conceptually the same situation as "no more files" when you're trying to find the first entry) then the code would fall through to the "/* We get here if `buf' contains valid data. */" code, but I don't think buf WOULD have valid data. >>> WIN32_FIND_DATA buf; HANDLE handle; struct dirent *res = NULL; + bool return_dot_dir = FALSE; + syscall_printf ("[doshea] readdir: entering"); + if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE && dir->__d_position == 0) { + syscall_printf ("[doshea] readdir: initial call"); + dir->__d_u.__d_data.__dotdir_flags = 0; handle = FindFirstFileA (dir->__d_dirname, &buf); DWORD lasterr = GetLastError (); dir->__d_u.__d_data.__handle = handle; + /* if there are no files in the directory, handle will be INVALID_HANDLE_VALUE + but, unexpectedly, lasterr will NOT be ERROR_NO_MORE_FILES */ + syscall_printf ("[doshea] readdir: handle invalid? %u lasterr? %u", + handle == INVALID_HANDLE_VALUE, lasterr); if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES)) { - seterrno_from_win_error (__FILE__, __LINE__, lasterr); - return res; + if (lasterr == ERROR_FILE_NOT_FOUND) + { + /* there are no files in the directory, so we should return the + '.' and '..' entries which are obviously missing */ + return_dot_dir = TRUE; + } + else + { + /* some other (unexpected) error has occured */ + seterrno_from_win_error (__FILE__, __LINE__, lasterr); + return res; + } } + /* FIXME: what is supposed to happen if lasterr == ERROR_NO_MORE_FILES??? */ } else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE) - return res; + { + /* dir->__d_position is != 0 so we might have returned some entries and + then gotten to the end but have yet to return both '.' and '..'. */ + syscall_printf ("[doshea] readdir: handle invalid but position %u", + dir->__d_position); + if ((dir->__d_u.__d_data.__dotdir_flags & __DIRENT_DOTDIR_SEEN_ALL) + != __DIRENT_DOTDIR_SEEN_ALL) + { + /* haven't seen both '.' and '..' */ + syscall_printf ("[doshea] readdir: haven't seen: %s %s", + dir->__d_u.__d_data.__dotdir_flags & __DIRENT_DOTDIR_SEEN_DOT ? "" : ".", + dir->__d_u.__d_data.__dotdir_flags & __DIRENT_DOTDIR_SEEN_DOTDOT ? "" : ".."); + return_dot_dir = TRUE; + } + else + return res; + } else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf)) { DWORD lasterr = GetLastError (); @@ -645,37 +681,97 @@ find any more files; so, if another error we leave it set. */ if (lasterr != ERROR_NO_MORE_FILES) seterrno_from_win_error (__FILE__, __LINE__, lasterr); - syscall_printf ("%p = readdir (%p)", res, dir); - return res; + else + { + /* there wasn't an error, so we now check if we need to add '.' + and '..' entries */ + if ((dir->__d_u.__d_data.__dotdir_flags & __DIRENT_DOTDIR_SEEN_ALL) + != __DIRENT_DOTDIR_SEEN_ALL) + { + /* haven't seen both '.' and '..' */ + syscall_printf ("[doshea] readdir: haven't seen: %s %s", + dir->__d_u.__d_data.__dotdir_flags & __DIRENT_DOTDIR_SEEN_DOT ? "" : ".", + dir->__d_u.__d_data.__dotdir_flags & __DIRENT_DOTDIR_SEEN_DOTDOT ? "" : ".."); + return_dot_dir = TRUE; + } + } + /* if we don't have any '.'/'..' entries to fake, return now */ + if (!return_dot_dir) + { + syscall_printf ("%p = readdir (%p)", res, dir); + return res; + } } - /* We get here if `buf' contains valid data. */ - if (get_encoded ()) - (void) fnunmunge (dir->__d_dirent->d_name, buf.cFileName); - else - strcpy (dir->__d_dirent->d_name, buf.cFileName); + /* if we had an INVALID_HANDLE_VALUE but we weren't at position 0, or + FindNextFileA failed failed with ERROR_NO_MORE_FILES, we may have + determined that we need to return fake '.' and/or '..' entries. */ + if (return_dot_dir) + { + if (!(dir->__d_u.__d_data.__dotdir_flags & __DIRENT_DOTDIR_SEEN_DOT)) + { + strcpy(dir->__d_dirent->d_name, "."); + syscall_printf ("[doshea] readdir: faking '.'"); + dir->__d_u.__d_data.__dotdir_flags |= __DIRENT_DOTDIR_SEEN_DOT; + } + else + { + strcpy(dir->__d_dirent->d_name, ".."); + syscall_printf ("[doshea] readdir: faking '..'"); + dir->__d_u.__d_data.__dotdir_flags |= __DIRENT_DOTDIR_SEEN_DOTDOT; + } + syscall_printf ("%p = readdir (%p) (*FAKE*)", + &dir->__d_dirent, dir); - /* Check for Windows shortcut. If it's a Cygwin or U/WIN - symlink, drop the .lnk suffix. */ - if (buf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) - { - char *c = dir->__d_dirent->d_name; - int len = strlen (c); - if (strcasematch (c + len - 4, ".lnk")) - { - char fbuf[MAX_PATH + 1]; - strcpy (fbuf, dir->__d_dirname); - strcpy (fbuf + strlen (fbuf) - 1, dir->__d_dirent->d_name); - path_conv fpath (fbuf, PC_SYM_NOFOLLOW); - if (fpath.issymlink ()) - c[len - 4] = '\0'; - } } - + else + { + syscall_printf("[doshea] readdir: we allegedly have a valid 'buf'"); + /* We get here if `buf' contains valid data. */ + if (get_encoded ()) + (void) fnunmunge (dir->__d_dirent->d_name, buf.cFileName); + else + strcpy (dir->__d_dirent->d_name, buf.cFileName); + + /* Check for Windows shortcut. If it's a Cygwin or U/WIN + symlink, drop the .lnk suffix. */ + if (buf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + { + char *c = dir->__d_dirent->d_name; + int len = strlen (c); + if (strcasematch (c + len - 4, ".lnk")) + { + char fbuf[MAX_PATH + 1]; + strcpy (fbuf, dir->__d_dirname); + strcpy (fbuf + strlen (fbuf) - 1, dir->__d_dirent->d_name); + path_conv fpath (fbuf, PC_SYM_NOFOLLOW); + if (fpath.issymlink ()) + c[len - 4] = '\0'; + } + } + + /* Check for a directory, it might be '.' or '..' */ + if (buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + syscall_printf ("[doshea] readdir: it's a directory"); + char *c = dir->__d_dirent->d_name; + if (strcmp(c, ".") == 0) + { + syscall_printf ("[doshea] readdir: it's '.'"); + dir->__d_u.__d_data.__dotdir_flags |= __DIRENT_DOTDIR_SEEN_DOT; + } + else if (strcmp(c, "..") == 0) + { + syscall_printf ("[doshea] readdir: it's '..'"); + dir->__d_u.__d_data.__dotdir_flags |= __DIRENT_DOTDIR_SEEN_DOTDOT; + } + } + syscall_printf ("%p = readdir (%p) (%s)", + &dir->__d_dirent, dir, buf.cFileName); + } + dir->__d_position++; res = dir->__d_dirent; - syscall_printf ("%p = readdir (%p) (%s)", - &dir->__d_dirent, dir, buf.cFileName); return res; } <<< Thanks in advance, David ----- Original Message ----- From: "David O'Shea" To: "Cygwin List" Sent: Wednesday, September 10, 2003 9:31 AM Subject: Re: Cygwin doesn't show .. in all directories > Hi Larry, > > Yes, that's exactly the problem I was reporting (with FAT32 in my > case). I managed to get a 'cygwin-snapshot' to build so I guess > that's the first step in developing a fix. Now comes the hard part, > figuring out how to fix the problem! > > If/when I have diffs can I just post them to this mailing list? > > Regards, > David > > ----- Original Message ----- > From: "Larry Hall" > To: "David O'Shea" ; > Sent: Monday, September 08, 2003 12:43 PM > Subject: Re: Cygwin doesn't show .. in all directories > > > > I don't see it when I just mount to a directory (i.e. "ls -al > /usr/bin" > > shows "." and ".."). I do see it if I mount a drive and then > "ls -al" > > the newly mounted directory, regardless of the format (well NTFS or > FAT, > > don't know about FAT32). Looks to me like the problem occurs if the > > Win32 path contains the drive specification. But that's just the > result > > of some quick checking. > > > > > > HTH, > > > > Larry > > > > At 10:28 PM 9/7/2003, David O'Shea you wrote: > > >Hi all, > > > > > >I didn't see a response to this query. Can someone at least > confirm > > >that this appears to be a valid bug (just mount some directories > and > > >take a look I guess!)? Once that happens I can look at how to fix > it. > > >I had a quick look at the code a month ago and thought it would > > >probably be hard to fix but I guess a challenge would be good :) > > > > > >Regards, > > >David > > > > > >----- Original Message ----- > > >From: "David O'Shea" > > >To: > > >Sent: Sunday, August 10, 2003 5:26 PM > > >Subject: Cygwin doesn't show .. in all directories > > > > > > > > >> Hi all, > > >> > > >> Apologies if this is old news, but I couldn't find mention of it > in > > >> the FAQ or mailing list archives. > > >> > > >> I have my F: mounted at /backup under Cygwin. When I 'ls -al > > >/backup' > > >> there is no '.' or '..' entry in /backup, I guess because they > are > > >not > > >> there physically and hence not reported by Windows (FAT > filesystems > > >> never have a '.' or '..' in the root directory as far as I know). > > >On > > >> Linux, every directory, including the root directory '/', has a > '.' > > >> and '..' entry, so I guess for consistency they ought to be > there. > > >> > > >> This is an issue for me because in MToolsFM, which allows you to > > >> graphically browse your directories (plus browse directories via > > >> 'mtools'), you go up a directory by double-clicking on a '..' > entry > > >in > > >> the list of directory contents. I imagine that if MToolsFM was > > >hacked > > >> to show a '..' entry even if it didn't see one in the filesystem, > > >> things would work, since 'cd ..' works fine when I am in the > /backup > > >> directory (I guess Cygwin doesn't actually look for the directory > > >> entry '..', it just goes up a directory). > > >> > > >> Of course I don't know if it might be the case that applications > > >> shouldn't assume that all *nix-ish platforms have a directory > entry > > >> pointing to the parent directory. Either way, please let me > know! > > >> > > >> Thanks in advance, > > >> David > > >> > > > > > >-- > > >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/ > > > > > -- 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/