From ef0a2650865b2de21fca220bbb8eae050699cf0a Mon Sep 17 00:00:00 2001 From: Evgeniy Ivanov Date: Fri, 1 Jul 2011 23:35:54 +0400 Subject: [PATCH] New stat structure. * VFS and installed MFSes must be in sync before and after this change * Use struct stat from NetBSD. It requires adding new STAT, FSTAT and LSTAT syscalls. Libc modification is both backward and forward compatible. Also new struct stat uses modern field sizes to avoid ABI incompatibility, when we update uid_t, gid_t and company. Exceptions are ino_t and off_t in old libc (though paddings added). --- commands/stat/stat.c | 2 - common/include/minix/callnr.h | 11 +- common/include/minix/type.h | 2 +- docs/UPDATING | 17 +++ include/minix/types.h | 15 ++- include/sys/stat.h | 55 ++++++++++ lib/libc/posix/_fstat.c | 23 +++- lib/libc/posix/_lstat.c | 23 +++- lib/libc/posix/_stat.c | 23 +++- lib/libvtreefs/stadir.c | 3 + lib/nbsd_libc/db/btree/bt_open.c | 11 +- lib/nbsd_libc/db/hash/hash.c | 11 +- lib/nbsd_libc/minix-port.patch | 92 +++++++++------- lib/nbsd_libc/resolv/res_init.c | 4 - lib/nbsd_libc/stdio/fseeko.c | 11 +- lib/nbsd_libc/stdio/makebuf.c | 19 ++-- lib/nbsd_libc/sys-minix/stat.c | 167 ++++++++++++++++------------ man/man2/Makefile | 2 +- man/man2/stat.2 | 179 ------------------------------- nbsd_include/sys/stat.h | 121 ++++++++++----------- nbsd_include/sys/types.h | 8 ++ servers/ext2/stadir.c | 5 + servers/hgfs/stat.c | 8 ++ servers/iso9660fs/stadir.c | 11 ++ servers/mfs/stadir.c | 11 ++ servers/pfs/stadir.c | 10 ++ servers/pm/table.c | 2 +- servers/rs/exec.c | 6 +- servers/vfs/exec.c | 8 +- servers/vfs/proto.h | 2 +- servers/vfs/request.c | 55 ++++++++-- servers/vfs/stadir.c | 19 +++- servers/vfs/table.c | 12 +-- servers/vm/exec.c | 2 +- 34 files changed, 533 insertions(+), 417 deletions(-) delete mode 100644 man/man2/stat.2 diff --git a/commands/stat/stat.c b/commands/stat/stat.c index be4d70d72..c872088d4 100644 --- a/commands/stat/stat.c +++ b/commands/stat/stat.c @@ -76,10 +76,8 @@ struct field { { "mtime", addr(st_mtime), size(st_mtime), 0 }, { "Ctime", addr(st_ctime), size(st_ctime), 0 }, { "ctime", addr(st_ctime), size(st_ctime), 0 }, -# ifdef BSD { "blksize", addr(st_blksize), size(st_blksize), 0 }, { "blocks", addr(st_blocks), size(st_blocks), 0 }, -# endif { NULL, 0, 0, 0 }, }; diff --git a/common/include/minix/callnr.h b/common/include/minix/callnr.h index a204e48b4..9b58f0fbb 100644 --- a/common/include/minix/callnr.h +++ b/common/include/minix/callnr.h @@ -17,7 +17,7 @@ #define CHMOD 15 #define CHOWN 16 #define BRK 17 -#define STAT 18 +#define PREV_STAT 18 #define LSEEK 19 #define MINIX_GETPID 20 #define MOUNT 21 @@ -27,7 +27,7 @@ #define STIME 25 #define PTRACE 26 #define ALARM 27 -#define FSTAT 28 +#define PREV_FSTAT 28 #define PAUSE 29 #define UTIME 30 #define ACCESS 33 @@ -44,7 +44,7 @@ #define GETGID 47 #define SIGNAL 48 #define RDLNK 49 -#define LSTAT 50 +#define PREV_LSTAT 50 #define IOCTL 54 #define FCNTL 55 #define FS_READY 57 @@ -115,6 +115,11 @@ #define GCOV_FLUSH 112 /* flush gcov data from server to gcov files */ +/* Numbers reused intentionally */ +#define STAT 65 +#define FSTAT 66 +#define LSTAT 67 + #define TASK_REPLY 121 /* to VFS: reply code from drivers, not * really a standalone call. */ diff --git a/common/include/minix/type.h b/common/include/minix/type.h index 7e312db7a..cb2b8e861 100644 --- a/common/include/minix/type.h +++ b/common/include/minix/type.h @@ -167,7 +167,7 @@ struct exec_newmem int is_elf; /* Is ELF exe? */ dev_t st_dev; /* Device holding executable file */ ino_t st_ino; /* Inode of executable file */ - time_t st_ctime; /* Last changed time of executable file */ + time_t enst_ctime; /* Last changed time of executable file */ uid_t new_uid; /* Process UID after exec */ gid_t new_gid; /* Process GID after exec */ char progname[16]; /* Should be at least PROC_NAME_LEN */ diff --git a/docs/UPDATING b/docs/UPDATING index e8b185873..d2cb1255e 100644 --- a/docs/UPDATING +++ b/docs/UPDATING @@ -1,3 +1,20 @@ +20110708 + * VFS and installed MFSes must be in sync before and after this change * + + You must update the GNU headers. + # cd /usr/src + # make gnu-includes + + You must rebuild both MFS and VFS (including those one in the image). + Either make world or do the following: + # cd /usr/src/servers/mfs + # make install + # cd /usr/src/servers/vfs + # make install + # cd /usr/src/tools + # make hdboot + # shutdown -r now + 20110701: # rm -rf /usr/include /usr/netbsd # make etcfiles includes cleandepend depend gnu-includes diff --git a/include/minix/types.h b/include/minix/types.h index 9bb2aa193..1d1ef3149 100644 --- a/include/minix/types.h +++ b/include/minix/types.h @@ -99,17 +99,28 @@ typedef long key_t; typedef long useconds_t; /* Time in microseconds */ typedef short dev_t; /* holds (major|minor) device pair */ +typedef u32_t big_dev_t; -/* Types used in disk, inode, etc. data structures. */ +/* Types used in disk, inode, etc. data structures. + * Some u64_t should be i64_t, but anyway with old libc we use .lo only. + */ typedef char gid_t; /* group id */ +typedef u32_t big_gid_t; /* group id */ typedef unsigned long ino_t; /* i-node number (V3 filesystem) */ +typedef u64_t big_ino_t; /* i-node number (V3 filesystem) */ typedef unsigned short mode_t; /* file type and permissions bits */ -typedef short nlink_t; /* number of links to a file */ +typedef u32_t big_mode_t; /* file type and permissions bits */ +typedef short nlink_t; /* number of links to a file */ +typedef u32_t big_nlink_t;/* number of links to a file */ typedef long off_t; /* offset within a file */ +typedef u64_t big_off_t; /* offset within a file */ typedef int pid_t; /* process id (must be signed) */ typedef short uid_t; /* user id */ +typedef u32_t big_uid_t; /* user id */ typedef unsigned long fsblkcnt_t; /* File system block count */ typedef unsigned long fsfilcnt_t; /* File system file count */ +typedef u32_t blkcnt_t; /* File system block count */ +typedef unsigned long blksize_t; /* File system block size */ /* Signal handler type, e.g. SIG_IGN */ typedef void _PROTOTYPE( (*sighandler_t), (int) ); diff --git a/include/sys/stat.h b/include/sys/stat.h index 6402bbacf..3af7b8d92 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -10,7 +10,43 @@ #include #endif + struct stat { + big_dev_t st_dev; /* inode's device */ + big_mode_t st_mode; /* inode protection mode */ + ino_t st_ino; /* inode's number */ + u32_t padding; /* inode's padding */ + big_nlink_t st_nlink; /* number of hard links */ + big_uid_t st_uid; /* user ID of the file's owner */ + big_gid_t st_gid; /* group ID of the file's group */ + big_dev_t st_rdev; /* device type */ +#if defined(_NETBSD_SOURCE) + struct timespec st_atimespec;/* time of last access */ + struct timespec st_mtimespec;/* time of last data modification */ + struct timespec st_ctimespec;/* time of last file status change */ + struct timespec st_birthtimespec; /* time of creation */ +#else + time_t st_atime; /* time of last access */ + long st_atimensec; /* nsec of last access */ + time_t st_mtime; /* time of last data modification */ + long st_mtimensec; /* nsec of last data modification */ + time_t st_ctime; /* time of last file status change */ + long st_ctimensec; /* nsec of last file status change */ + time_t st_birthtime; /* time of creation */ + long st_birthtimensec; /* nsec of time of creation */ +#endif + off_t st_size; /* file size, in bytes */ + u32_t padding2; /* size padding */ + blkcnt_t st_blocks; /* blocks allocated for file */ + u32_t padding3; /* blocks padding */ + blksize_t st_blksize; /* optimal blocksize for I/O */ + u32_t st_flags; /* user defined flags for file */ + u32_t st_gen; /* file generation number */ + u32_t st_spare[2]; +}; + + +struct minix_prev_stat { dev_t st_dev; /* major/minor device number */ ino_t st_ino; /* i-node number */ mode_t st_mode; /* file mode, protection bits, etc. */ @@ -24,6 +60,25 @@ struct stat { time_t st_ctime; /* time of last file status change */ }; + +/* Copy field by field because of st_gid type mismath and + * difference in order after atime. + */ +#define COPY_PREV_STAT_TO_NEW(dest, src)\ + (dest)->st_dev = (src)->st_dev;\ + (dest)->st_ino = (src)->st_ino;\ + (dest)->st_mode = (src)->st_mode;\ + (dest)->st_nlink = (src)->st_nlink;\ + (dest)->st_uid = (src)->st_uid;\ + (dest)->st_gid = (src)->st_gid;\ + (dest)->st_rdev = (src)->st_rdev;\ + (dest)->st_size = (src)->st_size;\ + (dest)->st_atime = (src)->st_atime;\ + (dest)->st_mtime = (src)->st_mtime;\ + (dest)->st_ctime = (src)->st_ctime + +#define S_BLKSIZE 512 /* block size used in the stat struct */ + /* Traditional mask definitions for st_mode. */ #define S_IFMT 0170000 /* type of file */ #define S_IFSOCK 0140000 /* socket */ diff --git a/lib/libc/posix/_fstat.c b/lib/libc/posix/_fstat.c index 314dc075e..1b29fdfec 100644 --- a/lib/libc/posix/_fstat.c +++ b/lib/libc/posix/_fstat.c @@ -1,14 +1,35 @@ #include #define fstat _fstat #include +#include PUBLIC int fstat(fd, buffer) int fd; struct stat *buffer; { message m; + int r; + struct minix_prev_stat old_sb; m.m1_i1 = fd; m.m1_p1 = (char *) buffer; - return(_syscall(VFS_PROC_NR, FSTAT, &m)); + + if((r = _syscall(VFS_PROC_NR, FSTAT, &m)) >= 0 || errno != ENOSYS) + return r; + + errno = 0; + + /* ENOSYS: new binary and old VFS, fallback to PREV_STAT. + * User has struct stat (buffer), VFS still fills minix_prev_stat. + */ + m.m1_i1 = fd; + m.m1_p1 = (char *) &old_sb; + + if((r = _syscall(VFS_PROC_NR, PREV_FSTAT, &m)) < 0) + return r; + + memset(buffer, 0, sizeof(struct stat)); + COPY_PREV_STAT_TO_NEW(buffer, &old_sb); + + return r; } diff --git a/lib/libc/posix/_lstat.c b/lib/libc/posix/_lstat.c index 4ad6ceb23..e0b0ba3ed 100644 --- a/lib/libc/posix/_lstat.c +++ b/lib/libc/posix/_lstat.c @@ -1,6 +1,5 @@ #include #define lstat _lstat -#define stat _stat #include #include @@ -10,11 +9,29 @@ struct stat *buffer; { message m; int r; + struct minix_prev_stat old_sb; m.m1_i1 = strlen(name) + 1; m.m1_p1 = (char *) name; m.m1_p2 = (char *) buffer; + if((r = _syscall(VFS_PROC_NR, LSTAT, &m)) >= 0 || errno != ENOSYS) - return r; - return _stat(name, buffer); + return r; + + errno = 0; + + /* ENOSYS: new binary and old VFS, fallback to PREV_STAT. + * User has struct stat (buffer), VFS still fills minix_prev_stat. + */ + m.m1_i1 = strlen(name) + 1; + m.m1_p1 = (char *) name; + m.m1_p2 = (char *) &old_sb; + + if((r = _syscall(VFS_PROC_NR, PREV_LSTAT, &m)) < 0) + return r; + + memset(buffer, 0, sizeof(struct stat)); + COPY_PREV_STAT_TO_NEW(buffer, &old_sb); + + return r; } diff --git a/lib/libc/posix/_stat.c b/lib/libc/posix/_stat.c index ddbf3d12f..1886081b0 100644 --- a/lib/libc/posix/_stat.c +++ b/lib/libc/posix/_stat.c @@ -8,9 +8,30 @@ _CONST char *name; struct stat *buffer; { message m; + int r; + struct minix_prev_stat old_sb; m.m1_i1 = strlen(name) + 1; m.m1_p1 = (char *) name; m.m1_p2 = (char *) buffer; - return(_syscall(VFS_PROC_NR, STAT, &m)); + + if((r = _syscall(VFS_PROC_NR, STAT, &m)) >= 0 || errno != ENOSYS) + return r; + + errno = 0; + + /* ENOSYS: new binary and old VFS, fallback to PREV_STAT. + * User has struct stat (buffer), VFS still fills minix_prev_stat. + */ + m.m1_i1 = strlen(name) + 1; + m.m1_p1 = (char *) name; + m.m1_p2 = (char *) &old_sb; + + if((r = _syscall(VFS_PROC_NR, PREV_STAT, &m)) < 0) + return r; + + memset(buffer, 0, sizeof(struct stat)); + COPY_PREV_STAT_TO_NEW(buffer, &old_sb); + + return r; } diff --git a/lib/libvtreefs/stadir.c b/lib/libvtreefs/stadir.c index 58859f6c4..b00ef34b2 100644 --- a/lib/libvtreefs/stadir.c +++ b/lib/libvtreefs/stadir.c @@ -5,6 +5,7 @@ #include #include #include +#include /*===========================================================================* * fs_stat * @@ -22,6 +23,8 @@ PUBLIC int fs_stat(void) if ((node = find_inode(fs_m_in.REQ_INODE_NR)) == NULL) return EINVAL; + memset(&statbuf, 0, sizeof(struct stat)); + /* Fill in the basic info. */ statbuf.st_dev = fs_dev; statbuf.st_ino = get_inode_number(node); diff --git a/lib/nbsd_libc/db/btree/bt_open.c b/lib/nbsd_libc/db/btree/bt_open.c index 16eb4fe62..b5f7158a8 100644 --- a/lib/nbsd_libc/db/btree/bt_open.c +++ b/lib/nbsd_libc/db/btree/bt_open.c @@ -263,10 +263,15 @@ __bt_open(const char *fname, int flags, mode_t mode, const BTREEINFO *openinfo, */ if (b.psize == 0) { #ifdef __minix - b.psize = MINIX_ST_BLKSIZE; -#else - b.psize = sb.st_blksize; + if (sb.st_blksize == 0) { + /* 0 in 2 cases: upgrade from old to new struct stat or + * there is a bug in underlying fs. + */ + b.psize = MINIX_ST_BLKSIZE; + } else #endif + b.psize = sb.st_blksize; + if (b.psize < MINPSIZE) b.psize = MINPSIZE; if (b.psize > MAX_PAGE_OFFSET + 1) diff --git a/lib/nbsd_libc/db/hash/hash.c b/lib/nbsd_libc/db/hash/hash.c index d334e8640..5e69e4cfe 100644 --- a/lib/nbsd_libc/db/hash/hash.c +++ b/lib/nbsd_libc/db/hash/hash.c @@ -302,10 +302,15 @@ init_hash(HTAB *hashp, const char *file, const HASHINFO *info) if (stat(file, &statbuf)) return (NULL); #ifdef __minix - hashp->BSIZE = MIN(MINIX_ST_BLKSIZE, MAX_BSIZE); -#else - hashp->BSIZE = MIN(statbuf.st_blksize, MAX_BSIZE); + if (statbuf.st_blksize == 0) { + /* 0 in 2 cases: upgrade from old to new struct stat or + * there is a bug in underlying fs. + */ + hashp->BSIZE = MIN(MINIX_ST_BLKSIZE, MAX_BSIZE); + } else #endif + hashp->BSIZE = MIN(statbuf.st_blksize, MAX_BSIZE); + hashp->BSHIFT = __log2((uint32_t)hashp->BSIZE); } diff --git a/lib/nbsd_libc/minix-port.patch b/lib/nbsd_libc/minix-port.patch index 1ea3e9014..9ea5ac0ad 100644 --- a/lib/nbsd_libc/minix-port.patch +++ b/lib/nbsd_libc/minix-port.patch @@ -280,15 +280,21 @@ diff -ru nbsdsrc/src/lib/libc/compat-43/Makefile.inc lib/nbsd_libc/compat-43/Mak diff -ru nbsdsrc/src/lib/libc/db/btree/bt_open.c lib/nbsd_libc/db/btree/bt_open.c --- nbsdsrc/src/lib/libc/db/btree/bt_open.c +++ lib/nbsd_libc/db/btree/bt_open.c -@@ -262,7 +262,11 @@ +@@ -262,7 +262,16 @@ * Don't overflow the page offset type. */ if (b.psize == 0) { +- b.psize = sb.st_blksize; +#ifdef __minix -+ b.psize = MINIX_ST_BLKSIZE; -+#else - b.psize = sb.st_blksize; ++ if (sb.st_blksize == 0) { ++ /* 0 in 2 cases: upgrade from old to new struct stat or ++ * there is a bug in underlying fs. ++ */ ++ b.psize = MINIX_ST_BLKSIZE; ++ } else +#endif ++ b.psize = sb.st_blksize; ++ if (b.psize < MINPSIZE) b.psize = MINPSIZE; if (b.psize > MAX_PAGE_OFFSET + 1) @@ -314,15 +320,21 @@ diff -ru nbsdsrc/src/lib/libc/db/db/db.c lib/nbsd_libc/db/db/db.c diff -ru nbsdsrc/src/lib/libc/db/hash/hash.c lib/nbsd_libc/db/hash/hash.c --- nbsdsrc/src/lib/libc/db/hash/hash.c +++ lib/nbsd_libc/db/hash/hash.c -@@ -301,7 +301,11 @@ +@@ -301,7 +301,16 @@ if (file != NULL) { if (stat(file, &statbuf)) return (NULL); +- hashp->BSIZE = MIN(statbuf.st_blksize, MAX_BSIZE); +#ifdef __minix -+ hashp->BSIZE = MIN(MINIX_ST_BLKSIZE, MAX_BSIZE); -+#else - hashp->BSIZE = MIN(statbuf.st_blksize, MAX_BSIZE); ++ if (statbuf.st_blksize == 0) { ++ /* 0 in 2 cases: upgrade from old to new struct stat or ++ * there is a bug in underlying fs. ++ */ ++ hashp->BSIZE = MIN(MINIX_ST_BLKSIZE, MAX_BSIZE); ++ } else +#endif ++ hashp->BSIZE = MIN(statbuf.st_blksize, MAX_BSIZE); ++ hashp->BSHIFT = __log2((uint32_t)hashp->BSIZE); } @@ -2184,18 +2196,7 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_comp.c lib/nbsd_libc/resolv/res_comp.c diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c --- nbsdsrc/src/lib/libc/resolv/res_init.c +++ lib/nbsd_libc/resolv/res_init.c -@@ -70,6 +70,10 @@ - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -+#ifdef __minix -+#define __MINIX_EMULATE_NETBSD_STAT -+#endif -+ - #include - #if defined(LIBC_SCCS) && !defined(lint) - #ifdef notdef -@@ -88,7 +92,9 @@ +@@ -88,7 +88,9 @@ #include #include #include @@ -2205,7 +2206,7 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c #include #include -@@ -348,7 +354,9 @@ +@@ -348,7 +350,9 @@ nserv = 0; if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { struct stat st; @@ -2215,7 +2216,7 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c /* read the config file */ while (fgets(buf, sizeof(buf), fp) != NULL) { -@@ -502,6 +510,7 @@ +@@ -502,6 +506,7 @@ if (fstat(statp->_u._ext.ext->resfd, &st) != -1) __res_conf_time = statp->_u._ext.ext->res_conf_time = st.st_mtimespec; @@ -2223,7 +2224,7 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c statp->_u._ext.ext->kq = kqueue(); (void)fcntl(statp->_u._ext.ext->kq, F_SETFD, FD_CLOEXEC); (void)fcntl(statp->_u._ext.ext->resfd, F_SETFD, FD_CLOEXEC); -@@ -509,6 +518,9 @@ +@@ -509,6 +514,9 @@ EV_ADD|EV_ENABLE|EV_CLEAR, NOTE_DELETE|NOTE_WRITE| NOTE_EXTEND| NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE, 0, 0); (void)kevent(statp->_u._ext.ext->kq, &kc, 1, NULL, 0, &ts); @@ -2233,7 +2234,7 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c } else { statp->_u._ext.ext->kq = -1; statp->_u._ext.ext->resfd = -1; -@@ -565,7 +577,13 @@ +@@ -565,7 +573,13 @@ int res_check(res_state statp, struct timespec *mtime) { @@ -2247,7 +2248,7 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c * If the times are equal, then we check if there * was a kevent related to resolv.conf and reload. * If the times are not equal, then we don't bother -@@ -593,6 +611,7 @@ +@@ -593,6 +607,7 @@ if (mtime) *mtime = __res_conf_time; return 1; @@ -2258,44 +2259,53 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c diff -ru nbsdsrc/src/lib/libc/stdio/fseeko.c lib/nbsd_libc/stdio/fseeko.c --- nbsdsrc/src/lib/libc/stdio/fseeko.c +++ lib/nbsd_libc/stdio/fseeko.c -@@ -150,7 +150,11 @@ +@@ -150,7 +150,16 @@ fp->_flags |= __SNPT; goto dumb; } +- fp->_blksize = st.st_blksize; +#ifdef __minix -+ fp->_blksize = MINIX_ST_BLKSIZE; -+#else - fp->_blksize = st.st_blksize; ++ if (st.st_blksize == 0) { ++ /* 0 in 2 cases: upgrade from old to new struct stat or ++ * there is a bug in underlying fs. ++ */ ++ fp->_blksize = MINIX_ST_BLKSIZE; ++ } else +#endif ++ fp->_blksize = st.st_blksize; ++ fp->_flags |= __SOPT; } diff -ru nbsdsrc/src/lib/libc/stdio/makebuf.c lib/nbsd_libc/stdio/makebuf.c --- nbsdsrc/src/lib/libc/stdio/makebuf.c +++ lib/nbsd_libc/stdio/makebuf.c -@@ -114,18 +114,25 @@ +@@ -114,18 +114,22 @@ /* could be a tty iff it is a character device */ *couldbetty = S_ISCHR(st.st_mode); -+#ifndef __minix - if (st.st_blksize == 0) { - *bufsize = BUFSIZ; - return (__SNPT); - } -+#endif +- if (st.st_blksize == 0) { +- *bufsize = BUFSIZ; +- return (__SNPT); +- } /* * Optimise fseek() only if it is a regular file. (The test for * __sseek is mainly paranoia.) It is safe to set _blksize * unconditionally; it will only be used if __SOPT is also set. */ +- *bufsize = st.st_blksize; +- fp->_blksize = st.st_blksize; +#ifdef __minix -+ *bufsize = MINIX_ST_BLKSIZE; -+ fp->_blksize = MINIX_ST_BLKSIZE; -+#else - *bufsize = st.st_blksize; - fp->_blksize = st.st_blksize; ++ if (st.st_blksize == 0) { ++ /* 0 in 2 cases: upgrade from old to new struct stat or ++ * there is a bug in underlying fs. ++ */ ++ *bufsize = fp->_blksize = MINIX_ST_BLKSIZE; ++ } else +#endif ++ *bufsize = fp->_blksize = st.st_blksize; ++ return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ? __SOPT : __SNPT); } diff --git a/lib/nbsd_libc/resolv/res_init.c b/lib/nbsd_libc/resolv/res_init.c index 7e39072d5..a3e65b92b 100644 --- a/lib/nbsd_libc/resolv/res_init.c +++ b/lib/nbsd_libc/resolv/res_init.c @@ -70,10 +70,6 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef __minix -#define __MINIX_EMULATE_NETBSD_STAT -#endif - #include #if defined(LIBC_SCCS) && !defined(lint) #ifdef notdef diff --git a/lib/nbsd_libc/stdio/fseeko.c b/lib/nbsd_libc/stdio/fseeko.c index 1008e777e..d1ed157e9 100644 --- a/lib/nbsd_libc/stdio/fseeko.c +++ b/lib/nbsd_libc/stdio/fseeko.c @@ -151,10 +151,15 @@ fseeko(FILE *fp, off_t offset, int whence) goto dumb; } #ifdef __minix - fp->_blksize = MINIX_ST_BLKSIZE; -#else - fp->_blksize = st.st_blksize; + if (st.st_blksize == 0) { + /* 0 in 2 cases: upgrade from old to new struct stat or + * there is a bug in underlying fs. + */ + fp->_blksize = MINIX_ST_BLKSIZE; + } else #endif + fp->_blksize = st.st_blksize; + fp->_flags |= __SOPT; } diff --git a/lib/nbsd_libc/stdio/makebuf.c b/lib/nbsd_libc/stdio/makebuf.c index dc37f8645..93fdd558f 100644 --- a/lib/nbsd_libc/stdio/makebuf.c +++ b/lib/nbsd_libc/stdio/makebuf.c @@ -114,12 +114,6 @@ __swhatbuf(fp, bufsize, couldbetty) /* could be a tty iff it is a character device */ *couldbetty = S_ISCHR(st.st_mode); -#ifndef __minix - if (st.st_blksize == 0) { - *bufsize = BUFSIZ; - return (__SNPT); - } -#endif /* * Optimise fseek() only if it is a regular file. (The test for @@ -127,12 +121,15 @@ __swhatbuf(fp, bufsize, couldbetty) * unconditionally; it will only be used if __SOPT is also set. */ #ifdef __minix - *bufsize = MINIX_ST_BLKSIZE; - fp->_blksize = MINIX_ST_BLKSIZE; -#else - *bufsize = st.st_blksize; - fp->_blksize = st.st_blksize; + if (st.st_blksize == 0) { + /* 0 in 2 cases: upgrade from old to new struct stat or + * there is a bug in underlying fs. + */ + *bufsize = fp->_blksize = MINIX_ST_BLKSIZE; + } else #endif + *bufsize = fp->_blksize = st.st_blksize; + return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ? __SOPT : __SNPT); } diff --git a/lib/nbsd_libc/sys-minix/stat.c b/lib/nbsd_libc/sys-minix/stat.c index 7aa47f675..ee39727eb 100644 --- a/lib/nbsd_libc/sys-minix/stat.c +++ b/lib/nbsd_libc/sys-minix/stat.c @@ -5,101 +5,126 @@ #include #include -#ifdef __MINIX_EMULATE_NETBSD_STAT -#error __MINIX_EMULATE_NETBSD_STAT is set. -#endif -int __orig_minix_stat(name, buffer) -const char *name; -struct __minix_stat *buffer; +/* XXX until that st_Xtime macroses used, we have to undefine them, + * because of minix_prev_stat + */ +#undef st_atime +#undef st_ctime +#undef st_mtime + +static void prev_stat2new_stat(struct stat *new, struct minix_prev_stat *prev) { - message m; - - m.m1_i1 = strlen(name) + 1; - m.m1_p1 = (char *) name; - m.m1_p2 = (char *) buffer; - return(_syscall(VFS_PROC_NR, STAT, &m)); + /* Copy field by field because of st_gid type mismath and + * difference in order after atime. + */ + new->st_dev = prev->st_dev; + new->st_ino = prev->st_ino; + new->st_mode = prev->st_mode; + new->st_nlink = prev->st_nlink; + new->st_uid = prev->st_uid; + new->st_gid = prev->st_gid; + new->st_rdev = prev->st_rdev; + new->st_size = prev->st_size; + new->st_atimespec.tv_sec = prev->st_atime; + new->st_mtimespec.tv_sec = prev->st_mtime; + new->st_ctimespec.tv_sec = prev->st_ctime; } -int __orig_minix_fstat(fd, buffer) -int fd; -struct __minix_stat *buffer; -{ - message m; - m.m1_i1 = fd; - m.m1_p1 = (char *) buffer; - return(_syscall(VFS_PROC_NR, FSTAT, &m)); -} - -int __orig_minix_lstat(name, buffer) +int _stat(name, buffer) const char *name; -struct __minix_stat *buffer; +struct stat *buffer; { message m; int r; + struct minix_prev_stat old_sb; m.m1_i1 = strlen(name) + 1; m.m1_p1 = (char *) name; m.m1_p2 = (char *) buffer; - if((r = _syscall(VFS_PROC_NR, LSTAT, &m)) >= 0 || errno != ENOSYS) - return r; - return __orig_minix_stat(name, buffer); -} -/* - * NetBSD Fields Emulation. - */ - -static void __emulate_netbsd_fields(struct __netbsd_stat *buffer) -{ - /* Emulated NetBSD fields. */ - buffer->st_atimespec.tv_sec = buffer->st_atime; - buffer->st_atimespec.tv_nsec = 0; - buffer->st_mtimespec.tv_sec = buffer->st_mtime; - buffer->st_mtimespec.tv_nsec = 0; - buffer->st_ctimespec.tv_sec = buffer->st_ctime; - buffer->st_ctimespec.tv_nsec = 0; - buffer->st_birthtimespec.tv_sec = 0; - buffer->st_birthtimespec.tv_nsec = 0; - buffer->st_blocks = (buffer->st_size / S_BLKSIZE) + 1; - buffer->st_blksize = MINIX_ST_BLKSIZE; -} - -const int __emu_netbsd_stat(name, buffer) -const char *name; -struct __netbsd_stat *buffer; -{ - int r; - - r = __orig_minix_stat(name, (struct __minix_stat *)buffer); - if (r < 0) - return r; - __emulate_netbsd_fields(buffer); + if((r = _syscall(VFS_PROC_NR, STAT, &m)) >= 0 || errno != ENOSYS) return r; + + errno = 0; + + /* ENOSYS: new binary and old VFS, fallback to PREV_STAT. + * User has struct stat (buffer), VFS still fills minix_prev_stat. + */ + m.m1_i1 = strlen(name) + 1; + m.m1_p1 = (char *) name; + m.m1_p2 = (char *) &old_sb; + + if((r = _syscall(VFS_PROC_NR, PREV_STAT, &m)) < 0) + return r; + + memset(buffer, 0, sizeof(struct stat)); + prev_stat2new_stat(buffer, &old_sb); + + return r; } -int __emu_netbsd_fstat(fd, buffer) +int _fstat(fd, buffer) int fd; -struct __netbsd_stat *buffer; +struct stat *buffer; { - int r; - r = __orig_minix_fstat(fd, (struct __minix_stat *)buffer); - if ( r < 0 ) - return r; - __emulate_netbsd_fields(buffer); + message m; + int r; + struct minix_prev_stat old_sb; + + m.m1_i1 = fd; + m.m1_p1 = (char *) buffer; + + if((r = _syscall(VFS_PROC_NR, FSTAT, &m)) >= 0 || errno != ENOSYS) return r; + + errno = 0; + + /* ENOSYS: new binary and old VFS, fallback to PREV_STAT. + * User has struct stat (buffer), VFS still fills minix_prev_stat. + */ + m.m1_i1 = fd; + m.m1_p1 = (char *) &old_sb; + + if((r = _syscall(VFS_PROC_NR, PREV_FSTAT, &m)) < 0) + return r; + + memset(buffer, 0, sizeof(struct stat)); + prev_stat2new_stat(buffer, &old_sb); + + return r; } -int __emu_netbsd_lstat(name, buffer) +int _lstat(name, buffer) const char *name; -struct __netbsd_stat *buffer; +struct stat *buffer; { - int r; + message m; + int r; + struct minix_prev_stat old_sb; - r = __orig_minix_lstat(name, (struct __minix_stat *)buffer); - if ( r < 0 ) - return r; - __emulate_netbsd_fields(buffer); + m.m1_i1 = strlen(name) + 1; + m.m1_p1 = (char *) name; + m.m1_p2 = (char *) buffer; + + if((r = _syscall(VFS_PROC_NR, LSTAT, &m)) >= 0 || errno != ENOSYS) return r; + + errno = 0; + + /* ENOSYS: new binary and old VFS, fallback to PREV_STAT. + * User has struct stat (buffer), VFS still fills minix_prev_stat. + */ + m.m1_i1 = strlen(name) + 1; + m.m1_p1 = (char *) name; + m.m1_p2 = (char *) &old_sb; + + if((r = _syscall(VFS_PROC_NR, PREV_LSTAT, &m)) < 0) + return r; + + memset(buffer, 0, sizeof(struct stat)); + prev_stat2new_stat(buffer, &old_sb); + + return r; } diff --git a/man/man2/Makefile b/man/man2/Makefile index ab7bedbdd..29d54b4cd 100644 --- a/man/man2/Makefile +++ b/man/man2/Makefile @@ -7,7 +7,7 @@ MAN= accept.2 access.2 alarm.2 bind.2 brk.2 chdir.2 chmod.2 chown.2 \ read.2 readlink.2 reboot.2 recv.2 recvfrom.2 recvmsg.2 rename.2 \ rmdir.2 select.2 send.2 sendmsg.2 sendto.2 setsid.2 \ setsockopt.2 setuid.2 shutdown.2 sigaction.2 sigpending.2 \ - sigprocmask.2 sigsuspend.2 socket.2 socketpair.2 stat.2 \ + sigprocmask.2 sigsuspend.2 socket.2 socketpair.2 \ statvfs.2 svrctl.2 symlink.2 sync.2 time.2 times.2 truncate.2 \ umask.2 uname.2 unlink.2 utime.2 wait.2 write.2 diff --git a/man/man2/stat.2 b/man/man2/stat.2 deleted file mode 100644 index f33c620ef..000000000 --- a/man/man2/stat.2 +++ /dev/null @@ -1,179 +0,0 @@ -.\" Copyright (c) 1980 Regents of the University of California. -.\" All rights reserved. The Berkeley software License Agreement -.\" specifies the terms and conditions for redistribution. -.\" -.\" @(#)stat.2 6.5 (Berkeley) 5/12/86 -.\" -.TH STAT 2 "May 12, 1986" -.UC 4 -.SH NAME -stat, lstat, fstat \- get file status -.SH SYNOPSIS -.nf -.ft B -#include -#include - -.ta +54n -int stat(const char *\fIpath\fP, struct stat *\fIbuf\fP) -int lstat(const char *\fIpath\fP, struct stat *\fIbuf\fP) -int fstat(int \fIfd\fP, struct stat *\fIbuf\fP) -.fi -.ft R -.SH DESCRIPTION -.B Stat -obtains information about the file -.IR path . -Read, write or execute -permission of the named file is not required, but all directories -listed in the path name leading to the file must be reachable. -.PP -.B Lstat -is like \fBstat\fP except in the case where the named file is a symbolic link, -in which case -.B lstat -returns information about the link, -while -.B stat -returns information about the file the link references. -.PP -.B Fstat -obtains the same information about an open file -referenced by the argument descriptor, such as would -be obtained by an \fBopen\fP call. Pipe descriptors -look like named pipes with a link count of zero. The -st_size field of pipes or named pipes shows the amount of -bytes currently buffered in the pipe. -.PP -.I Buf -is a pointer to a -.B stat -structure into which information is placed concerning the file. -The contents of the structure pointed to by -.I buf -is as follows: -.PP -.if t .RS -.nf -.ta +0.4i +0.8i +1i -struct stat { - dev_t st_dev; /* device inode resides on */ - ino_t st_ino; /* this inode's number */ - mode_t st_mode; /* file mode, protection bits, etc. */ - nlink_t st_nlink; /* number or hard links to the file */ - uid_t st_uid; /* user-id of the file's owner */ - gid_t st_gid; /* group-id of the file's owner */ - dev_t st_rdev; /* the device type, for inode that is device */ - off_t st_size; /* total size of file */ - time_t st_atime; /* time of last access */ - time_t st_mtime; /* time of last data modification */ - time_t st_ctime; /* time of last file status change */ -}; -.fi -.if t .RE -.DT -.PP -.TP 12 -st_atime -Time when file data was last read or modified. Changed by the following system -calls: -.BR mknod (2), -.BR utime (2), -.BR read (2), -and -.BR write (2). -For reasons of efficiency, -st_atime is not set when a directory -is searched, although this would be more logical. -.TP 12 -st_mtime -Time when data was last modified. -It is not set by changes of owner, group, link count, or mode. -Changed by the following system calls: -.BR mknod (2), -.BR utime (2), -.BR write (2). -.TP 12 -st_ctime -Time when file status was last changed. -It is set both both by writing and changing the i-node. -Changed by the following system calls: -.BR chmod (2) -.BR chown (2), -.BR link (2), -.BR mknod (2), -.BR rename (2), -.BR unlink (2), -.BR utime (2), -.BR write (2). -.PP -The file type information in \fBst_mode\fP has bits: -.PP -.nf -.in +5n -.ta 1.6i 2.5i 3i -#define S_IFMT 0170000 /* type of file */ -#define\ \ \ \ S_IFIFO 0010000 /* named pipe */ -#define\ \ \ \ S_IFCHR 0020000 /* character special */ -#define\ \ \ \ S_IFDIR 0040000 /* directory */ -#define\ \ \ \ S_IFBLK 0060000 /* block special */ -#define\ \ \ \ S_IFREG 0100000 /* regular */ -#define\ \ \ \ S_IFLNK 0120000 /* symbolic link */ -.fi -.in -5n -.PP -The mode bits 0007777 encode set-uid/gid bits and -permission bits (see -.BR chmod (2)). -.SH "RETURN VALUE -Upon successful completion a value of 0 is returned. -Otherwise, a value of \-1 is returned and -.B errno -is set to indicate the error. -.SH "ERRORS -.B Stat -and -.B lstat -will fail if one or more of the following are true: -.TP 15 -[ENOTDIR] -A component of the path prefix is not a directory. -.TP 15 -[ENAMETOOLONG] -The path name exceeds PATH_MAX characters. -.TP 15 -[ENOENT] -The named file does not exist. -.TP 15 -[EACCES] -Search permission is denied for a component of the path prefix. -.TP 15 -[ELOOP] -Too many symbolic links were encountered in translating the pathname. -.TP 15 -[EFAULT] -.I Buf -or -.I name -points to an invalid address. -.TP 15 -[EIO] -An I/O error occurred while reading from or writing to the file system. -.PP -.B Fstat -will fail if one or both of the following are true: -.TP 15 -[EBADF] -.I Fildes -is not a valid open file descriptor. -.TP 15 -[EFAULT] -.I Buf -points to an invalid address. -.TP 15 -[EIO] -An I/O error occurred while reading from or writing to the file system. -.SH "SEE ALSO" -.BR chmod (2), -.BR chown (2), -.BR utime (2). diff --git a/nbsd_include/sys/stat.h b/nbsd_include/sys/stat.h index 92cd78517..27324e622 100644 --- a/nbsd_include/sys/stat.h +++ b/nbsd_include/sys/stat.h @@ -8,62 +8,66 @@ #include #endif -/* - * __MINIX_EMULATE_NETBSD_STAT - * - * Userspace flag to emulate netbsd stat structure. - */ -#ifdef __MINIX_EMULATE_NETBSD_STAT -#define __netbsd_stat stat -#else -#define __minix_stat stat -#endif -struct __minix_stat { - dev_t st_dev; /* major/minor device number */ - ino_t st_ino; /* i-node number */ - mode_t st_mode; /* file mode, protection bits, etc. */ - nlink_t st_nlink; /* # links; */ - uid_t st_uid; /* uid of the file's owner */ - gid_t st_gid; /* gid */ - dev_t st_rdev; - off_t st_size; /* file size */ - time_t st_atime; /* time of last access */ - time_t st_mtime; /* time of last data modification */ - time_t st_ctime; /* time of last file status change */ +struct stat { + big_dev_t st_dev; /* inode's device */ + big_mode_t st_mode; /* inode protection mode */ + big_ino_t st_ino; /* inode's number */ + big_nlink_t st_nlink; /* number of hard links */ + big_uid_t st_uid; /* user ID of the file's owner */ + big_gid_t st_gid; /* group ID of the file's group */ + big_dev_t st_rdev; /* device type */ +#if defined(_NETBSD_SOURCE) + struct timespec st_atimespec;/* time of last access */ + struct timespec st_mtimespec;/* time of last data modification */ + struct timespec st_ctimespec;/* time of last file status change */ + struct timespec st_birthtimespec; /* time of creation */ +#else + time_t st_atime; /* time of last access */ + long st_atimensec; /* nsec of last access */ + time_t st_mtime; /* time of last data modification */ + long st_mtimensec; /* nsec of last data modification */ + time_t st_ctime; /* time of last file status change */ + long st_ctimensec; /* nsec of last file status change */ + time_t st_birthtime; /* time of creation */ + long st_birthtimensec; /* nsec of time of creation */ +#endif + big_off_t st_size; /* file size, in bytes */ + blkcnt_t st_blocks; /* blocks allocated for file */ + blksize_t st_blksize; /* optimal blocksize for I/O */ + u32_t st_flags; /* user defined flags for file */ + u32_t st_gen; /* file generation number */ + u32_t st_spare[2]; }; + +struct minix_prev_stat { + dev_t st_dev; /* major/minor device number */ + ino_t st_ino; /* i-node number */ + mode_t st_mode; /* file mode, protection bits, etc. */ + nlink_t st_nlink; /* # links; */ + uid_t st_uid; /* uid of the file's owner */ + short int st_gid; /* gid; TEMPORARY HACK: should be gid_t */ + dev_t st_rdev; + off_t st_size; /* file size */ + time_t st_atime; /* time of last access */ + time_t st_mtime; /* time of last data modification */ + time_t st_ctime; /* time of last file status change */ +}; + + #if defined(_NETBSD_SOURCE) -struct __netbsd_stat { - dev_t st_dev; /* major/minor device number */ - ino_t st_ino; /* i-node number */ - mode_t st_mode; /* file mode, protection bits, etc. */ - nlink_t st_nlink; /* # links; */ - uid_t st_uid; /* uid of the file's owner */ - gid_t st_gid; /* gid */ - dev_t st_rdev; - off_t st_size; /* file size */ - time_t st_atime; /* time of last access */ - time_t st_mtime; /* time of last data modification */ - time_t st_ctime; /* time of last file status change */ +/* XXX after updating stat struct we don't want to update all the code */ +#define st_atime st_atimespec.tv_sec +#define st_mtime st_mtimespec.tv_sec +#define st_ctime st_ctimespec.tv_sec +#define st_birthtime st_birthtimespec.tv_sec +#define st_atimensec st_atimespec.tv_nsec +#define st_mtimensec st_mtimespec.tv_nsec +#define st_ctimensec st_ctimespec.tv_nsec +#define st_birthtimensec st_birthtimespec.tv_nsec +#endif - /* XXX: Currently not supported by Minix, and here are just emulated. */ - struct timespec st_atimespec;/* time of last access */ - struct timespec st_mtimespec;/* time of last data modification */ - struct timespec st_ctimespec;/* time of last file status change */ - struct timespec st_birthtimespec; /* time of creation */ - blkcnt_t st_blocks; /* blocks allocated for file */ - blksize_t st_blksize; /* optimal blocksize for I/O */ -}; - -#ifdef __MINIX_EMULATE_NETBSD_STAT -#define st_atimensec st_atimespec.tv_nsec -#define st_mtimensec st_mtimespec.tv_nsec -#define st_ctimensec st_ctimespec.tv_nsec -#define st_birthtime st_birthtimespec.tv_sec -#define st_birthtimensec st_birthtimespec.tv_nsec -#endif -#endif /* _NETBSD_SOURCE */ #define S_ISUID 0004000 /* set user id on execution */ #define S_ISGID 0002000 /* set group id on execution */ @@ -153,21 +157,12 @@ __BEGIN_DECLS int chmod(const char *, mode_t); int mkdir(const char *, mode_t); int mkfifo(const char *, mode_t); -#ifdef __MINIX_EMULATE_NETBSD_STAT -int stat(const char *, struct stat *) __RENAME(__emu_netbsd_stat); -int fstat(int, struct stat *) __RENAME(__emu_netbsd_fstat); -#else -int stat(const char *, struct stat *) __RENAME(__orig_minix_stat); -int fstat(int, struct stat *) __RENAME(__orig_minix_fstat); -#endif +int stat(const char *, struct stat *) __RENAME(_stat); +int fstat(int, struct stat *) __RENAME(_fstat); +int lstat(const char *, struct stat *) __RENAME(_lstat); mode_t umask(mode_t); #if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE) int fchmod(int, mode_t); -#ifdef __MINIX_EMULATE_NETBSD_STAT -int lstat(const char *, struct stat *) __RENAME(__emu_netbsd_lstat); -#else -int lstat(const char *, struct stat *) __RENAME(__orig_minix_lstat); -#endif int mknod(const char *, mode_t, dev_t) __RENAME(__mknod50); #endif /* defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE) */ __END_DECLS diff --git a/nbsd_include/sys/types.h b/nbsd_include/sys/types.h index 41f403c2b..546641a8c 100644 --- a/nbsd_include/sys/types.h +++ b/nbsd_include/sys/types.h @@ -105,6 +105,14 @@ typedef int16_t i16_t; typedef int32_t i32_t; typedef int64_t i64_t; +typedef uint64_t big_ino_t; +typedef int64_t big_off_t; +typedef u32_t big_dev_t; +typedef u32_t big_gid_t; +typedef u32_t big_mode_t; +typedef u32_t big_nlink_t; +typedef u32_t big_uid_t; + /* some Minix specific types that do not conflict with posix */ typedef u32_t zone_t; /* zone number */ diff --git a/servers/ext2/stadir.c b/servers/ext2/stadir.c index 43036c1f0..720d5e7ed 100644 --- a/servers/ext2/stadir.c +++ b/servers/ext2/stadir.c @@ -3,6 +3,7 @@ */ #include "fs.h" +#include #include #include #include @@ -35,6 +36,8 @@ PRIVATE int stat_inode( /* true iff special */ s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL); + memset(&statbuf, 0, sizeof(struct stat)); + statbuf.st_dev = rip->i_dev; statbuf.st_ino = rip->i_num; statbuf.st_mode = rip->i_mode; @@ -46,6 +49,8 @@ PRIVATE int stat_inode( statbuf.st_atime = rip->i_atime; statbuf.st_mtime = rip->i_mtime; statbuf.st_ctime = rip->i_ctime; + statbuf.st_blksize = rip->i_sp->s_block_size; + statbuf.st_blocks = rip->i_blocks; /* Copy the struct to user space. */ r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf, diff --git a/servers/hgfs/stat.c b/servers/hgfs/stat.c index df8c23d70..727302c46 100644 --- a/servers/hgfs/stat.c +++ b/servers/hgfs/stat.c @@ -62,6 +62,8 @@ PUBLIC int do_stat() if ((r = verify_inode(ino, path, &attr)) != OK) return r; + memset(&stat, 0, sizeof(struct stat)); + stat.st_dev = state.dev; stat.st_ino = ino_nr; stat.st_mode = get_mode(ino, attr.a_mode); @@ -76,6 +78,12 @@ PUBLIC int do_stat() stat.st_mtime = attr.a_mtime; stat.st_ctime = attr.a_ctime; + stat.st_blocks = stat.st_size / S_BLKSIZE; + if (stat.st_size % S_BLKSIZE != 0) + stat.st_blocks += 1; + + stat.st_blksize = BLOCK_SIZE; + /* We could make this more accurate by iterating over directory inodes' * children, counting how many of those are directories as well. * It's just not worth it. diff --git a/servers/iso9660fs/stadir.c b/servers/iso9660fs/stadir.c index a637ae1f4..8fa86a4b0 100644 --- a/servers/iso9660fs/stadir.c +++ b/servers/iso9660fs/stadir.c @@ -1,4 +1,5 @@ #include "inc.h" +#include #include #include #include @@ -29,6 +30,14 @@ PRIVATE int stat_dir_record( int r; struct tm ltime; time_t time1; + u32_t blocks; + + blocks = v_pri.volume_space_size_l; + /* The unit of blocks should be 512 */ + assert(v_pri.logical_block_size_l >= 512); + blocks = blocks * (v_pri.logical_block_size_l >> 9); + + memset(&statbuf, 0, sizeof(struct stat)); statbuf.st_dev = fs_dev; /* the device of the file */ statbuf.st_ino = ID_DIR_RECORD(dir); /* the id of the dir record */ @@ -38,6 +47,8 @@ PRIVATE int stat_dir_record( statbuf.st_gid = 0; /* group operator */ statbuf.st_rdev = NO_DEV; statbuf.st_size = dir->d_file_size; /* size of the file */ + statbuf.st_blksize = v_pri.logical_block_size_l; + statbuf.st_blocks = blocks; ltime.tm_year = dir->rec_date[0]; ltime.tm_mon = dir->rec_date[1] - 1; diff --git a/servers/mfs/stadir.c b/servers/mfs/stadir.c index 3f2a205cf..0e980bdd4 100644 --- a/servers/mfs/stadir.c +++ b/servers/mfs/stadir.c @@ -1,4 +1,6 @@ #include "fs.h" +#include +#include #include #include #include @@ -21,6 +23,7 @@ PRIVATE int stat_inode( struct stat statbuf; mode_t mo; int r, s; + u32_t blocks; /* The unit of this is 512 */ /* Update the atime, ctime, and mtime fields in the inode, if need be. */ if (rip->i_update) update_times(rip); @@ -31,6 +34,12 @@ PRIVATE int stat_inode( /* true iff special */ s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL); + blocks = rip->i_size / 512; + if (rip->i_size % 512 != 0) + blocks += 1; + + memset(&statbuf, 0, sizeof(struct stat)); + statbuf.st_dev = rip->i_dev; statbuf.st_ino = rip->i_num; statbuf.st_mode = rip->i_mode; @@ -42,6 +51,8 @@ PRIVATE int stat_inode( statbuf.st_atime = rip->i_atime; statbuf.st_mtime = rip->i_mtime; statbuf.st_ctime = rip->i_ctime; + statbuf.st_blksize = fs_block_size; + statbuf.st_blocks = blocks; /* Copy the struct to user space. */ r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf, diff --git a/servers/pfs/stadir.c b/servers/pfs/stadir.c index 707301a07..345d24ec9 100644 --- a/servers/pfs/stadir.c +++ b/servers/pfs/stadir.c @@ -1,5 +1,6 @@ #include "fs.h" #include "inode.h" +#include #include @@ -15,6 +16,7 @@ PRIVATE int stat_inode( /* Common code for stat and fstat system calls. */ mode_t type; struct stat statbuf; + u32_t blocks; /* The unit of this is 512 */ int r, s; type = rip->i_mode & I_TYPE; @@ -23,6 +25,12 @@ PRIVATE int stat_inode( /* Update the atime, ctime, and mtime fields in the inode, if need be. */ if (rip->i_update) update_times(rip); + blocks = rip->i_size / S_BLKSIZE; + if (rip->i_size % S_BLKSIZE != 0) + blocks += 1; + + memset(&statbuf, 0, sizeof(struct stat)); + statbuf.st_dev = rip->i_dev; statbuf.st_ino = rip->i_num; statbuf.st_mode = rip->i_mode; @@ -35,6 +43,8 @@ PRIVATE int stat_inode( statbuf.st_atime = rip->i_atime; statbuf.st_mtime = rip->i_mtime; statbuf.st_ctime = rip->i_ctime; + statbuf.st_blksize = PIPE_BUF; + statbuf.st_blocks = blocks; /* Copy the struct to user space. */ r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf, diff --git a/servers/pm/table.c b/servers/pm/table.c index 8fdc6683d..444455dc2 100644 --- a/servers/pm/table.c +++ b/servers/pm/table.c @@ -61,7 +61,7 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = { do_get, /* 47 = getgid */ no_sys, /* 48 = (signal)*/ no_sys, /* 49 = unused */ - no_sys, /* 50 = unused */ + no_sys, /* 50 = lstat */ no_sys, /* 51 = (acct) */ no_sys, /* 52 = (phys) */ no_sys, /* 53 = (lock) */ diff --git a/servers/rs/exec.c b/servers/rs/exec.c index 040c8a6b0..39c98914d 100644 --- a/servers/rs/exec.c +++ b/servers/rs/exec.c @@ -12,7 +12,7 @@ static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes, vir_bytes data_addr, vir_bytes data_bytes, vir_bytes tot_bytes, vir_bytes frame_len, int sep_id, int is_elf, - dev_t st_dev, ino_t st_ino, time_t st_ctime, char *progname, + dev_t st_dev, ino_t st_ino, time_t ctime, char *progname, int new_uid, int new_gid, vir_bytes *stack_topp, int *load_textp, int *allow_setuidp); static void patch_ptr(char stack[ARG_MAX], vir_bytes base); @@ -321,7 +321,7 @@ static int exec_newmem( int is_elf, dev_t st_dev, ino_t st_ino, - time_t st_ctime, + time_t ctime, char *progname, int new_uid, int new_gid, @@ -344,7 +344,7 @@ static int exec_newmem( e.is_elf= is_elf; e.st_dev= st_dev; e.st_ino= st_ino; - e.st_ctime= st_ctime; + e.enst_ctime= ctime; e.new_uid= new_uid; e.new_gid= new_gid; strncpy(e.progname, progname, sizeof(e.progname)-1); diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index b78ca8b07..679667456 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -38,7 +38,7 @@ static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes, vir_bytes data_addr, vir_bytes data_bytes, vir_bytes tot_bytes, vir_bytes frame_len, int sep_id, - int is_elf, dev_t st_dev, ino_t st_ino, time_t st_ctime, + int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime, char *progname, int new_uid, int new_gid, vir_bytes *stack_topp, int *load_textp, int *allow_setuidp); @@ -129,7 +129,7 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, r = r1; else r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR, - (char *) &(execi.sb), 0); + (char *) &(execi.sb), 0, 0); if (r != OK) { put_vnode(vp); return(r); @@ -314,7 +314,7 @@ static int exec_newmem( int is_elf, dev_t st_dev, ino_t st_ino, - time_t st_ctime, + time_t ctime, char *progname, int new_uid, int new_gid, @@ -337,7 +337,7 @@ static int exec_newmem( e.is_elf = is_elf; e.st_dev = st_dev; e.st_ino = st_ino; - e.st_ctime = st_ctime; + e.enst_ctime = ctime; e.new_uid = new_uid; e.new_gid = new_gid; strncpy(e.progname, progname, sizeof(e.progname)-1); diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 443e135d3..be51cdc9d 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -226,7 +226,7 @@ _PROTOTYPE(int req_slink, (endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t who_e, char *path_addr, unsigned short path_length, uid_t uid, gid_t gid) ); _PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e, - char *buf, int pos) ); + char *buf, int pos, int stat_version) ); _PROTOTYPE( int req_sync, (endpoint_t fs_e) ); _PROTOTYPE( int req_unlink, (endpoint_t fs_e, ino_t inode_nr, char *lastc) ); diff --git a/servers/vfs/request.c b/servers/vfs/request.c index b6d32c3ba..277300349 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -9,6 +9,7 @@ #include "fs.h" #include +#include #include #include #include @@ -925,19 +926,21 @@ PUBLIC int req_slink( /*===========================================================================* * req_stat * *===========================================================================*/ -PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos) +PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos, stat_version) int fs_e; ino_t inode_nr; int who_e; char *buf; int pos; +int stat_version; { cp_grant_id_t grant_id; int r; message m; struct stat sb; + struct minix_prev_stat old_sb; /* for backward compatibility */ - if (pos != 0) + if (pos != 0 || stat_version != 0) grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb, sizeof(struct stat), CPF_WRITE); else @@ -956,11 +959,51 @@ int pos; r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); - if (r == OK && pos != 0) { - sb.st_size -= pos; - r = sys_vircopy(SELF, D, (vir_bytes) &sb, who_e, D, (vir_bytes) buf, - sizeof(struct stat)); + if (r != OK || (pos == 0 && stat_version == 0)) + return(r); + + if (pos != 0) + sb.st_size -= pos; + if (stat_version == 0) { + r = sys_vircopy(SELF, D, (vir_bytes) &sb, who_e, D, (vir_bytes) buf, + sizeof(struct stat)); + return(r); } + + /* User needs old struct stat. + * Just 1 prev version at this moment */ + assert(stat_version == 1); + +/* XXX until that st_Xtime macroses used, we have to undefine them, + * because of minix_prev_stat + */ +#undef st_atime +#undef st_ctime +#undef st_mtime + +/* Copy field by field because of st_gid type mismath and + * difference in order after atime. + */ + old_sb.st_dev = sb.st_dev; + old_sb.st_ino = sb.st_ino; + old_sb.st_mode = sb.st_mode; + old_sb.st_nlink = sb.st_nlink; + old_sb.st_uid = sb.st_uid; + old_sb.st_gid = sb.st_gid; + old_sb.st_rdev = sb.st_rdev; + old_sb.st_size = sb.st_size; +#if defined(_NETBSD_SOURCE) + old_sb.st_atime = sb.st_atimespec.tv_sec; + old_sb.st_mtime = sb.st_mtimespec.tv_sec; + old_sb.st_ctime = sb.st_ctimespec.tv_sec; +#else + old_sb.st_atime = sb.st_atime; + old_sb.st_mtime = sb.st_mtime; + old_sb.st_ctime = sb.st_ctime; +#endif + + r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, who_e, D, (vir_bytes) buf, + sizeof(struct minix_prev_stat)); return(r); } diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index 55d80c290..2517a7a6d 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -22,6 +22,7 @@ #include "fproc.h" #include "param.h" #include +#include #include "vnode.h" #include "vmnt.h" @@ -121,10 +122,14 @@ PUBLIC int do_stat() /* Perform the stat(name, buf) system call. */ int r; struct vnode *vp; + int old_stat = 0; + + if (call_nr == PREV_STAT) + old_stat = 1; if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code); - r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0); + r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat); put_vnode(vp); return r; @@ -139,6 +144,10 @@ PUBLIC int do_fstat() /* Perform the fstat(fd, buf) system call. */ register struct filp *rfilp; int pipe_pos = 0; + int old_stat = 0; + + if (call_nr == PREV_FSTAT) + old_stat = 1; /* Is the file descriptor valid? */ if ((rfilp = get_filp(m_in.fd)) == NULL) return(err_code); @@ -153,7 +162,7 @@ PUBLIC int do_fstat() } return req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, - who_e, m_in.buffer, pipe_pos); + who_e, m_in.buffer, pipe_pos, old_stat); } @@ -212,10 +221,14 @@ PUBLIC int do_lstat() /* Perform the lstat(name, buf) system call. */ struct vnode *vp; int r; + int old_stat = 0; + + if (call_nr == PREV_LSTAT) + old_stat = 1; if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); if ((vp = eat_path(PATH_RET_SYMLINK, fp)) == NULL) return(err_code); - r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0); + r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat); put_vnode(vp); return(r); diff --git a/servers/vfs/table.c b/servers/vfs/table.c index b2557df8a..5385e7b14 100644 --- a/servers/vfs/table.c +++ b/servers/vfs/table.c @@ -33,7 +33,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = { do_chmod, /* 15 = chmod */ do_chown, /* 16 = chown */ no_sys, /* 17 = break */ - do_stat, /* 18 = stat */ + do_stat, /* 18 = stat (prev)*/ do_lseek, /* 19 = lseek */ no_sys, /* 20 = getpid */ do_mount, /* 21 = mount */ @@ -43,7 +43,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = { no_sys, /* 25 = (stime) */ no_sys, /* 26 = ptrace */ no_sys, /* 27 = alarm */ - do_fstat, /* 28 = fstat */ + do_fstat, /* 28 = fstat (prev)*/ no_sys, /* 29 = pause */ do_utime, /* 30 = utime */ no_sys, /* 31 = (stty) */ @@ -65,7 +65,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = { no_sys, /* 47 = getgid */ no_sys, /* 48 = (signal)*/ do_rdlink, /* 49 = readlink*/ - do_lstat, /* 50 = lstat */ + do_lstat, /* 50 = lstat (prev)*/ no_sys, /* 51 = (acct) */ no_sys, /* 52 = (phys) */ no_sys, /* 53 = (lock) */ @@ -80,9 +80,9 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = { no_sys, /* 62 = (setsid)*/ no_sys, /* 63 = (getpgrp)*/ no_sys, /* 64 = (itimer)*/ - no_sys, /* 65 = unused */ - no_sys, /* 66 = unused */ - no_sys, /* 67 = unused */ + do_stat, /* 65 = stat */ + do_fstat, /* 66 = fstat */ + do_lstat, /* 67 = lstat */ no_sys, /* 68 = unused */ no_sys, /* 69 = unused */ no_sys, /* 70 = unused */ diff --git a/servers/vm/exec.c b/servers/vm/exec.c index 8bbf0dcf7..bd520b691 100644 --- a/servers/vm/exec.c +++ b/servers/vm/exec.c @@ -113,7 +113,7 @@ SANITYCHECK(SCL_DETAIL); /* Save file identification to allow it to be shared. */ vmp->vm_ino = args.st_ino; vmp->vm_dev = args.st_dev; - vmp->vm_ctime = args.st_ctime; + vmp->vm_ctime = args.enst_ctime; /* set/clear separate I&D flag */ if (args.sep_id)