delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/05/22/11:32:41

Date: Tue, 22 May 2001 18:24:03 +0300
From: "Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il>
Sender: halo1 AT zahav DOT net DOT il
To: djgpp-workers AT delorie DOT com
Message-Id: <1659-Tue22May2001182402+0300-eliz@is.elta.co.il>
X-Mailer: Emacs 20.6 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.9
Subject: Add d_type member to struct dirent
Reply-To: djgpp-workers AT delorie DOT com

Please see if the changes below look good.  Fileutils 4.1 looks for
this feature and if it is available, `ls' runs much faster (or so we
are told in NEWS).  Perhaps someone who have Fileutils 4.1 on their
disk could actually test this (I didn't have time).

The diffs are against stock v2.03, so you might need to tweak them a
bit for the CVS.  They do mean to support symlinks, though, so please
see if the design decision I made in that respect makes sense.

Thanks in advance for any comments.

Btw, Richard, is it perhaps a good idea to retrofit your changes to
Filutils to v4.1?  If the changes between 4.0 and 4.1 are not large,
this will gain us the latest version, when the testing is finished.

--- src/libc/posix/dirent/readdir.c~0	Sun Nov 15 08:47:22 1998
+++ src/libc/posix/dirent/readdir.c	Tue May 22 09:33:12 2001
@@ -26,6 +26,10 @@ readdir(DIR *dir)
     else
       strcpy(dir->de.d_name, "..");
     dir->de.d_namlen = strlen(dir->de.d_name);
+    if ((__opendir_flags & __OPENDIR_NO_D_TYPE) == 0)
+      dir->de.d_type = DT_DIR;
+    else
+      dir->de.d_type = DT_UNKNOWN;
     return &(dir->de);
   }
 
@@ -71,6 +75,27 @@ readdir(DIR *dir)
   }
   strcpy(dir->de.d_name, dir->ff.ff_name);
   dir->de.d_namlen = strlen(dir->de.d_name);
+  if ((__opendir_flags & __OPENDIR_NO_D_TYPE) == 0)
+    {
+      unsigned char attrib = dir->ff.ff_attrib;
+
+      if ((attrib & FA_DIREC) == FA_DIREC)
+	dir->de.d_type = DT_DIR;
+      else if ((attrib & FA_LABEL) == FA_LABEL)
+	dir->de.d_type = DT_LABEL;
+      else if ((attrib & 0x40) == 0x40)
+	dir->de.d_type = DT_CHR;
+      else if (dir->ff.ff_fsize == 510)
+	/* This could or could not be a symlink.  Since we don't want
+	   to pay the price of finding out, we return DT_UNKNOWN, and
+	   the application is supposed to stat the file in response.  */
+	dir->de.d_type = DT_UNKNOWN;
+      /* FIXME: anything else DOS can return? */
+      else
+	dir->de.d_type = DT_REG;
+    }
+  else
+    dir->de.d_type = DT_UNKNOWN;
   return &dir->de;
 }
 
--- src/libc/posix/dirent/readdir.t~0	Sun Nov 15 08:47:22 1998
+++ src/libc/posix/dirent/readdir.txh	Tue May 22 09:46:22 2001
@@ -17,6 +17,7 @@ this format:
 struct dirent @{
   unsigned short d_namlen;  /* The length of the name (like strlen) */
   char d_name[MAXNAMLEN+1]; /* The name */
+  mode_t d_type;            /* The file's type */
 @};
 @end example
 
@@ -24,6 +25,38 @@ Note that some directory entries might b
 depending on the bits set in the global variable
 @code{__opendir_flags}.  @xref{opendir, __opendir_flags, opendir}.
 
+The possible values of the @code{d_type} member are:
+
+@table @code
+@item DT_REG
+This is a regular file.
+@item DT_BLK
+The file is a block device.
+@item DT_CHR
+The file is a character device.
+@item DT_DIR
+The file is a directory.
+@item DT_FIFO
+This is a pipe (never happens in DJGPP).
+@item DT_LABEL
+The file is a volume label.
+@item DT_LNK
+The file is a symlink.
+@item DT_SOCK
+The file is a socket.
+@item DT_UNKNOWN
+The file's type is unknown.  This value is put into the @code{d_type}
+member if the exact file's type is too expensive to compute (one notable
+case is when the file could be a symlink).  If the
+@code{__OPENDIR_NO_D_TYPE} flag is set in the global variable
+@code{__opendir_flags}, @emph{all} files get marked with
+@code{DT_UNKNOWN}.
+@end table
+
+The macro @code{DTTOIF} (@pxref{DTTOIF}) can be used to convert the
+@code{d_type} member to the equivalent value of the @code{st_mode}
+member of @code{struct stat}, see @ref{stat}.
+
 @subheading Return Value
 
 A pointer to a static buffer that is overwritten with each call.
@@ -31,6 +64,7 @@ A pointer to a static buffer that is ove
 @subheading Portability
 
 @port-note posix The @code{__opendir_flags} variable is DJGPP-specific.
+@port-note posix The @code{d_type} member is an extension available on some systems such as GNU/Linux.
 @portability !ansi, posix
 
 @subheading Example
@@ -43,3 +77,32 @@ while (de = readdir(d))
 closedir(d);
 @end example
 
+@c -------------------------------------------------
+@node DTTOIF, file system
+@subheading Syntax
+
+@example
+#include <dirent.h>
+
+struct dirent *de;
+mode_t file_mode = DTTOIF(de->d_type)
+@end example
+
+@subheading Description
+
+This macro converts the @code{d_type} member of a @code{struct dirent}
+variable to an equivalent value of the @code{st_mode} member of a
+@code{struct stat} variable (@pxref{stat}).
+
+Note that the access rights are not set in the result returned by this
+macro.  Only the file-type information is copied.
+
+@subheading Return Value
+
+The file's mode bits are returned.  If the argument has the value
+@code{DT_UNKNOWN}, the result will be @code{S_IFREG}.
+
+@subheading Portability
+
+@port-note posix This macro is available on systems which support the @code{d_type} member in @code{struct dirent}.
+@portability !ansi, !posix
--- src/libc/posix/dirent/opendir.t~0	Sun Nov 15 08:47:22 1998
+++ src/libc/posix/dirent/opendir.txh	Tue May 22 09:50:20 2001
@@ -21,7 +21,6 @@ following values to control the operatio
 @table @code
 
 @item __OPENDIR_PRESERVE_CASE
-
 Do not change the case of files to lower case.  Just in case Micros*ft
 decides to support case-sensitive file systems some day.
 
@@ -32,20 +31,21 @@ other ways of achieving this and for mor
 automatic letter-case conversion by DJGPP library functions.
 
 @item __OPENDIR_NO_HIDDEN
-
 Do not include hidden files and directories in the search.  By default,
 all files and directories are included.
 
 @item __OPENDIR_FIND_HIDDEN
-
 Provided for back-compatibility with previous DJGPP versions, where
 hidden files and directories were by default skipped.  In versions 2.02
 and later, this flag has no effect.
 
 @item __OPENDIR_FIND_LABEL
-
 Include volume labels in the search.  By default, these are skipped.
 
+@item __OPENDIR_NO_D_TYPE
+Do not compute the @code{d_type} member of @code{struct dirent}.  If
+this flag is set, all files will get @code{DT_UNKNOWN} in the
+@code{d_type} member.  By default, this flag is reset.  @xref{readdir}.
 @end table
 
 You can simply put @samp{int __opendir_flags = ...;} in your code.  The
--- include/dirent.h~0	Sun Nov 15 08:48:38 1998
+++ include/dirent.h	Tue May 22 09:01:16 2001
@@ -10,14 +10,28 @@
 #ifndef __dj_ENFORCE_ANSI_FREESTANDING
 
 #ifndef __STRICT_ANSI__
+#include <sys/types.h>
 
 /* Definition of DIR requires many other headers; not included here to
    avoid namespace pollution. */
 typedef struct __dj_DIR DIR;
 
+#define DT_REG	    0x1
+#define DT_BLK	    0x2
+#define DT_CHR	    0x3
+#define DT_DIR	    0x4
+#define DT_FIFO	    0x5
+#define DT_LABEL    0x6
+#define DT_LNK	    0x7
+#define DT_SOCK	    0x8
+#define DT_UNKNOWN  0xf
+
+#define DTTOIF(dt)  ((dt) == DT_UNKNOWN ? 0 : (dt) - 1)
+
 struct dirent {
   char d_namlen;
   char d_name[256];
+  mode_t d_type;
 };
 
 int		closedir(DIR *dirp);
@@ -32,6 +46,7 @@
 #define __OPENDIR_FIND_HIDDEN	0002 /* ignored; on by default */
 #define __OPENDIR_FIND_LABEL	0004
 #define __OPENDIR_NO_HIDDEN	0x08 /* NOT 0002 for back-compatibility */
+#define __OPENDIR_NO_D_TYPE	0x10
 
 void seekdir(DIR *_dir, long _loc);
 long telldir(DIR *_dir);

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019