delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/11/18/16:52:57

Sender: rich AT phekda DOT freeserve DOT co DOT uk
Message-ID: <3BF82D64.84C50E28@phekda.freeserve.co.uk>
Date: Sun, 18 Nov 2001 21:51:32 +0000
From: Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.19 i586)
X-Accept-Language: de,fr
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: RESEND: Patch to computer st_blksize in struct stat
References: <Pine DOT SUN DOT 3 DOT 91 DOT 1011111152354 DOT 6498A-100000 AT is>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Eli Zaretskii wrote:
[snip]
>   2) I'm a bit worried by the possible slow-down, due to the call to
>      statfs.  Could you compare the old and the new versions, at least
>      on hard disks, floppies, and CDs?

Using gprof on src/libc/sys/stat/*stat.c I managed to get the following
information. Here is the time spent in __dpmi_int() for running the
fstat.c test on a file with the new block size support in *stat():

HD, CD-ROM drives: 0s (probably too short to measure)
Floppy drive:      0.11s
Network drive:     0.06s

In all cases the current code in CVS takes 0s on my machine (Athlon
850MHz) for the same files.

I've added code to return 512 bytes as the block size for A:, B:. I've
also defaulted the block size to 32K for remote drives. If you don't think
0.06s is much overhead, then I can remove the hard-coded size for remote
drives.

Anyhow, please find below a new version of the patch. Thanks to Eli &
Charles for their helpful comments.

Also I just noticed that _STAT_* are defined in include/sys/stat.h, but
src/libc/posix/sys/stat/xstat.c does not use the definitions from
sys/stat.h. Shouldn't xstat.c include sys/stat.h, to get common
definitions for _STAT_*?

BTW there seems to be some cruft in include/dos.h - should this be
removed?

    /* int _get_default_drive(void);
    void _fixpath(const char *, char *); */

Thanks, bye, Rich =]

-- 
Richard Dawe
http://www.phekda.freeserve.co.uk/richdawe/

Index: include/sys/types.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/sys/types.h,v
retrieving revision 1.6
diff -p -u -3 -r1.6 types.h
--- include/sys/types.h 2000/12/05 14:05:53     1.6
+++ include/sys/types.h 2001/11/18 21:46:36
@@ -13,7 +13,9 @@ extern "C" {
 #ifndef __STRICT_ANSI__
 
 #include <sys/djtypes.h>
-  
+
+typedef int             blkcnt_t;
+typedef int             blksize_t;
 typedef int            dev_t;
 typedef int            ino_t;
 typedef int            mode_t;
Index: include/sys/stat.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/sys/stat.h,v
retrieving revision 1.4
diff -p -u -3 -r1.4 stat.h
--- include/sys/stat.h  2000/12/05 14:05:53     1.4
+++ include/sys/stat.h  2001/11/18 21:46:42
@@ -49,9 +49,9 @@ struct stat {
   time_t       st_mtime;
   nlink_t      st_nlink;
   off_t                st_size;
-  off_t                st_blksize;
+  blksize_t    st_blksize;
   uid_t                st_uid;
-  dev_t                st_rdev; /* unused */
+  dev_t                st_rdev;
 };
 
 int    chmod(const char *_path, mode_t _mode);
Index: include/libc/fd_props.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/libc/fd_props.h,v
retrieving revision 1.6
diff -p -u -3 -r1.6 fd_props.h
--- include/libc/fd_props.h     2001/06/06 21:09:50     1.6
+++ include/libc/fd_props.h     2001/11/18 21:47:01
@@ -8,6 +8,8 @@ extern "C" {
 
 #ifndef __dj_ENFORCE_ANSI_FREESTANDING
 
+#include <string.h>
+
 #ifndef __STRICT_ANSI__
 
 #ifndef _POSIX_SOURCE
@@ -63,6 +65,11 @@ static __inline__ void __clear_fd_flags(
 static __inline__ unsigned long __get_fd_flags(int _fd)
 {
   return __has_fd_properties(_fd) ? __fd_properties[_fd]->flags : 0;
+}
+
+static __inline__ const char * __get_fd_name(int _fd)
+{
+  return __has_fd_properties(_fd) ? __fd_properties[_fd]->filename :
NULL;
 }
 
 #endif /* !_POSIX_SOURCE */
Index: src/libc/posix/sys/stat/fstat.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/fstat.c,v
retrieving revision 1.7
diff -p -u -3 -r1.7 fstat.c
--- src/libc/posix/sys/stat/fstat.c     2001/09/25 01:00:52     1.7
+++ src/libc/posix/sys/stat/fstat.c     2001/11/18 21:47:24
@@ -106,6 +106,8 @@
 #include <dos.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <limits.h>
+#include <libc/fd_props.h>
 
 #include <dpmi.h>
 #include <go32.h>
@@ -434,7 +436,21 @@ fstat_assist(int fhandle, struct stat *s
   stat_buf->st_gid = getgid();
   stat_buf->st_nlink = 1;
 #ifndef  NO_ST_BLKSIZE
-  stat_buf->st_blksize = _go32_info_block.size_of_transfer_buffer;
+  if (__get_fd_name(fhandle))
+    {
+      const char *filename;
+      char fixed_filename[PATH_MAX + 1];
+
+      filename = __get_fd_name(fhandle);
+      _fixpath(filename, fixed_filename);
+      stat_buf->st_blksize = _get_cached_blksize(fixed_filename);
+    }
+  else
+    {
+      /* Fall back on transfer buffer size, if we can't determine file
name
+       * (which gives the drive letter and then the drive's cluster
size). */
+      stat_buf->st_blksize = _go32_info_block.size_of_transfer_buffer;
+    }
 #endif
 
   /* If SFT entry for our handle is required and available, we will use
it.  */
@@ -936,6 +952,9 @@ int main(int argc, char *argv[])
       _djstat_describe_lossage(stderr);
     }
 
+  if (!argc)
+    return EXIT_SUCCESS;
+
   /* Now call fstat() for each command-line argument. */
   while (++argv, --argc)
     {
@@ -956,6 +975,8 @@ int main(int argc, char *argv[])
          fprintf (stderr, "\t\t\tTimes: %lu %lu\n",
                   (unsigned long)stat_buf.st_atime,
                   (unsigned long)stat_buf.st_ctime);
+         fprintf(stderr, "\t\t\tBlock size: %d\n",
+                 stat_buf.st_blksize);
           _djstat_describe_lossage(stderr);
         }
       else
@@ -965,7 +986,7 @@ int main(int argc, char *argv[])
           _djstat_describe_lossage(stderr);
         }
     }
-  return 0;
+  return EXIT_SUCCESS;
 }
 
 #endif  /* TEST */
Index: src/libc/posix/sys/stat/lstat.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/lstat.c,v
retrieving revision 1.7
diff -p -u -3 -r1.7 lstat.c
--- src/libc/posix/sys/stat/lstat.c     2001/10/17 05:08:39     1.7
+++ src/libc/posix/sys/stat/lstat.c     2001/11/18 21:47:38
@@ -445,7 +445,7 @@ stat_assist(const char *path, struct sta
   statbuf->st_gid     = getgid();
   statbuf->st_nlink   = 1;
 #ifndef  NO_ST_BLKSIZE
-  statbuf->st_blksize = _go32_info_block.size_of_transfer_buffer;
+  statbuf->st_blksize = _get_cached_blksize(path);
 #endif
 
   /* Make the path explicit.  This makes the rest of our job much
@@ -932,9 +932,11 @@ lstat(const char *path, struct stat *sta
 
 #ifdef  TEST
 
+#include <stdlib.h>
+
 unsigned short _djstat_flags = 0;
 
-void
+int
 main(int argc, char *argv[])
 {
   struct stat stat_buf;
@@ -943,7 +945,7 @@ main(int argc, char *argv[])
   if (argc < 2)
     {
       fprintf (stderr, "Usage: %s <_djstat_flags> <file...>\n", argv[0]);
-      exit(0);
+      return (EXIT_FAILURE);
     }
 
   if (lstat(*argv, &stat_buf) != 0)
@@ -968,6 +970,8 @@ main(int argc, char *argv[])
                   (long)stat_buf.st_size,
                   (unsigned long)stat_buf.st_mtime,
                   ctime(&stat_buf.st_mtime));
+         fprintf(stderr, "\t\t\tBlock size: %d\n",
+                 stat_buf.st_blksize);
           _djstat_describe_lossage(stderr);
         }
       else
@@ -980,7 +984,7 @@ main(int argc, char *argv[])
       ++argv;
     }
 
-    exit (0);
+    return (EXIT_SUCCESS);
 }
 
 #endif
Index: src/libc/posix/sys/stat/xstat.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/xstat.c,v
retrieving revision 1.3
diff -p -u -3 -r1.3 xstat.c
--- src/libc/posix/sys/stat/xstat.c     2000/08/05 16:53:46     1.3
+++ src/libc/posix/sys/stat/xstat.c     2001/11/18 21:47:59
@@ -19,6 +19,7 @@
 #include <limits.h>
 #include <time.h>
 #include <errno.h>
+#include <sys/vfs.h>
 #include <dos.h>
 #include <dpmi.h>
 #include <libc/farptrgs.h>
@@ -116,6 +117,76 @@ _getftime(int fhandle, unsigned int *dos
   *dos_ftime = ((unsigned int)regs.x.dx << 16) + (unsigned int)regs.x.cx;
 
   return 0;
+}
+
+/* Cache the cluster size (aka block size) for each drive letter, so we
can
+ * populate the st_blksize of struct stat easily. The cluster size is
+ * measured in bytes.
+ *
+ * ASSUMPTION: path has already been fixed by `_fixpath'.
+ */
+
+/* Comment copied from DJGPP 2.03's src/libc/compat/mntent/mntent.c:
+ *
+ * There may be a maximum of 32 block devices.  Novell Netware indeed
+ * allows for 32 disks (A-Z plus 6 more characters from '[' to '\'')
+ */
+static blksize_t cache_blksize[32];
+static int cache_blksize_count = -1;
+
+blksize_t
+_get_cached_blksize (const char *path)
+{
+  struct statfs sbuf;
+  int           d; /* index into drive cache = drive_num - 1 */  
+  static int    overmax_d = sizeof(cache_blksize) /
sizeof(cache_blksize[0]);
+
+  /* Force initialization in restarted programs (emacs).  */
+  if (cache_blksize_count != __bss_count)
+    {
+      cache_blksize_count = __bss_count;
+      memset(cache_blksize, 0, sizeof(cache_blksize));
+
+      /* Default floppy drives to 512B block size. */
+      cache_blksize[0] = cache_blksize[1] = 512;
+    }
+
+  /* Get the drive number. The fixed filename will begin with a lowercase
+   * letter or a symbol. The symbols for drives > 'z:' occur straight
+   * after 'Z' in ASCII.
+   */
+  if ((path[0] >= 'a') && (path[0] <= 'z'))
+    d = path[0] - 'a';
+  else
+    d = path[0] - 'A';
+
+  if ((d < 0) || (d >= overmax_d))
+    {
+      errno = ENODEV;
+      return -1;
+    }
+
+  if (!cache_blksize[d])
+    {
+      if (_is_remote_drive(d + 1))
+       {
+         /* Default remote drives to 32K block size. */
+         cache_blksize[d] = 32768;
+       }
+      else
+       {
+         /* No entry => retrieve cluster size */
+         if (statfs(path, &sbuf) != 0)
+           {
+             /* Failed, pass error through */
+             return -1;
+           }
+
+         cache_blksize[d] = sbuf.f_bsize;
+       }
+    }
+
+  return cache_blksize[d];
 }
 
 /* Invent an inode number for those files which don't have valid DOS
Index: src/libc/posix/sys/stat/stat.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/stat.c,v
retrieving revision 1.10
diff -p -u -3 -r1.10 stat.c
--- src/libc/posix/sys/stat/stat.c      2000/08/22 18:45:07     1.10
+++ src/libc/posix/sys/stat/stat.c      2001/11/18 21:48:06
@@ -31,9 +31,11 @@ stat(const char *path, struct stat *stat
 
 #ifdef  TEST
 
+#include <stdlib.h>
+
 unsigned short _djstat_flags = 0;
 
-void
+int
 main(int argc, char *argv[])
 {
   struct stat stat_buf;
@@ -42,7 +44,7 @@ main(int argc, char *argv[])
   if (argc < 2)
     {
       fprintf (stderr, "Usage: %s <_djstat_flags> <file...>\n", argv[0]);
-      exit(0);
+      return (EXIT_FAILURE);
     }
 
   if (stat(*argv, &stat_buf) != 0)
@@ -67,6 +69,8 @@ main(int argc, char *argv[])
                   (long)stat_buf.st_size,
                   (unsigned long)stat_buf.st_mtime,
                   ctime(&stat_buf.st_mtime));
+         fprintf(stderr, "\t\t\tBlock size: %d\n",
+                 stat_buf.st_blksize);
           _djstat_describe_lossage(stderr);
         }
       else
@@ -79,7 +83,7 @@ main(int argc, char *argv[])
       ++argv;
     }
 
-    exit (0);
+    return (EXIT_SUCCESS);
 }
 
 #endif
Index: src/libc/posix/sys/stat/xstat.h
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/xstat.h,v
retrieving revision 1.4
diff -p -u -3 -r1.4 xstat.h
--- src/libc/posix/sys/stat/xstat.h     2000/08/05 16:53:46     1.4
+++ src/libc/posix/sys/stat/xstat.h     2001/11/18 21:48:14
@@ -68,5 +68,6 @@ extern long             __filelength(int
 extern int              _is_remote_handle(int);
 extern void             _djstat_describe_lossage(FILE *);
 extern int              _getftime(int, unsigned int *);
+extern blksize_t        _get_cached_blksize (const char *path);
 
 #endif  /* __XSTAT_H */
Index: src/libc/posix/sys/stat/lstat.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/lstat.txh,v
retrieving revision 1.3
diff -p -u -3 -r1.3 lstat.txh
--- src/libc/posix/sys/stat/lstat.txh   2001/08/01 10:31:02     1.3
+++ src/libc/posix/sys/stat/lstat.txh   2001/11/18 21:48:25
@@ -14,17 +14,18 @@ it in @var{sbuf}, which has this structu
 
 @smallexample
 struct  stat @{
-        time_t   st_atime;     /* time of last access       */
-        time_t   st_ctime;     /* time of file's creation   */
-        dev_t    st_dev;       /* The drive number (0 = a:) */
-        gid_t    st_gid;       /* what getgid() returns */
-        ino_t    st_ino;       /* starting cluster or unique identifier
*/
-        mode_t   st_mode;      /* file mode - S_IF* and S_IRUSR/S_IWUSR
*/
-        time_t   st_mtime;     /* time that the file was last written */
-        nlink_t  st_nlink;     /* 2 + number of subdirs, or 1 for files
*/
-        off_t    st_size;      /* size of file in bytes */
-        off_t    st_blksize;   /* the size of transfer buffer */
-        uid_t    st_uid;       /* what getuid() returns */
+        time_t    st_atime;     /* time of last access       */
+        time_t    st_ctime;     /* time of file's creation   */
+        dev_t     st_dev;       /* The drive number (0 = a:) */
+        gid_t     st_gid;       /* what getgid() returns */
+        ino_t     st_ino;       /* starting cluster or unique identifier
*/
+        mode_t    st_mode;      /* file mode - S_IF* and S_IRUSR/S_IWUSR
*/
+        time_t    st_mtime;     /* time that the file was last written */
+        nlink_t   st_nlink;     /* 2 + number of subdirs, or 1 for files
*/
+        off_t     st_size;      /* size of file in bytes */
+       blksize_t st_blksize;   /* block size in bytes*/
+        uid_t     st_uid;       /* what getuid() returns */
+       dev_t     st_rdev;      /* The drive number (0 = a:) */
 @};
 @end smallexample
 
Index: src/libc/posix/sys/stat/stat.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/stat.txh,v
retrieving revision 1.8
diff -p -u -3 -r1.8 stat.txh
--- src/libc/posix/sys/stat/stat.txh    2001/08/01 10:31:02     1.8
+++ src/libc/posix/sys/stat/stat.txh    2001/11/18 21:48:30
@@ -14,17 +14,18 @@ it in @var{sbuf}, which has this structu
 
 @smallexample
 struct  stat @{
-        time_t   st_atime;     /* time of last access       */
-        time_t   st_ctime;     /* time of file's creation   */
-        dev_t    st_dev;       /* The drive number (0 = a:) */
-        gid_t    st_gid;       /* what getgid() returns */
-        ino_t    st_ino;       /* starting cluster or unique identifier
*/
-        mode_t   st_mode;      /* file mode - S_IF* and S_IRUSR/S_IWUSR
*/
-        time_t   st_mtime;     /* time that the file was last written */
-        nlink_t  st_nlink;     /* 2 + number of subdirs, or 1 for files
*/
-        off_t    st_size;      /* size of file in bytes */
-        off_t    st_blksize;   /* the size of transfer buffer */
-        uid_t    st_uid;       /* what getuid() returns */
+        time_t    st_atime;     /* time of last access       */
+        time_t    st_ctime;     /* time of file's creation   */
+        dev_t     st_dev;       /* The drive number (0 = a:) */
+        gid_t     st_gid;       /* what getgid() returns */
+        ino_t     st_ino;       /* starting cluster or unique identifier
*/
+        mode_t    st_mode;      /* file mode - S_IF* and S_IRUSR/S_IWUSR
*/
+        time_t    st_mtime;     /* time that the file was last written */
+        nlink_t   st_nlink;     /* 2 + number of subdirs, or 1 for files
*/
+        off_t     st_size;      /* size of file in bytes */
+        blksize_t st_blksize;   /* block size in bytes*/
+        uid_t     st_uid;       /* what getuid() returns */
+       dev_t     st_rdev;      /* The drive number (0 = a:) */
 @};
 @end smallexample
 
Index: src/docs/kb/develop.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/develop.txi,v
retrieving revision 1.6
diff -p -u -3 -r1.6 develop.txi
--- src/docs/kb/develop.txi     2001/11/02 18:48:50     1.6
+++ src/docs/kb/develop.txi     2001/11/18 21:48:36
@@ -77,6 +77,13 @@ functions, it should include @file{libc/
 @sc{gs} register instead of @sc{fs}, to avoid clobbering @sc{fs} which
 might be used by the application.
 
+@subsection Filename manipulation
+
+When manipulating filenames, don't use the ctype functions from
+@file{ctype.h}, because they are locale sensitive.  For example,
+instead of using @code{tolower} (@pxref{tolower, , tolower, libc}),
+convert the case with explicit code.
+
 @subsection Assertions
 @cindex Assertions
 
Index: src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.100
diff -p -u -3 -r1.100 wc204.txi
--- src/docs/kb/wc204.txi       2001/10/17 05:19:49     1.100
+++ src/docs/kb/wc204.txi       2001/11/18 21:48:47
@@ -675,3 +675,10 @@ case lowering.  This replaces the functi
 which is hopelessly buggy on Windows 2000 and XP.  New function used in
 @file{srchpath.c}, @file{readdir.c}, @file{glob.c}, @file{fixpath.c},
 @file{lstat.c} and @file{getcwd.c}.
+
+@findex stat AT r{, and block size}
+@findex lstat AT r{, and block size}
+@findex fstat AT r{, and block size}
+The functions @code{stat}, @code{lstat} and @code{fstat} now fill
+the @code{st_blksize} member of @code{struct stat} with the correct block
+size for the device where the file is located.

- Raw text -


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