/* * NAME: iOpenAccess() * * FUNCTION: check access permissions before an open * called by jfs_open() and jfs_create(). * * PARAMETER: ip - inode in question * flag - permissions to check * crp - credential * * RETURN: */ int32 iOpenAccess( inode_t *ip, /* inode to check access for */ int32 flag, /* open flags */ struct ucred *crp) { int32 rc = 0; int32 mode; struct gnode *gp = IP2GP(ip); if (((flag & OPEN_FLAGS_LARGEFILE) == 0) && (ip->i_size > 0x7fffffff)) return ERROR_ACCESS_DENIED; /* set up mode for call to iAccess */ switch (flag & (OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY)) { case (OPEN_ACCESS_READWRITE): mode = (IREAD|IWRITE); break; case (OPEN_ACCESS_WRITEONLY): mode = IWRITE; break; default: mode = IREAD; } /* check for sharing violation */ if ((mode & IREAD) && (gp->gn_drcnt)) rc = ETXTBSY; else if ((mode & IWRITE) && (gp->gn_dwcnt)) rc = ETXTBSY; else if (gp->gn_flags & GNF_NSHARE) rc = ETXTBSY; /* check permissions */ else rc = iAccess(ip, mode, crp); return rc; }
/* * NAME: jfs_mknod(dvp, name, mode, dev, crp) * * FUNCTION: make a new object in directory <dvp> with mode = <mode>, * name = <pname>, and rdev = <dev>. * * PARAMETER: dvp - directory vnode * name - name of new object * mode - create mode (rwxrwxrwx). * dev - new device number if block/character-special file * crp - credential * * RETURN: Errors from subroutines * * note: JFS allows mknod() to create a special file. * XPG4.2: the only portable use of mknod() is to create a FIFO-special file * with mode = S_IFIFO and dev = 0. */ jfs_mknod( struct vnode *dvp, caddr_t name, mode_t mode, dev_t dev, struct ucred *crp) { int32 rc; int32 tid; inode_t *dip = VP2IP(dvp); inode_t *ip; ino_t ino; component_t dname; struct vfs *vfsp = dvp->v_vfsp; btstack_t btstack; inode_t *iplist[2]; /* JFS does NOT support mknod() of directory */ if ((mode & IFMT) == IFDIR) return EISDIR; if ((mode & IFMT) != IFIFO && (mode & IFMT) != IFSOCK) if (rc = privcheck_cr(DEV_CONFIG, crp)) return rc; IWRITE_LOCK(dip); txBegin(dip->i_ipmnt, &tid, 0); /* validate search+write permission on parent directory */ if (rc = iAccess(dip, IEXEC|IWRITE, crp)) goto out1; /* * scan parent directory for entry/freespace * (dtSearch() returns parent directory page pinned) */ dname.name = name; dname.namlen = strlen(name); if (rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)) goto out1; /* * allocate in-memory+on-disk inode: * (iAlloc() returns new, locked inode) */ if (rc = iAlloc(vfsp, dip, mode, &ip, crp)) { /* release parent directory page */ BT_PUTSEARCH(&btstack); goto out1; } /* * create entry in parent directory * (dtInsert() releases parent directory page) */ ino = ip->i_number; if (rc = dtInsert(tid, dip, &dname, &ino, &btstack)) { /* discard the new inode */ ip->i_nlink = 0; goto out2; } /* * fo a block or character special file, the passed-in device number * needs to be set into the inode's device field and the gnode's * "real device" field. */ if ((ip->i_mode & IFMT) == IFBLK || (ip->i_mode & IFMT) == IFCHR) { ip->i_rdev = dev; IP2GP(ip)->gn_rdev = dev; } imark(ip, IACC|ICHG|IUPD|IFSYNC); /* update parent directory inode */ imark(dip, ICHG|IUPD|IFSYNC); /* * insert entry for the new file to dnlc */ ncEnter(dip->i_ipimap, dip->i_number, &dname, ino, NULL); iplist[0] = dip; iplist[1] = ip; rc = txCommit(tid, 2, &iplist[0], 0); out2: IWRITE_UNLOCK(ip); ICACHE_LOCK(); iput(ip, vfsp); ICACHE_UNLOCK(); out1: IWRITE_UNLOCK(dip); txEnd(tid); return rc; }
/* * NAME: iOpen() * * FUNCTION: common function that opens a file. * called by jfs_open() and jfs_create(). * * PARAMETER: ip - inode to open * flag - open flags from the file pointer. * ext - external data used by the device driver. * crp - credential * * RETURN: EBUSY - if truncating a mapped file * errors from subroutines * * note: at most a single commit may occur in jfs_open() and jfs_create() * as FEXEC and FTRUNC are mutually exclusive. */ int32 iOpen( inode_t *ip, /* inode of file to open */ int32 flag, /* open(2) flags */ int32 tflag, /* trucation flag */ FEALIST *pfealist, /* EAs if truncating */ struct ucred *crp) /* credential */ { int32 rc = 0; struct gnode *gp; /* gnode pointer from inode */ int64 orig_nblocks; // F226941 int32 tid; /* bind the newly opened file to a cache control object */ if ((ip->i_mode & IFMT) == IFREG && ip->i_cacheid == NULL) { if (rc = iBindCache(ip)) return rc; } /* if open/create FTRUNC, truncate to zero length */ if (tflag & OPEN_ACTION_REPLACE_IF_EXISTS) { if (isReadOnly(ip)) return EROFS; orig_nblocks = ip->i_nblocks; // F226941 // BEGIN D230860 /* * Cannot begin transaction until all inodes are locked */ if (ip->i_dasdlim && (ip->i_dasdlim->flag & DLIM_DIRS_LOCKED) == 0) dasd_write_lock(0, ip->i_dasdlim); // END D230860 txBegin(ip->i_ipmnt, &tid, 0); if (rc = iTruncate(tid, ip, 0)) { txEnd(tid); return rc; } imark(ip, IACC|ICHG|IUPD|IFSYNC); // D233382 #ifdef _JFS_OS2 rc = jfs_InitializeFEAList(ip, tid, pfealist); /* If we successfully truncated the file, but failed adding the * EA's, we are in a bad state. Punt... */ if (rc) { txAbort(tid, 0); txEnd(tid); return rc; } #endif /* _JFS_OS2 */ DLIM_UPDATE(tid, ip, ip->i_nblocks - orig_nblocks); // F226941 rc = DLIM_TXCOMMIT(tid, ip, 0); // F226941 txEnd(tid); if (rc) return rc; } /* * update per open counters */ gp = IP2GP(ip); #ifdef _JFS_OS2 /* keep count of opens by type */ switch (flag & (OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY)) { case (OPEN_ACCESS_READWRITE): gp->gn_wrcnt++; gp->gn_rdcnt++; break; case (OPEN_ACCESS_WRITEONLY): gp->gn_wrcnt++; break; default: gp->gn_rdcnt++; } /* set up sharing mode */ switch (flag & (OPEN_SHARE_DENYREAD)) { case(OPEN_SHARE_DENYWRITE): gp->gn_dwcnt++; break; case(OPEN_SHARE_DENYREAD): gp->gn_drcnt++; break; case(OPEN_SHARE_DENYREADWRITE): gp->gn_flags |= GNF_NSHARE; break; } if ((flag & OPEN_FLAGS_LARGEFILE) == 0) gp->gn_lgcnt++; #endif /* _JFS_OS2 */ return rc; }