Mail Archives: djgpp-workers/2000/08/18/14:38:50
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 -