Message-ID: <3986F623.18444B8D@softhome.net> Date: Tue, 01 Aug 2000 18:09:07 +0200 From: Laurynas Biveinis X-Mailer: Mozilla 4.73 [en] (Win98; U) X-Accept-Language: lt,en MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Re: New function: lstat() References: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Reply-To: djgpp-workers AT delorie DOT com OK, here is reworked patch: - New stat.c is diffed against /dev/null - lstat.c is diffed against old stat.c - everything else has been left untouched. --- /dev/null Tue Aug 1 18:04:59 2000 +++ stat.c.new Sun Jul 30 21:22:52 2000 @@ -0,0 +1,80 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1999 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 */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +/* Main entry point. This is library stat() function. + Actual code has been moved to lstat() in lstat.c. + */ + +#include +#include +#include +#include + +#ifdef TEST +#include "xstat.h" +#endif + +int +stat(const char *path, struct stat *statbuf) +{ + return lstat(path, statbuf); +} + +#ifdef TEST + +unsigned short _djstat_flags = 0; + +void +main(int argc, char *argv[]) +{ + struct stat stat_buf; + char *endp; + + if (argc < 2) + { + fprintf (stderr, "Usage: %s <_djstat_flags> \n", argv[0]); + exit(0); + } + + if (stat(*argv, &stat_buf) != 0) + perror ("stat failed on argv[0]"); + else + fprintf(stderr, "DOS %d.%d (%s)\n", _osmajor, _osminor, _os_flavor); + argc--; argv++; + + _djstat_flags = (unsigned short)strtoul(*argv, &endp, 0); + argc--; argv++; + + while (argc--) + { + if (!stat(*argv, &stat_buf)) + { + fprintf(stderr, "%s: %d %6u %o %d %d %ld %lu %s", *argv, + stat_buf.st_dev, + (unsigned)stat_buf.st_ino, + stat_buf.st_mode, + stat_buf.st_nlink, + stat_buf.st_uid, + (long)stat_buf.st_size, + (unsigned long)stat_buf.st_mtime, + ctime(&stat_buf.st_mtime)); + _djstat_describe_lossage(stderr); + } + else + { + fprintf(stderr, "%s: lossage", *argv); + perror(" "); + _djstat_describe_lossage(stderr); + } + + ++argv; + } + + exit (0); +} + +#endif Index: stat/stat.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/stat.c,v retrieving revision 1.7 diff -u -r1.7 stat.c --- stat.c 1999/06/03 17:27:40 1.7 +++ stat.c 2000/08/01 16:03:28 @@ -1,15 +1,17 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1999 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 */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -/* This is file STAT.C */ +/* This is file LSTAT.C */ /* - * Almost a 100% U**X-compatible stat() substitute. + * Almost a 100% U**X-compatible stat()/lstat() substitute. * - * Usage: + * Note: * - * That's easy: put this into libc.a, then just call stat() as usual. + * The actual function implemented here is lstat(), not stat(). The + * stat() now is just a lstat() wrapper. * * Rationale: * @@ -851,11 +853,11 @@ return 0; } -/* Main entry point. This is library stat() function. +/* Main entry point. This is library lstat() function. */ int -stat(const char *path, struct stat *statbuf) +lstat(const char *path, struct stat *statbuf) { int e = errno; int pathlen, ret; @@ -911,8 +913,8 @@ exit(0); } - if (stat(*argv, &stat_buf) != 0) - perror ("stat failed on argv[0]"); + if (lstat(*argv, &stat_buf) != 0) + perror ("lstat failed on argv[0]"); else fprintf(stderr, "DOS %d.%d (%s)\n", _osmajor, _osminor, _os_flavor); argc--; argv++; @@ -922,7 +924,7 @@ while (argc--) { - if (!stat(*argv, &stat_buf)) + if (!lstat(*argv, &stat_buf)) { fprintf(stderr, "%s: %d %6u %o %d %d %ld %lu %s", *argv, stat_buf.st_dev, @@ -949,4 +951,3 @@ } #endif - Index: src/docs/kb/wc204.txi =================================================================== RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v retrieving revision 1.15 diff -u -r1.15 wc204.txi --- wc204.txi 2000/07/26 17:54:44 1.15 +++ wc204.txi 2000/07/30 19:53:31 @@ -84,7 +84,9 @@ @email{restone@@skypoint.com, Richard E. Stone}. @findex lchown AT r{, added to the library} -New function @code{lchown} has been added for UNIX compatibility. +@findex lstat AT r{, added to the library} +New functions @code{lchown} and @code{lstat} have been added for +UNIX compatibility. @findex setitimer AT r{, and zero @code{it_interval.tv_usec}} Calling the @code{setitimer} function with both Index: src/libc/posix/sys/stat/lstat.txh =================================================================== RCS file: lstat.txh diff -N lstat.txh --- /dev/null Tue May 5 16:32:27 1998 +++ lstat.txh Sun Jul 30 15:53:46 2000 @@ -0,0 +1,117 @@ +@node lstat, io +@subheading Syntax + +@example +#include + +int lstat(const char *file, struct stat *sbuf); +@end example + +@subheading Description + +This function obtains the status of the file @var{file} and stores +it in @var{sbuf}, which has this structure: + +@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 */ +@}; +@end smallexample + +The @code{st_atime}, @code{st_ctime} and @code{st_mtime} have different +values only when long file names are supported (e.g. on Windows 9X); +otherwise, they all have the same value: the time that the file was last +written AT footnote{ +Even when long file names @emph{are} supported, the three time values +returned by @code{stat} might be identical if the file was last written +by a program which used legacy DOS functions that don't know about long +file names.}. Most Windows 9X VFAT filesystems only support the date of +the file's last access (the time is set to zero); therefore, the DJGPP +implementation of @code{stat} sets the @code{st_atime} member to the +same value as @code{st_mtime} if the time part of @code{st_atime} +returned by the filesystem is zero (to prevent the situation where the +file appears to have been created @emph{after} it was last accessed, +which doesn't look good). + +Some members of @code{struct stat} are very expensive to compute. If +your application is a heavy user of @code{stat} and is too slow, you can +disable computation of the members your application doesn't need, as +described in @ref{_djstat_flags}. + +@subheading Return Value + +Zero on success, nonzero on failure (and @var{errno} set). + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +struct stat s; +lstat("data.txt", &s); +if (S_ISDIR(s.st_mode)) + printf("is directory\n"); +@end example + +@subheading Implementation Notes + +Supplying a 100% Unix-compatible @code{lstat} function under DOS is an +implementation nightmare. The following notes describe some of the +obscure points specific to @code{lstat}s behavior in DJGPP. + +1. The @samp{drive} for character devices (like @code{con}, @code{/dev/null} +and others is returned as -1. For drives networked by Novell Netware, it +is returned as -2. + +2. The starting cluster number of a file serves as its inode number. For +files whose starting cluster number is inaccessible (empty files, files on +Windows 9X, on networked drives, etc.) the @code{st_inode} field will be +@emph{invented} +in a way which guarantees that no two different files will get the same +inode number (thus it is unique). This invented inode will also be +different from any real cluster number of any local file. However, only +on plain DOS, and only for local, non-empty files/directories the inode +is guaranteed to be consistent between @code{stat} and @code{fstat} +function calls. + +3. The WRITE access mode bit is set only for the user (unless the file is +read-only, hidden or system). EXECUTE bit is set for directories, files +which can be executed from the DOS prompt (batch files, .com, .dll and .exe +executables) or run by @code{go32-v2}. + +4. Size of directories is reported as the number of its files (sans `.' and +`..' entries) multiplied by 32 bytes (the size of directory entry). On FAT +filesystems that support the LFN API (such as Windows 9X), the reported +size of the directory accounts for additional space used to store the long +file names. + +5. Time stamp for root directories is taken from the volume label entry, +if that's available; otherwise, it is reported as 1-Jan-1980. + +6. The variable @code{_djstat_flags} (@pxref{_djstat_flags}) controls +what hard-to-get fields of @code{struct stat} are needed by the +application. + +7. @code{stat} should not be used to get an up-to-date info about a file +which is open and has been written to, because @code{stat} will only +return correct data after the file is closed. Use @code{fstat} +(@pxref{fstat}) while the file is open. Alternatively, you can call +@code{fflush} and @code{fsync} to make the OS flush all the file's data +to the disk, before calling @code{stat}. + +8. The number of links @code{st_nlink} is always 1 for files other than +directories. For directories, it is the number of subdirectories plus +2. This is so that programs written for Unix that depend on this to +optimize recursive traversal of the directory tree, will still work. Index: src/libc/posix/sys/stat/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/makefile,v retrieving revision 1.1 diff -u -r1.1 makefile --- makefile 1995/04/05 05:59:56 1.1 +++ makefile 2000/07/30 19:53:46 @@ -6,6 +6,7 @@ SRC += fixpath.c SRC += fstat.c SRC += is_exec.c +SRC += lstat.c SRC += mkdir.c SRC += mkfifo.c SRC += st_loss.c Index: src/libc/posix/sys/stat/xstat.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/xstat.c,v retrieving revision 1.2 diff -u -r1.2 xstat.c --- xstat.c 2000/06/19 18:00:57 1.2 +++ xstat.c 2000/07/30 19:53:47 @@ -3,7 +3,7 @@ /* * This is file XSTAT.C * - * Internal assist functions which are common to stat() and fstat(). + * Internal assist functions which are common to stat(), fstat() and lstat(). * * * Copyright (c) 1994-96 Eli Zaretskii Index: src/libc/posix/sys/stat/xstat.h =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/xstat.h,v retrieving revision 1.3 diff -u -r1.3 xstat.h --- xstat.h 1996/08/12 23:58:18 1.3 +++ xstat.h 2000/07/30 19:53:48 @@ -1,7 +1,7 @@ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ /* - * Header for internal stat()/fstat() assist functions. + * Header for internal stat()/fstat()/lstat() assist functions. * */