This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Cygwin doesn't show .. in all directories


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" <dcoshea@hotmail.com>
To: "Cygwin List" <cygwin@cygwin.com>
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" <cygwin-lh@cygwin.com>
> To: "David O'Shea" <dcoshea@hotmail.com>; <cygwin@cygwin.com>
> 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" <dcoshea@hotmail.com>
> > >To: <cygwin@cygwin.com>
> > >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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]