Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/compat/sunos32 implement stat & fstat properly.



details:   https://anonhg.NetBSD.org/src/rev/48ebf2049527
branches:  trunk
changeset: 503186:48ebf2049527
user:      mrg <mrg%NetBSD.org@localhost>
date:      Fri Feb 02 13:00:29 2001 +0000

description:
implement stat & fstat properly.

diffstat:

 sys/compat/sunos32/sunos32_misc.c |  148 +++++++++++++++++++++++++++++--------
 1 files changed, 114 insertions(+), 34 deletions(-)

diffs (179 lines):

diff -r dadea28eab79 -r 48ebf2049527 sys/compat/sunos32/sunos32_misc.c
--- a/sys/compat/sunos32/sunos32_misc.c Fri Feb 02 12:59:43 2001 +0000
+++ b/sys/compat/sunos32/sunos32_misc.c Fri Feb 02 13:00:29 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sunos32_misc.c,v 1.1 2001/02/02 07:28:54 mrg Exp $     */
+/*     $NetBSD: sunos32_misc.c,v 1.2 2001/02/02 13:00:29 mrg Exp $     */
 /* from :NetBSD: sunos_misc.c,v 1.107 2000/12/01 19:25:10 jdolecek Exp */
 
 /*
@@ -217,6 +217,37 @@
        return (sys_access(p, &ua, retval));
 }
 
+static __inline void sunos32_from___stat13 __P((struct stat *, struct stat43 *));
+
+static __inline void
+sunos32_from___stat13(sbp, sb32p)
+       struct stat *sbp;
+       struct stat43 *sb32p;
+{
+       sb32p->st_dev = sbp->st_dev;
+       sb32p->st_ino = sbp->st_ino;
+       sb32p->st_mode = sbp->st_mode;
+       sb32p->st_nlink = sbp->st_nlink;
+       sb32p->st_uid = sbp->st_uid;
+       sb32p->st_gid = sbp->st_gid;
+       sb32p->st_rdev = sbp->st_rdev;
+       if (sbp->st_size < (quad_t)1 << 32)
+               sb32p->st_size = sbp->st_size;
+       else
+               sb32p->st_size = -2;
+       sb32p->st_atimespec.tv_sec = (netbsd32_time_t)sbp->st_atimespec.tv_sec;
+       sb32p->st_atimespec.tv_nsec = (netbsd32_long)sbp->st_atimespec.tv_nsec;
+       sb32p->st_mtimespec.tv_sec = (netbsd32_time_t)sbp->st_mtimespec.tv_sec;
+       sb32p->st_mtimespec.tv_nsec = (netbsd32_long)sbp->st_mtimespec.tv_nsec;
+       sb32p->st_ctimespec.tv_sec = (netbsd32_time_t)sbp->st_ctimespec.tv_sec;
+       sb32p->st_ctimespec.tv_nsec = (netbsd32_long)sbp->st_ctimespec.tv_nsec;
+       sb32p->st_blksize = sbp->st_blksize;
+       sb32p->st_blocks = sbp->st_blocks;
+       sb32p->st_flags = sbp->st_flags;
+       sb32p->st_gen = sbp->st_gen;
+}
+
+
 int
 sunos32_sys_stat(p, v, retval)
        struct proc *p;
@@ -224,24 +255,27 @@
        register_t *retval;
 {
        struct sunos32_sys_stat_args *uap = v;
-       struct netbsd32_stat43 *sp32;
-       struct stat43 sb43;
-       struct stat43 *sp43 = &sb43;
-       struct compat_43_sys_stat_args ua;
-       int rv;
+       struct stat43 sb32;
+       struct stat sb;
+       struct nameidata nd;
        caddr_t sg;
+       const char *path;
+       int error;
+
+       path = (char *)(u_long)SCARG(uap, path);
+       sg = stackgap_init(p->p_emul);
+       SUNOS32_CHECK_ALT_EXIST(p, &sg, path);
 
-       SUNOS32TOP_UAP(path, const char);
-       SCARG(&ua, ub) = &sb43;
-       sg = stackgap_init(p->p_emul);
-       SUNOS32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
-
-       rv = compat_43_sys_stat(p, &ua, retval);
-
-       sp32 = (struct netbsd32_stat43 *)(u_long)SCARG(uap, ub);
-       netbsd32_from_stat43(sp43, sp32);
-
-       return (rv);
+       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, path, p);
+       if ((error = namei(&nd)) != 0)
+               return (error);
+       error = vn_stat(nd.ni_vp, &sb, p);
+       vput(nd.ni_vp);
+       if (error)
+               return (error);
+       sunos32_from___stat13(&sb, &sb32);
+       error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32));
+       return (error);
 }
 
 int
@@ -251,24 +285,70 @@
        register_t *retval;
 {
        struct sunos32_sys_lstat_args *uap = v;
-       struct compat_43_sys_lstat_args ua;
-       struct netbsd32_stat43 *sp32;
-       struct stat43 sb43;
-       struct stat43 *sp43 = &sb43;
-       caddr_t sg = stackgap_init(p->p_emul);
-       int rv;
+       struct vnode *vp, *dvp;
+       struct stat sb, sb1;
+       struct stat43 sb32;
+       int error;
+       struct nameidata nd;
+       int ndflags;
+       const char *path;
+       caddr_t sg;
+
+       path = (char *)(u_long)SCARG(uap, path);
+       sg = stackgap_init(p->p_emul);
+       SUNOS32_CHECK_ALT_EXIST(p, &sg, path);
 
-       SUNOS32TOP_UAP(path, const char);
-       SCARG(&ua, ub) = &sb43;
-       sg = stackgap_init(p->p_emul);
-       SUNOS32_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
-
-       rv = compat_43_sys_stat(p, &ua, retval);
-
-       sp32 = (struct netbsd32_stat43 *)(u_long)SCARG(uap, ub);
-       netbsd32_from_stat43(sp43, sp32);
-
-       return (rv);
+       ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT;
+again:
+       NDINIT(&nd, LOOKUP, ndflags, UIO_USERSPACE, path, p);
+       if ((error = namei(&nd))) {
+               if (error == EISDIR && (ndflags & LOCKPARENT) != 0) {
+                       /*
+                        * Should only happen on '/'. Retry without LOCKPARENT;
+                        * this is safe since the vnode won't be a VLNK.
+                        */
+                       ndflags &= ~LOCKPARENT;
+                       goto again;
+               }
+               return (error);
+       }
+       /*
+        * For symbolic links, always return the attributes of its
+        * containing directory, except for mode, size, and links.
+        */
+       vp = nd.ni_vp;
+       dvp = nd.ni_dvp;
+       if (vp->v_type != VLNK) {
+               if ((ndflags & LOCKPARENT) != 0) {
+                       if (dvp == vp)
+                               vrele(dvp);
+                       else
+                               vput(dvp);
+               }
+               error = vn_stat(vp, &sb, p);
+               vput(vp);
+               if (error)
+                       return (error);
+       } else {
+               error = vn_stat(dvp, &sb, p);
+               vput(dvp);
+               if (error) {
+                       vput(vp);
+                       return (error);
+               }
+               error = vn_stat(vp, &sb1, p);
+               vput(vp);
+               if (error)
+                       return (error);
+               sb.st_mode &= ~S_IFDIR;
+               sb.st_mode |= S_IFLNK;
+               sb.st_nlink = sb1.st_nlink;
+               sb.st_size = sb1.st_size;
+               sb.st_blocks = sb1.st_blocks;
+       }
+       sunos32_from___stat13(&sb, &sb32);
+       error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32));
+       return (error);
 }
 
 int



Home | Main Index | Thread Index | Old Index