📄 vnodeops_gfs.c
字号:
goto bad; } gp = *gpp; if (access(gp, GWRITE)) goto bad; if ((gp->g_mode&GFMT) == GFDIR) { u.u_error = EISDIR; goto bad; } if (vap->va_size == 0) { if (GTRUNC(gp, (u_long) 0, u.u_cred) == GNOFUNC) { u.u_error == EOPNOTSUPP; } if (u.u_error) goto bad; } } return(u.u_error);bad: gput(*gpp);bad2: /* entry for *gpp already unlocked */ *gpp = NULL; return (u.u_error);}intvop_remove(pgp, name, cred) struct gnode *pgp; char *name; struct ucred *cred;{ struct nameidata *ndp = &u.u_nd; struct gnode *gp; ndp->ni_nameiop = DELETE | LOCKPARENT | NOMOUNT; ndp->ni_dirp = name; u.u_cdir = pgp; gfs_unlock(pgp); gp = GNAMEI(ndp); if (gp == NULL) { return (u.u_error); } /* Can't unlink directories -- use vop_rmdir. */ if ((gp->g_mode & GFMT) == GFDIR) { u.u_error = EISDIR; goto out; } if (gp->g_dev != pgp->g_dev) { u.u_error = EBUSY; goto out; } if (gp->g_flag & GTEXT) xrele(gp); GUNLINK(gp, ndp);out: if (gp != pgp) gput(gp); gput(pgp); return (u.u_error);}intvop_link(sgp, tdgp, name, savectime, cred) struct gnode *sgp; struct gnode *tdgp; char *name; struct timeval *savectime; struct ucred *cred;{ register struct nameidata *ndp = &u.u_nd; struct gnode *gp; int error = 0; if (sgp->g_nlink >= LINK_MAX) { gput(sgp); grele(tdgp); u.u_error = EMLINK; return (u.u_error); } if (((sgp->g_mode & GFMT) == GFDIR) && !suser()) { gput(sgp); grele(tdgp); u.u_error = EPERM; return (u.u_error); } sgp->g_nlink++; sgp->g_flag |= GCHG; (void) GUPDATE(sgp, timepick, timepick, 1, cred); /* save ctime for successful cases */ *savectime = sgp->g_ctime; /* save ctime for successful cases */ ndp->ni_nameiop = CREATE | NOMOUNT; ndp->ni_dirp = name; u.u_cdir = tdgp; gfs_unlock(sgp); gp = GNAMEI(ndp); if (u.u_error) { error = u.u_error; goto errout; } if (gp) { gput(gp); error = EEXIST; goto errout; } if (sgp->g_mp != tdgp->g_mp) { error = EXDEV; goto errout; } /* The UFS routine will do the de-referencing */ (void) GLINK(sgp, ndp); grele(tdgp); return (u.u_error);errout: gfs_lock(sgp); sgp->g_nlink--; sgp->g_flag |= GCHG; (void) GUPDATE(sgp, timepick, timepick, 1, cred); /* don't bother saving ctime for unsuccessful cases */ gput(sgp); grele(tdgp); return (u.u_error = error);}intvop_rename(sdp, sname, tdp, tname, cred) struct gnode *sdp; char *sname; struct gnode *tdp; char *tname; struct ucred *cred;{ struct nameidata tnd; struct nameidata *sndp = &u.u_nd; struct gnode *sgp; int ret; tnd.ni_nameiop = CREATE | LOCKPARENT | NOMOUNT; tnd.ni_segflg = UIO_SYSSPACE; tnd.ni_dirp = tname; /* * If sname is a symbolic link, ni_dirp can be bogus * when passed down to the local rename routine. SAVE_DIRP * ensures the original ni_dirp remains in tact. */ sndp->ni_nameiop = DELETE | LOCKPARENT | NOMOUNT | SAVE_DIRP; sndp->ni_dirp = sname; u.u_cdir = sdp; /* * XXX - Unlock sdp and tdp to guard against * rename("/mnt/a", "/mnt/a/b") */ gfs_unlock(sdp); if (tdp != sdp) gfs_unlock(tdp); sgp = GNAMEI(sndp); if (sgp == NULL) { return (u.u_error); } /* * XXX (cont) - If sgp and tdp are equal, target * is a direct descendent of source. */ if (sgp == tdp) { gput(sgp); if (sgp == sdp) grele(sdp); else gput(sdp); u.u_error = EINVAL; return (u.u_error); } if (sgp->g_flag & GMOUNT) { gput(sgp); if (sgp == sdp) grele(sdp); else gput(sdp); u.u_error = EBUSY; return (u.u_error); } u.u_cdir = tdp; ret = GRENAMEG(sgp, sdp, sndp, tdp, &tnd, NOMOUNT); return (u.u_error);}intvop_symlink(pgp, fname, vap, tname, cred) struct gnode *pgp; char *fname; struct vattr *vap; /* NOT DEALT WITH */ char *tname; struct ucred *cred;{ register struct nameidata *ndp = &u.u_nd; struct uio auio; struct iovec aiov; register struct gnode *gp; ndp->ni_nameiop = CREATE | LOCKPARENT | NOMOUNT; ndp->ni_dirp = fname; u.u_cdir = pgp; gfs_unlock(pgp); gp = GNAMEI(ndp); if (gp) { gput(gp); gput(ndp->ni_pdir); return (EEXIST); } if (u.u_error) return (u.u_error); if(GSYMLINK(ndp, tname) == GNOFUNC) u.u_error = EOPNOTSUPP; return (u.u_error);}intvop_mkdir(pgp, name, vap, gpp, cred) struct gnode *pgp; char *name; struct vattr *vap; struct gnode **gpp; struct ucred *cred;{ register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = CREATE | LOCKPARENT | NOMOUNT; ndp->ni_dirp = name; u.u_cdir = pgp; gfs_unlock(pgp); *gpp = GNAMEI(ndp); if (u.u_error) { return (u.u_error); } if (*gpp != NULL) { gput(*gpp); gput(ndp->ni_pdir); return (EEXIST); } *gpp = GMKDIR(ndp->ni_pdir, name, vap->va_mode); return (u.u_error); }intvop_rmdir(pgp, name, cred) struct gnode *pgp; char *name; struct ucred *cred;{ register struct nameidata *ndp = &u.u_nd; struct gnode *gp; int ret; ndp->ni_nameiop = DELETE | LOCKPARENT | NOMOUNT; ndp->ni_dirp = name; u.u_cdir = pgp; gfs_unlock(pgp); gp = GNAMEI(ndp); if (gp == NULL) { return (u.u_error); } /* * GFS requires the sfs be passed a directory gp. Lets make * sure the client was as thoughtful. */ if ((gp->g_mode & GFMT) != GFDIR) { /* * Two gputs are ok here because rmdir(".") will * never execute this conditional. */ gput(ndp->ni_pdir); gput(gp); u.u_error = ENOTDIR; return(ENOTDIR); } /* * Don't allow rmdir's of mount points. Name translations * would fail when attempting to traverse removed entry. */ if (gp->g_flag & GMOUNT) { gput(gp); if (gp == ndp->ni_pdir) grele(ndp->ni_pdir); else gput(ndp->ni_pdir); u.u_error = EBUSY; return(EBUSY); } ret = GRMDIR(gp, ndp); return (u.u_error);}intvop_readdir(gp, uiop, cred) struct gnode *gp; struct uio *uiop; struct ucred *cred;{ if (access(gp, GREAD)) { u.u_error = EPERM; return(EPERM); /* XXX */ } (void) GGETDIRENTS(gp, uiop, cred); return (u.u_error);}intvop_brelse(gp, bp) struct gnode *gp; struct buf *bp;{ bp->b_resid = 0; brelse(bp);}intvop_bread(gp, lbn, bpp) struct gnode *gp; daddr_t lbn; struct buf **bpp;{ register struct buf *bp; register daddr_t bn; register int size; size = blksize(FS(gp), gp, lbn); bn = GBMAP(gp, lbn, B_READ, 0, 0); if ((long)bn < 0) { bp = geteblk(size); clrbuf(bp); } else if (gp->g_lastr + 1 == lbn) { bp = breada(gp->g_dev, bn, size, rablock, rasize, (struct gnode *) 0); } else { bp = bread(gp->g_dev, bn, size, (struct gnode *) 0); } gp->g_lastr = lbn; gp->g_flag |= GACC; if (bp->b_flags & B_ERROR) { brelse(bp); return (EIO); } else { *bpp = bp; return (0); }}/* * Perform chown operation on gnode gp. This is similar to chown1() * in gfs_syscalls.c, but we leave some preliminary error checking and * the GUPDATE operation for the caller to do. This routine should not * exist; please merge these someday. */struct dquot *inoquota();chown2(gp, uid, gid) register struct gnode *gp; register int uid, gid;{#ifdef QUOTA register long change;#endif if (uid == -1) uid = gp->g_uid; if (gid == -1) gid = gp->g_gid;#ifdef QUOTA if (gp->g_uid == uid) change = 0; else change = gp->g_blocks; (void) chkdq(gp, -change, 1); (void) chkiq(gp->g_dev, gp, gp->g_uid, 1); dquot_lock(gp->g_dquot); dqrele(gp->g_dquot); dquot_unlock(gp->g_dquot);#endif gp->g_uid = uid; gp->g_gid = gid; gp->g_flag |= (GCHG | GCID); if (u.u_ruid != 0) gp->g_mode &= ~(GSUID|GSGID);#ifdef QUOTA gp->g_dquot = inoquota(gp); (void) chkdq(gp, change, 1); (void) chkiq(gp->g_dev, (struct gnode *)NULL, uid, 1); return (u.u_error); #else return(0);#endif}gattr_to_nattr(gp, na) register struct gnode *gp; register struct nfsfattr *na;{ na->na_type = (enum nfsftype)IFTOVT(gp->g_mode); na->na_mode = gp->g_mode; na->na_uid = gp->g_uid; na->na_gid = gp->g_gid; na->na_fsid = gp->g_dev; na->na_nodeid = gp->g_number; na->na_nlink = gp->g_nlink; na->na_size = gp->g_size; na->na_atime = gp->g_atime; na->na_mtime = gp->g_mtime; na->na_ctime = gp->g_ctime; na->na_rdev = gp->g_rdev; na->na_blocks = gp->g_blocks;/* na->na_blocksize = KLUDGE: CALLER MUST DO THIS */}/* * Special kludge for fifos (named pipes) * [to adhere to (unwritten) NFS Protocol Spec] * * VFIFO is not in the protocol spec (VNON will be replaced by VFIFO) * so the over-the-wire representation is VCHR with a '-1' device number. * * NOTE: This kludge becomes unnecessary with the Protocol Revision, * but it may be necessary to support it (backwards compatibility). *//* identify fifo in nfs attributes */#define NA_ISFIFO(NA) (((NA)->na_type == NFS_FIFO_TYPE) && \ ((NA)->na_rdev == NFS_FIFO_DEV))nattr_to_gattr(gp, na) register struct gnode *gp; register struct nfsfattr *na;{ gp->g_mode = na->na_mode; gp->g_uid = na->na_uid; gp->g_gid = na->na_gid; gp->g_nlink = na->na_nlink; gp->g_size = na->na_size; gp->g_atime = na->na_atime; gp->g_mtime = na->na_mtime; gp->g_ctime = na->na_ctime; gp->g_blocks = na->na_blocks; gp->g_rdev = na->na_rdev; /* *** From nfssrc 4.0 *** * This bit of ugliness is a *TEMPORARY* hack to preserve the * over-the-wire protocols for named-pipe vnodes. It remaps the * special over-the-wire type to the VFIFO type. (see note in nfs.h) * * BUYER BEWARE: * If you are porting the NFS to a non-SUN server, you probably * don't want to include the following block of code. The * over-the-wire special file types will be changing with the * NFS Protocol Revision. */ if (NA_ISFIFO(na)) { gp->g_mode = (gp->g_mode & ~GFMT) | GFPORT; gp->g_rdev = 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -