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)