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).
This commit is contained in:
Evgeniy Ivanov 2011-07-01 23:35:54 +04:00 committed by Ben Gras
parent 48331843ea
commit ef0a265086
34 changed files with 533 additions and 417 deletions

View file

@ -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 },
};

View file

@ -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.
*/

View file

@ -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 */

View file

@ -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

View file

@ -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) );

View file

@ -10,7 +10,43 @@
#include <minix/types.h>
#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 */

View file

@ -1,14 +1,35 @@
#include <lib.h>
#define fstat _fstat
#include <sys/stat.h>
#include <string.h>
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;
}

View file

@ -1,6 +1,5 @@
#include <lib.h>
#define lstat _lstat
#define stat _stat
#include <sys/stat.h>
#include <string.h>
@ -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;
}

View file

@ -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;
}

View file

@ -5,6 +5,7 @@
#include <time.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
#include <string.h>
/*===========================================================================*
* 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);

View file

@ -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)

View file

@ -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);
}

View file

@ -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 <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#ifdef notdef
@@ -88,7 +92,9 @@
@@ -88,7 +88,9 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
@ -2205,7 +2206,7 @@ diff -ru nbsdsrc/src/lib/libc/resolv/res_init.c lib/nbsd_libc/resolv/res_init.c
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -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);
}

View file

@ -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 <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#ifdef notdef

View file

@ -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;
}

View file

@ -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);
}

View file

@ -5,101 +5,126 @@
#include <sys/stat.h>
#include <string.h>
#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;
}

View file

@ -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

View file

@ -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 <sys/types.h>
#include <sys/stat.h>
.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).

View file

@ -8,62 +8,66 @@
#include <sys/time.h>
#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

View file

@ -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 */

View file

@ -3,6 +3,7 @@
*/
#include "fs.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
@ -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,

View file

@ -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.

View file

@ -1,4 +1,5 @@
#include "inc.h"
#include <assert.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
@ -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;

View file

@ -1,4 +1,6 @@
#include "fs.h"
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
@ -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,

View file

@ -1,5 +1,6 @@
#include "fs.h"
#include "inode.h"
#include <string.h>
#include <sys/stat.h>
@ -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,

View file

@ -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) */

View file

@ -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);

View file

@ -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);

View file

@ -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) );

View file

@ -9,6 +9,7 @@
#include "fs.h"
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
@ -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);
}

View file

@ -22,6 +22,7 @@
#include "fproc.h"
#include "param.h"
#include <minix/vfsif.h>
#include <minix/callnr.h>
#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);

View file

@ -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 */

View file

@ -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)