delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/08/18/14:38:50

Message-ID: <399D81BD.2DD855CA@softhome.net>
Date: Fri, 18 Aug 2000 20:34:37 +0200
From: Laurynas Biveinis <lauras AT softhome DOT net>
X-Mailer: Mozilla 4.74 [en] (Win98; U)
X-Accept-Language: lt,en
MIME-Version: 1.0
To: DJGPP Workers <djgpp-workers AT delorie DOT com>
Subject: Patch: fstat()
Reply-To: djgpp-workers AT delorie DOT com

Updated to honor symlinks, testsuite added.
I'm not sure how wc204.txi entry should look for it, or 
is it required at all, because we will end up with a
looong list of function which support symlinks now.

Laurynas

Index: djgpp/src/libc/posix/sys/stat/fstat.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/fstat.c,v
retrieving revision 1.3
diff -u -r1.3 fstat.c
--- fstat.c	1998/06/28 22:20:00	1.3
+++ fstat.c	2000/08/18 18:35:56
@@ -1,3 +1,4 @@
+/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
@@ -97,6 +98,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
+#include <io.h>
 #include <time.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -107,6 +109,7 @@
 #include <go32.h>
 #include <libc/farptrgs.h>
 #include <libc/bss.h>
+#include <libc/symlink.h>
 #include <sys/fsext.h>
 #include "xstat.h"
 
@@ -381,6 +384,7 @@
   long           sft_fsize;
   unsigned short trusted_ftime = 0, trusted_fdate = 0;
   long           trusted_fsize = 0;
+  int            is_link = 0;
 
   if ((dev_info = _get_dev_info(fhandle)) == -1)
     return -1;	/* errno set by _get_dev_info() */
@@ -591,20 +595,38 @@
                   *dst-- = *src--;
 
               /* Build Unix-style file permission bits. */
-              if ( !(sft_buf[fattr_ofs] & 0x07) ) /* no R, S or H bits set */
-                stat_buf->st_mode |= WRITE_ACCESS;
-
-              /* Execute permission bits.  fstat() cannot be called on
-               * directories under DOS, so only executable programs/batch
-               * files should be considered.
+              /* Check for symlink at first.  This test will fail if we 
+               * don't have read access to file.
                */
-              if (_is_executable((const char *)0, fhandle, sft_extension))
-                stat_buf->st_mode |= EXEC_ACCESS;
-
-              /* DOS 4.x and above seems to know about named pipes. */
-              if (dos_major > 3 && (sft_buf[6] & 0x20))
-                stat_buf->st_mode |= S_IFIFO;
-
+              if (sft_fsize == 510)
+              {
+                 int old_errno = errno;
+		 char buf[2];
+		 int bytes_read = __internal_readlink(NULL, fhandle, buf, 1);
+		 if (bytes_read != -1)
+		 {
+		    stat_buf->st_mode = S_IFLNK;
+		    is_link = 1;
+		 }
+		 else
+ 		    errno = old_errno;
+              }
+              if (!is_link)
+              {
+                 if ( !(sft_buf[fattr_ofs] & 0x07) ) /* no R, S or H bits set */
+                   stat_buf->st_mode |= WRITE_ACCESS;
+
+                 /* Execute permission bits.  fstat() cannot be called on
+                  * directories under DOS, so only executable programs/batch
+                  * files should be considered.
+                  */
+                 if (_is_executable((const char *)0, fhandle, sft_extension))
+                   stat_buf->st_mode |= EXEC_ACCESS;
+
+                 /* DOS 4.x and above seems to know about named pipes. */
+                 if (dos_major > 3 && (sft_buf[6] & 0x20))
+                   stat_buf->st_mode |= S_IFIFO;
+              }
               /* Device code. */
               stat_buf->st_dev = drv_no;
 #ifdef  HAVE_ST_RDEV
@@ -773,36 +795,51 @@
               _djstat_fail_bits |= _STFAIL_HASH;
               stat_buf->st_ino = _invent_inode("", dos_ftime, trusted_fsize);
             }
-
-          /* Return the minimum access bits every file has under DOS. */
-          stat_buf->st_mode |= (S_IFREG | READ_ACCESS);
-          if (_djstat_flags & _STAT_ACCESS)
-            _djstat_fail_bits |= _STFAIL_WRITEBIT;
-
-	  /* If we run on Windows 9X, and LFN is enabled, try harder.
-	     Note that we deliberately do NOT use this call when LFN is
-	     disabled, even if we are on Windows 9X, because then we
-	     open the file with function 3Ch, and such handles aren't
-	     supported by 71A6h call we use here.  */
-	  if (dos_major >= 7 && _USE_LFN)
-	    {
-	      __dpmi_regs r;
-
-	      r.x.ax = 0x71a6;	/* file info by handle */
-	      r.x.bx = fhandle;
-	      r.x.ds = __tb >> 4;
-	      r.x.dx = 0;
-	      __dpmi_int(0x21, &r);
-	      if ((r.x.flags & 1) == 0
-		  && (_farpeekl(dos_mem_base, __tb) & 0x07) == 0)
-		stat_buf->st_mode |= WRITE_ACCESS; /* no R, S or H bits set */
-	    }
-
-          /* Executables are detected if they have magic numbers.  */
-          if ( (_djstat_flags & _STAT_EXEC_MAGIC) == 0 &&
-               _is_executable((const char *)0, fhandle, (const char *)0))
-            stat_buf->st_mode |= EXEC_ACCESS;
 
+          if (trusted_fsize == 510)
+          {
+             int old_errno = errno;
+             char buf[2];
+             int bytes_read = __internal_readlink(NULL, fhandle, buf, 1);
+             if (bytes_read != -1)
+             {
+                stat_buf->st_mode = S_IFLNK;
+                is_link = 1;
+             }
+             else
+                errno = old_errno;
+          }
+          if (!is_link)
+          {
+              /* Return the minimum access bits every file has under DOS. */
+              stat_buf->st_mode |= (S_IFREG | READ_ACCESS);
+              if (_djstat_flags & _STAT_ACCESS)
+                _djstat_fail_bits |= _STFAIL_WRITEBIT;
+    
+              /* If we run on Windows 9X, and LFN is enabled, try harder.
+                 Note that we deliberately do NOT use this call when LFN is
+                 disabled, even if we are on Windows 9X, because then we
+                 open the file with function 3Ch, and such handles aren't
+                 supported by 71A6h call we use here.  */
+              if (dos_major >= 7 && _USE_LFN)
+                {
+                  __dpmi_regs r;
+    
+                  r.x.ax = 0x71a6;	/* file info by handle */
+                  r.x.bx = fhandle;
+                  r.x.ds = __tb >> 4;
+                  r.x.dx = 0;
+    	          __dpmi_int(0x21, &r);
+    	          if ((r.x.flags & 1) == 0
+    		       && (_farpeekl(dos_mem_base, __tb) & 0x07) == 0)
+    		  stat_buf->st_mode |= WRITE_ACCESS; /* no R, S or H bits set */
+    	        }
+    
+              /* Executables are detected if they have magic numbers.  */
+              if ( (_djstat_flags & _STAT_EXEC_MAGIC) == 0 &&
+                _is_executable((const char *)0, fhandle, (const char *)0))
+                stat_buf->st_mode |= EXEC_ACCESS;
+          }
           /* Lower 6 bits of IOCTL return value give the device number. */
           stat_buf->st_dev = dev_info & 0x3f;
 #ifdef  HAVE_ST_RDEV
@@ -933,3 +970,4 @@
 }
 
 #endif  /* TEST */
+
Index: djgpp/src/libc/posix/sys/stat/fstat.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/fstat.txh,v
retrieving revision 1.4
diff -u -r1.4 fstat.txh
--- fstat.txh	1999/10/04 09:12:55	1.4
+++ fstat.txh	2000/08/18 18:35:57
@@ -39,10 +39,11 @@
 
 @subheading Bugs
 
-If a file was open in write-only mode, its execute mode bits might be
-incorrectly reported as if the file were non-executable.  This is
-because some executables are only recognized by reading their first
-two bytes, which cannot be done for files open in write-only mode.
+If a file was open in write-only mode, its execute and symlink mode 
+bits might be incorrectly reported as if the file were non-executable
+or non-symlink.  This is because executables and symlinks are only 
+recognized by reading their first few bytes, which cannot be done for 
+files open in write-only mode.
 
 For @code{fstat} to return correct info, you should make sure that all
 the data written to the file has been delivered to the operating system,
Index: djgpp/tests/libc/posix/sys/stat/fstat.c
===================================================================
RCS file: fstat.c
diff -N fstat.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ fstat.c	Fri Aug 18 14:36:01 2000
@@ -0,0 +1,72 @@
+/* Testsuite for fstat()                                                
+ * TODO: only symlink handlink aspect is tested. Other things should be 
+ * tested too.                                                          
+ * Currently there are following tests:         
+ *   1. Opens simple file, positions somewhere, checks for symlinks, checks
+ * file position.
+ *   2. The same as above with symlinks
+ */
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main(void)
+{
+   int fd = open("fstat.c", O_RDONLY);
+   off_t file_pos;
+   struct stat st;
+   if (fd < 0)
+   {
+      perror("Failed to open fstat.c ");
+      return 1;
+   }
+   lseek(fd, 65, SEEK_SET);
+   file_pos = tell(fd);
+   if (fstat(fd, &st))
+   {
+      perror("Failed to stat fstat.c ");
+      return 1;
+   }
+   if (S_ISLNK(st.st_mode))
+   {
+      fprintf(stderr, "Test 1 failed - S_IFLNK bit should not be set\n");
+      return 1;
+   }
+   if (file_pos != tell(fd))
+   {
+      fprintf(stderr, "Test 1 failed - file position changed\n");
+      return 1;
+   }
+   printf("Test 1 passed\n");
+   close(fd);
+   symlink("fstat.c", "linkst");
+   fd = open("linkst", O_RDONLY | O_NOLINK);
+   if (fd < 0)
+   {
+      perror("Failed to open link to fstat.c ");
+      return 1;
+   }
+   lseek(fd, 56, SEEK_SET);
+   file_pos = tell(fd);
+   if (fstat(fd, &st))
+   {
+      perror("Failed to stat link to fstat.c ");
+      return 1;
+   }
+   if (!S_ISLNK(st.st_mode))
+   {
+      fprintf(stderr, "Test 2 failed - S_IFLNK bit should be set\n");
+      return 1;
+   }
+   if (file_pos != tell(fd))
+   {
+      fprintf(stderr, "Test 2 failed - file position changed\n");
+      return 1;
+   }
+   printf("Test 2 passed\n");
+   close(fd);
+   remove("linkst");
+   return 0;
+}
\ No newline at end of file
Index: djgpp/tests/libc/posix/sys/stat/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/posix/sys/stat/makefile,v
retrieving revision 1.2
diff -u -r1.2 makefile
--- makefile	2000/08/15 17:38:41	1.2
+++ makefile	2000/08/18 18:36:01
@@ -1,6 +1,7 @@
 TOP=../../..
 
 SRC += fixpath.c
+SRC += fstat.c
 SRC += leak.c
 SRC += lstat.c
 SRC += mkdir.c

- Raw text -


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