X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/6b496efad6f5fbbefcf3cdfdb43368dde2a7abfb..528f664cb046a6bc60c14f34650cb0acdbdb084a:/usr/src/sys/kern/vfs_syscalls.c diff --git a/usr/src/sys/kern/vfs_syscalls.c b/usr/src/sys/kern/vfs_syscalls.c index 8a63b1712d..b8de1e6916 100644 --- a/usr/src/sys/kern/vfs_syscalls.c +++ b/usr/src/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* vfs_syscalls.c 4.31 82/07/25 */ +/* vfs_syscalls.c 4.32 82/08/10 */ #include "../h/param.h" #include "../h/systm.h" @@ -11,10 +11,9 @@ #include "../h/buf.h" #include "../h/proc.h" #include "../h/inline.h" -#ifdef EFS -#include "../net/in.h" -#include "../h/efs.h" -#endif +/* no reason to inline expand these guys here */ +#undef ilock +#undef iunlock #include "../h/quota.h" #include "../h/descrip.h" @@ -32,7 +31,7 @@ chroot() } chdirec(ipp) -register struct inode **ipp; + register struct inode **ipp; { register struct inode *ip; struct a { @@ -66,16 +65,29 @@ open() register struct inode *ip; register struct a { char *fname; - int rwmode; + int flags; + int mode; } *uap; + int checkpermissions = 1; uap = (struct a *)u.u_ap; - ip = namei(uchar, 0, 1); + if (uap->flags&FCREATE) { + ip = namei(uchar, 1, 1); + if (ip == NULL) { + if (u.u_error) + return; + ip = maknode(uap->mode&07777&(~ISVTX)); + checkpermissions = 0; + uap->flags &= ~FTRUNCATE; + } + } else + ip = namei(uchar, 0, 1); if (ip == NULL) return; - open1(ip, ++uap->rwmode, 0); + open1(ip, ++uap->flags, checkpermissions); } +#ifndef NOCOMPAT /* * Creat system call. */ @@ -93,58 +105,74 @@ ocreat() if (u.u_error) return; ip = maknode(uap->fmode&07777&(~ISVTX)); - if (ip==NULL) + if (ip == NULL) return; - open1(ip, FWRITE, 2); + open1(ip, FWRITE, 0); } else - open1(ip, FWRITE, 1); + open1(ip, FWRITE|FTRUNCATE, 0); } +#endif /* * Common code for open and creat. - * Check permissions, allocate an open file structure, - * and call the device open routine if any. + * Check permissions (if we haven't done so already), + * allocate an open file structure, and call + * the device open routine, if any. */ -open1(ip, mode, trf) +open1(ip, mode, checkpermissions) register struct inode *ip; register mode; { register struct file *fp; - int i; + int i, flags; - if (trf != 2) { + if (checkpermissions) { if (mode&FREAD) - (void) access(ip, IREAD); + if (access(ip, IREAD)) + goto bad; if (mode&FWRITE) { - (void) access(ip, IWRITE); - if ((ip->i_mode&IFMT) == IFDIR) + if (access(ip, IWRITE)) + goto bad; + if ((ip->i_mode&IFMT) == IFDIR) { u.u_error = EISDIR; + goto bad; + } } } - if (u.u_error) { - iput(ip); - return; + + /* + * Check locking on inode. Release "inode lock" + * while doing so in case we block inside flocki. + */ + flags = 0; + if (mode&(FRDLOCK|FWRLOCK)) { + iunlock(ip); + flags = flocki(ip, 0, mode); + ilock(ip); + if (u.u_error) + goto bad; } - if (trf == 1) - itrunc(ip); + if (mode&FTRUNCATE) + itrunc(ip, 0); iunlock(ip); if ((fp = falloc()) == NULL) goto out; - fp->f_flag = mode&(FREAD|FWRITE); + fp->f_flag = mode & FMODES; fp->f_type = DTYPE_FILE; i = u.u_r.r_val1; fp->f_inode = ip; -#ifdef EFS - openi(ip, mode&(FREAD|FWRITE), trf); -#else - openi(ip, mode&(FREAD|FWRITE)); -#endif - if (u.u_error == 0) + openi(ip, mode); + if (u.u_error == 0) { + u.u_pofile[i] = flags; return; + } u.u_ofile[i] = NULL; fp->f_count--; out: irele(ip); + return; +bad: + iput(ip); } /* @@ -295,25 +323,6 @@ unlink() pp = namei(uchar, 2, 0); if (pp == NULL) return; -#ifdef EFS - /* divert to extended file system if off machine. */ - if (efsinode(pp)) { - dev_t ndev = pp->i_rdev; - - iput(pp); /* avoid recursive hang on inode */ - efsunlink(ndev); - if (u.u_error != EEXIST) - return; - - /* - * If a null pathname remainder, then do - * the unlink locally after restoring state. - */ - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - pp = namei(uchar, 2, 0); - } -#endif /* * Check for unlink(".") @@ -358,29 +367,23 @@ seek() { register struct file *fp; register struct a { - int fdes; + int fd; off_t off; int sbase; } *uap; uap = (struct a *)u.u_ap; - fp = getf(uap->fdes); + fp = getf(uap->fd); if (fp == NULL) return; if (fp->f_type == DTYPE_SOCKET) { u.u_error = ESPIPE; return; } - if (uap->sbase == 1) + if (uap->sbase == FSEEK_RELATIVE) uap->off += fp->f_offset; - else if (uap->sbase == 2) { -#ifdef EFS - struct inode *ip = fp->f_inode; - uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size; -#else + else if (uap->sbase == FSEEK_EOF) uap->off += fp->f_inode->i_size; -#endif - } fp->f_offset = uap->off; u.u_r.r_off = uap->off; } @@ -403,26 +406,14 @@ saccess() u.u_uid = u.u_ruid; u.u_gid = u.u_rgid; ip = namei(uchar, 0, 1); -#ifdef EFS - if (efsinode(ip)) { - dev_t ndev = ip->i_rdev; - - iput(ip); - efssaccess(ndev); - if (u.u_error != EEXIST) - return; - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - ip = namei(uchar, 0, 1); - } -#endif if (ip != NULL) { - if (uap->fmode&(IREAD>>6)) - (void) access(ip, IREAD); - if (uap->fmode&(IWRITE>>6)) - (void) access(ip, IWRITE); - if (uap->fmode&(IEXEC>>6)) - (void) access(ip, IEXEC); + if (uap->fmode&FACCESS_READ && access(ip, IREAD)) + goto done; + if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) + goto done; + if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) + goto done; +done: iput(ip); } u.u_uid = svuid; @@ -436,20 +427,14 @@ fstat() { register struct file *fp; register struct a { - int fdes; + int fd; struct stat *sb; } *uap; uap = (struct a *)u.u_ap; - fp = getf(uap->fdes); + fp = getf(uap->fd); if (fp == NULL) return; -#ifdef EFS - if (efsinode(fp->f_inode)) { - efsfstat(fp->f_inode->i_rdev, fp); - return; - } -#endif if (fp->f_type == DTYPE_SOCKET) u.u_error = sostat(fp->f_socket, uap->sb); else @@ -471,19 +456,6 @@ stat() ip = namei(uchar, 0, 1); if (ip == NULL) return; -#ifdef EFS - if (efsinode(ip)) { - dev_t ndev = ip->i_rdev; - - iput(ip); - efsstat(ndev); - if (u.u_error != EEXIST) - return; - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - ip = namei(uchar, 0, 1); - } -#endif stat1(ip, uap->sb); iput(ip); } @@ -503,19 +475,6 @@ lstat() ip = namei(uchar, 0, 0); if (ip == NULL) return; -#ifdef EFS - if (efsinode(ip)) { - dev_t ndev = ip->i_rdev; - - iput(ip); - efslstat(ndev); - if (u.u_error != EEXIST) - return; - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - ip = namei(uchar, 0, 0); - } -#endif stat1(ip, uap->sb); iput(ip); } @@ -545,7 +504,13 @@ stat1(ip, ub) ds.st_atime = ip->i_atime; ds.st_mtime = ip->i_mtime; ds.st_ctime = ip->i_ctime; - ds.st_blksize = ip->i_fs->fs_bsize; + /* this doesn't belong here */ + if ((ip->i_mode&IFMT) == IFBLK) + ds.st_blksize = BLKDEV_IOSIZE; + else if ((ip->i_mode&IFMT) == IFCHR) + ds.st_blksize = MAXBSIZE; + else + ds.st_blksize = ip->i_fs->fs_bsize; if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) u.u_error = EFAULT; } @@ -565,20 +530,6 @@ readlink() ip = namei(uchar, 0, 0); if (ip == NULL) return; -#ifdef EFS - if (efsinode(ip)) { - dev_t ndev = ip->i_rdev; - - iput(ip); - efsreadlink(ndev); - if (u.u_error != EEXIST) - return; - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - ip = namei(uchar, 0, 0); - return (0); - } -#endif if ((ip->i_mode&IFMT) != IFLNK) { u.u_error = ENXIO; goto out; @@ -596,8 +547,8 @@ out: chmod() { - register struct inode *ip; - register struct a { + struct inode *ip; + struct a { char *fname; int fmode; } *uap; @@ -605,83 +556,119 @@ chmod() uap = (struct a *)u.u_ap; if ((ip = owner(1)) == NULL) return; -#ifdef EFS - if (efsinode(ip)) { - dev_t ndev = ip->i_rdev; + chmod1(ip, uap->fmode); +} - iput(ip); - efschmod(ndev); - if (u.u_error != EEXIST) - return; - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - ip = owner(1); +fchmod() +{ + struct a { + int fd; + int fmode; + } *uap; + register struct inode *ip; + register struct file *fp; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fd); + if (fp == NULL) + return; + if (fp->f_type == DTYPE_SOCKET) { + u.u_error = EINVAL; + return; } -#endif + ip = fp->f_inode; + ilock(ip); + if (u.u_uid != ip->i_uid && !suser()) { + iunlock(ip); + return; + } + chmod1(ip, uap->fmode); +} + +chmod1(ip, mode) + register struct inode *ip; + register int mode; +{ ip->i_mode &= ~07777; if (u.u_uid) { - uap->fmode &= ~ISVTX; + mode &= ~ISVTX; if (ip->i_gid >= NGRPS || (u.u_grps[ip->i_gid/(sizeof(int)*8)] & (1 << ip->i_gid%(sizeof(int)*8))) == 0) - uap->fmode &= ~ISGID; -#if MUSH + mode &= ~ISGID; +#ifdef MUSH if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && (ip->i_mode & IFMT) != IFCHR) - uap->fmode &= ~u.u_cmask; + mode &= ~u.u_cmask; #endif } - ip->i_mode |= uap->fmode&07777; + ip->i_mode |= mode&07777; ip->i_flag |= ICHG; if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) xrele(ip); -#ifdef MELB - if ((ip->i_mode & ISUID) && ip->i_uid == 0) - printf("%s: ino %d (%s) setuid root\n" - , getfs(ip->i_dev)->s_fsmnt - , ip->i_number - , u.u_dent.d_name - ); -#endif iput(ip); } chown() { - register struct inode *ip; - register struct a { + struct inode *ip; + struct a { char *fname; int uid; int gid; } *uap; -#if QUOTA - register long change; -#endif uap = (struct a *)u.u_ap; if (!suser() || (ip = owner(0)) == NULL) return; -#ifdef EFS - if (efsinode(ip)) { - dev_t ndev = ip->i_rdev; + chown1(ip, uap->uid, uap->gid); +} - iput(ip); - efschown(ndev); - if (u.u_error != EEXIST) - return; - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - ip = owner(0); +fchown() +{ + struct a { + int fd; + int uid; + int gid; + } *uap; + register struct inode *ip; + register struct file *fp; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fd); + if (fp == NULL) + return; + if (fp->f_type == DTYPE_SOCKET) { + u.u_error = EINVAL; + return; } -#endif -#if QUOTA + ip = fp->f_inode; + ilock(ip); + if (!suser()) { + iunlock(ip); + return; + } + chown1(ip, uap->uid, uap->gid); +} + +/* + * Perform chown operation on inode ip; + * inode must be locked prior to call. + */ +chown1(ip, uid, gid) + register struct inode *ip; + int uid, gid; +{ +#ifdef QUOTA + register long change; + /* * This doesn't allow for holes in files (which hopefully don't * happen often in files that we chown), and is not accurate anyway * (eg: it totally ignores 3 level indir blk files - but hopefully * noone who can make a file that big will have a quota) */ - if (ip->i_uid == uap->uid) + if (ip->i_uid == uid) change = 0; else { register struct fs *fs = ip->i_fs; @@ -692,7 +679,7 @@ chown() size = blkroundup(fs, ip->i_size) - change; change += size; change += fs->fs_bsize; - /* This assumes NIADDR <= 2 */ + /* this assumes NIADDR <= 2 */ if (size > NINDIR(fs) * fs->fs_bsize) change += fs->fs_bsize; } else @@ -704,20 +691,20 @@ chown() dqrele(ip->i_dquot); #endif /* - * keep uid/gid's in sane range - no err, so chown(file, uid, -1) - * will do something useful + * keep uid/gid's in sane range -- no err, + * so chown(file, uid, -1) will do something useful */ - if (uap->uid >= 0 && uap->uid <= 32767) /* should have a const */ - ip->i_uid = uap->uid; - if (uap->gid >= 0 && uap->gid <= 32767) /* same here */ - ip->i_gid = uap->gid; + if (uid >= 0 && uid <= 32767) /* should have a constant */ + ip->i_uid = uid; + if (gid >= 0 && gid <= 32767) /* same here */ + ip->i_gid = gid; ip->i_flag |= ICHG; if (u.u_ruid != 0) ip->i_mode &= ~(ISUID|ISGID); -#if QUOTA +#ifdef QUOTA ip->i_dquot = inoquota(ip); chkdq(ip, change, 1); - chkiq(ip->i_dev, NULL, uap->uid, 1); + chkiq(ip->i_dev, NULL, uid, 1); #endif iput(ip); } @@ -741,19 +728,6 @@ utime() if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { u.u_error = EFAULT; } else { -#ifdef EFS - if (efsinode(ip)) { - dev_t ndev = ip->i_rdev; - - iput(ip); - efsutime(ndev, uap->fname, tv); - if (u.u_error != EEXIST) - return; - u.u_error = 0; - u.u_dirp = (caddr_t)u.u_arg[0]; - ip = owner(1); - } -#endif ip->i_flag |= IACC|IUPD|ICHG; iupdat(ip, &tv[0], &tv[1], 0); } @@ -766,6 +740,101 @@ sync() update(0); } +flock() +{ + struct a { + int fd; + int how; + } *uap; + register struct file *fp; + register int cmd, flags; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fd); + if (fp == NULL) + return; + if (fp->f_type == DTYPE_SOCKET) { /* XXX */ + u.u_error = EINVAL; + return; + } + cmd = uap->how; + flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); + if (cmd&FUNLOCK) { + if (flags == 0) { + u.u_error = EINVAL; + return; + } + funlocki(fp->f_inode, flags); + u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); + return; + } + /* + * No reason to write lock a file we've already + * write locked, similarly with a read lock. + */ + if ((flags&WRLOCK) && (cmd&FWRLOCK) || + (flags&RDLOCK) && (cmd&FRDLOCK)) + return; + u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); +} + +truncate() +{ + struct a { + char *fname; + int length; + } *uap; + struct inode *ip; + + ip = namei(uchar, 0, 1); + if (ip == NULL) + return; + if (access(ip, IWRITE)) + goto bad; + if ((ip->i_mode&IFMT) == IFDIR) { + u.u_error = EISDIR; + goto bad; + } + itrunc(ip, uap->length); + return; +bad: + iput(ip); +} + +ftruncate() +{ + struct a { + int fd; + int length; + } *uap; + struct inode *ip; + struct file *fp; + + fp = getf(uap->fd); + if (fp == NULL) + return; + if (fp->f_type == DTYPE_SOCKET) { + u.u_error = EINVAL; + return; + } + if ((fp->f_flag&FWRITE) == 0) { + u.u_error = EINVAL; + return; + } + ip = fp->f_inode; + ilock(ip); + itrunc(ip, uap->length); +} + +rename() +{ + struct a { + char *from; + char *to; + } *uap; + +} + /* * Make a new file. */ @@ -783,9 +852,9 @@ maknode(mode) ip = ialloc(u.u_pdir, ipref, mode); if (ip == NULL) { iput(u.u_pdir); - return(NULL); + return (NULL); } -#ifdef QUOTA +#ifdef QUOTA if (ip->i_dquot != NODQUOT) panic("maknode: dquot"); #endif @@ -796,7 +865,7 @@ maknode(mode) ip->i_nlink = 1; ip->i_uid = u.u_uid; ip->i_gid = u.u_pdir->i_gid; -#ifdef QUOTA +#ifdef QUOTA ip->i_dquot = inoquota(ip); #endif @@ -813,7 +882,7 @@ maknode(mode) ip->i_nlink = 0; ip->i_flag |= ICHG; iput(ip); - return(NULL); + return (NULL); } - return(ip); + return (ip); }