int r, proc_e;
- if(task_nr == SYSTEM) printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
+ if(task_nr == SYSTEM) {
+ printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
+ }
proc_e = mess_ptr->IO_ENDPT;
- r = sendrec(task_nr, mess_ptr);
- if(r == OK && mess_ptr->REP_STATUS == ERESTART) r = EDEADEPT;
- if (r != OK) {
- if (r == EDEADSRCDST || r == EDEADEPT) {
- printf("fs: dead driver %d\n", task_nr);
- dmap_unmap_by_endpt(task_nr);
- return(r);
+
+ for (;;) {
+
+ r = sendrec(task_nr, mess_ptr);
+ if(r == OK && mess_ptr->REP_STATUS == ERESTART) r = EDEADEPT;
+ if (r != OK) {
+ if (r == EDEADSRCDST || r == EDEADEPT) {
+ printf("fs: dead driver %d\n", task_nr);
+ dmap_unmap_by_endpt(task_nr);
+ return(r);
+ }
+ if (r == ELOCKED) {
+ printf("fs: ELOCKED talking to %d\n", task_nr);
+ return(r);
+ }
+ panic("call_task: can't send/receive: %d", r);
}
- if (r == ELOCKED) {
- printf("fs: ELOCKED talking to %d\n", task_nr);
- return(r);
+
+ /* Did the process we did the sendrec() for get a result? */
+ if (mess_ptr->REP_ENDPT != proc_e && VFS_PROC_NR != proc_e) {
+
+ printf("fs: strange device reply from %d, type = %d, "
+ "proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
+ mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
+
+ return(EIO);
}
- panic("call_task: can't send/receive: %d", r);
- }
- /* Did the process we did the sendrec() for get a result? */
- if (mess_ptr->REP_ENDPT != proc_e) {
- printf("fs: strange device reply from %d, type = %d, proc = %d "
- "(not %d) (2) ignored\n", mess_ptr->m_source, mess_ptr->m_type,
- proc_e, mess_ptr->REP_ENDPT);
- return(EIO);
+ if (mess_ptr->m_type == TASK_REPLY ||
+ IS_DEV_RS(mess_ptr->m_type) ||
+ mess_ptr->m_type <= 0) {
+
+ break; /* reply */
+ } else {
+
+ nested_dev_call(mess_ptr);
+ }
}
return(OK);
progname[PROC_NAME_LEN-1] = '\0';
/* Open executable */
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
if ((vp->v_mode & I_TYPE) != I_REGULAR)
r = ENOEXEC;
/* This file contains the procedures that manipulate file descriptors.
*
* The entry points into this file are
- * get_fd: look for free file descriptor and free filp slots
- * get_filp: look up the filp entry for a given file descriptor
- * find_filp: find a filp slot that points to a given vnode
- * inval_filp: invalidate a filp and associated fd's, only let close()
- * happen on it
+ * get_fd: look for free file descriptor and free filp slots
+ * get_filp: look up the filp entry for a given file descriptor
+ * find_filp: find a filp slot that points to a given vnode
+ * inval_filp: invalidate a filp and associated fd's, only let close()
+ * happen on it
+ * do_verify_fd: verify whether the given file descriptor is valid for
+ * the given endpoint.
+ * do_set_filp: marks a filp as in-flight.
+ * do_copy_filp: copies a filp to another endpoint.
+ * do_put_filp: marks a filp as not in-flight anymore.
+ * do_cancel_fd: cancel the transaction when something goes wrong for
+ * the receiver.
*/
#include <sys/select.h>
+#include <minix/callnr.h>
#include <minix/u64.h>
#include <assert.h>
#include "fs.h"
return(n); /* Report back how often this filp has been invalidated. */
}
+
+/*===========================================================================*
+ * verify_fd *
+ *===========================================================================*/
+PUBLIC filp_id_t verify_fd(ep, fd)
+endpoint_t ep;
+int fd;
+{
+ /*
+ * verify whether the given file descriptor 'fd' is valid for the
+ * endpoint 'ep'. When the file descriptor is valid verify_fd returns a
+ * pointer to that filp, else it returns NULL.
+ */
+ int proc;
+
+ if (isokendpt(ep, &proc) != OK) {
+ return NULL;
+ }
+
+ return get_filp2(&fproc[proc], fd);
+}
+
+/*===========================================================================*
+ * do_verify_fd *
+ *===========================================================================*/
+PUBLIC int do_verify_fd(void)
+{
+ m_out.ADDRESS = (void *) verify_fd(m_in.IO_ENDPT, m_in.COUNT);
+ return (m_out.ADDRESS != NULL) ? OK : EINVAL;
+}
+
+/*===========================================================================*
+ * set_filp *
+ *===========================================================================*/
+PUBLIC int set_filp(sfilp)
+filp_id_t sfilp;
+{
+ if (sfilp == NULL) {
+ return EINVAL;
+ } else {
+ sfilp->filp_count++;
+ return OK;
+ }
+}
+
+/*===========================================================================*
+ * do_set_filp *
+ *===========================================================================*/
+PUBLIC int do_set_filp(void)
+{
+ return set_filp((filp_id_t) m_in.ADDRESS);;
+}
+
+/*===========================================================================*
+ * copy_filp *
+ *===========================================================================*/
+PUBLIC int copy_filp(to_ep, cfilp)
+endpoint_t to_ep;
+filp_id_t cfilp;
+{
+ int j;
+ int proc;
+
+ if (isokendpt(to_ep, &proc) != OK) {
+ return EINVAL;
+ }
+
+ /* Find an open slot in fp_filp */
+ for (j = 0; j < OPEN_MAX; j++) {
+ if (fproc[proc].fp_filp[j] == NULL &&
+ !FD_ISSET(j, &fproc[proc].fp_filp_inuse)) {
+
+ /* Found a free slot, add descriptor */
+ FD_SET(j, &fproc[proc].fp_filp_inuse);
+ fproc[proc].fp_filp[j] = cfilp;
+ fproc[proc].fp_filp[j]->filp_count++;
+ return j;
+ }
+ }
+
+ /* File Descriptor Table is Full */
+ return EMFILE;
+}
+
+/*===========================================================================*
+ * do_copy_filp *
+ *===========================================================================*/
+PUBLIC int do_copy_filp(void)
+{
+ return copy_filp(m_in.IO_ENDPT, (filp_id_t) m_in.ADDRESS);
+}
+
+/*===========================================================================*
+ * put_filp *
+ *===========================================================================*/
+PUBLIC int put_filp(pfilp)
+filp_id_t pfilp;
+{
+ if (pfilp == NULL) {
+ return EINVAL;
+ } else {
+ close_filp(pfilp);
+ return OK;
+ }
+}
+
+/*===========================================================================*
+ * do_put_filp *
+ *===========================================================================*/
+PUBLIC int do_put_filp(void)
+{
+ return put_filp((filp_id_t) m_in.ADDRESS);
+}
+
+/*===========================================================================*
+ * cancel_fd *
+ *===========================================================================*/
+PUBLIC int cancel_fd(ep, fd)
+endpoint_t ep;
+int fd;
+{
+ int j;
+ int proc;
+
+ if (isokendpt(ep, &proc) != OK) {
+ return EINVAL;
+ }
+
+ /* Check that the input 'fd' is valid */
+ if (verify_fd(ep, fd) != NULL) {
+
+ /* Found a valid descriptor, remove it */
+ FD_CLR(fd, &fproc[proc].fp_filp_inuse);
+ fproc[proc].fp_filp[fd]->filp_count--;
+ fproc[proc].fp_filp[fd] = NULL;
+
+ return fd;
+ }
+
+ /* File descriptor is not valid for the endpoint. */
+ return EINVAL;
+}
+
+/*===========================================================================*
+ * do_cancel_fd *
+ *===========================================================================*/
+PUBLIC int do_cancel_fd(void)
+{
+ return cancel_fd(m_in.IO_ENDPT, m_in.COUNT);
+}
+
+/*===========================================================================*
+ * close_filp *
+ *===========================================================================*/
+PUBLIC void close_filp(fp)
+struct filp *fp;
+{
+ int mode_word, rw;
+ dev_t dev;
+ struct vnode *vp;
+
+ vp = fp->filp_vno;
+ if (fp->filp_count - 1 == 0 && fp->filp_mode != FILP_CLOSED) {
+ /* Check to see if the file is special. */
+ mode_word = vp->v_mode & I_TYPE;
+ if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
+ dev = (dev_t) vp->v_sdev;
+ if (mode_word == I_BLOCK_SPECIAL) {
+ if (vp->v_bfs_e == ROOT_FS_E) {
+ /* Invalidate the cache unless the special is
+ * mounted. Assume that the root filesystem's
+ * is open only for fsck.
+ */
+ req_flush(vp->v_bfs_e, dev);
+ }
+ }
+ /* Do any special processing on device close. */
+ (void) dev_close(dev, fp-filp);
+ /* Ignore any errors, even SUSPEND. */
+
+ fp->filp_mode = FILP_CLOSED;
+ }
+ }
+
+ /* If the inode being closed is a pipe, release everyone hanging on it. */
+ if (vp->v_pipe == I_PIPE) {
+ rw = (fp->filp_mode & R_BIT ? WRITE : READ);
+ release(vp, rw, NR_PROCS);
+ }
+
+ /* If a write has been done, the inode is already marked as DIRTY. */
+ if (--fp->filp_count == 0) {
+ if (vp->v_pipe == I_PIPE) {
+ /* Last reader or writer is going. Tell PFS about latest
+ * pipe size.
+ */
+ truncate_vnode(vp, vp->v_size);
+ }
+
+ put_vnode(fp->filp_vno);
+ }
+}
*
* The entry points into this file are
* nested_fs_call perform a nested call from a file system server
+ * nested_dev_call perform a nested call from a device driver server
+ *
*/
#include "fs.h"
#include <assert.h>
#include <minix/callnr.h>
#include <minix/endpoint.h>
+#include <minix/vfsif.h>
/* maximum nested call stack depth */
#define MAX_DEPTH 1
m->m_type = r;
}
+
+/*===========================================================================*
+ * nested_dev_call *
+ *===========================================================================*/
+PUBLIC void nested_dev_call(m)
+message *m; /* request/reply message pointer */
+{
+/* Handle a nested call from a device driver server.
+ */
+ int r;
+
+ /* Save global variables of the current call */
+ if ((r = push_globals()) != OK) {
+ printf("VFS: error saving globals in call %d from driver %d\n",
+ m->m_type, m->m_source);
+ } else {
+ /* Initialize global variables for the nested call */
+ set_globals(m);
+
+ if (call_nr >= PFS_BASE) {
+ call_nr -= PFS_BASE;
+ }
+
+ /* Perform the nested call */
+ if (call_nr < 0 || call_nr >= PFS_NREQS) {
+
+ printf("VFS: invalid nested call %d from driver %d\n",
+ call_nr, who_e);
+
+ r = ENOSYS;
+ } else if (who_e == PFS_PROC_NR) {
+
+ r = (*pfs_call_vec[call_nr])();
+ } else {
+
+ printf("VFS: only the PFS device can make nested VFS calls\n");
+
+ r = ENOSYS;
+ }
+
+ /* Store the result, and restore original global variables */
+ *m = m_out;
+
+ pop_globals();
+ }
+
+ m->m_type = r;
+}
/* Data initialized elsewhere. */
extern _PROTOTYPE (int (*call_vec[]), (void) ); /* sys call table */
+extern _PROTOTYPE (int (*pfs_call_vec[]), (void) ); /* pfs callback table */
extern char dot1[2]; /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
extern char dot2[3]; /* meaning to search_dir: no access permission check. */
/* See if 'name1' (file to be linked to) exists. */
if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
/* Does the final directory of 'name2' exist? */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
r = err_code;
- else if ((vp_d = last_dir()) == NULL)
+ else if ((vp_d = last_dir(fp)) == NULL)
r = err_code;
if (r != OK) {
put_vnode(vp);
/* Get the last directory in the path. */
if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
- if ((vldirp = last_dir()) == NULL) return(err_code);
+ if ((vldirp = last_dir(fp)) == NULL) return(err_code);
/* Make sure that the object is a directory */
if((vldirp->v_mode & I_TYPE) != I_DIRECTORY) {
user is allowed to unlink */
if ((vldirp->v_mode & S_ISVTX) == S_ISVTX) {
/* Look up inode of file to unlink to retrieve owner */
- vp = advance(vldirp, PATH_RET_SYMLINK);
+ vp = advance(vldirp, PATH_RET_SYMLINK, fp);
if (vp != NULL) {
if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
r = EPERM;
/* See if 'name1' (existing file) exists. Get dir and file inodes. */
if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- if ((old_dirp = last_dir()) == NULL) return(err_code);
+ if ((old_dirp = last_dir(fp)) == NULL) return(err_code);
/* If the sticky bit is set, only the owner of the file or a privileged
user is allowed to rename */
if((old_dirp->v_mode & S_ISVTX) == S_ISVTX) {
/* Look up inode of file to unlink to retrieve owner */
- vp = advance(old_dirp, PATH_RET_SYMLINK);
+ vp = advance(old_dirp, PATH_RET_SYMLINK, fp);
if (vp != NULL) {
if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
r = EPERM;
/* See if 'name2' (new name) exists. Get dir inode */
if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
r = err_code;
- else if ((new_dirp = last_dir()) == NULL)
+ else if ((new_dirp = last_dir(fp)) == NULL)
r = err_code;
if (r != OK) {
put_vnode(old_dirp);
/* Temporarily open file */
if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
/* Ask FS to truncate the file */
if ((r = forbidden(vp, W_BIT)) == OK)
/* Get dir inode of 'name2' */
if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK) return(err_code);
- if ((vp = last_dir()) == NULL) return(err_code);
+ if ((vp = last_dir(fp)) == NULL) return(err_code);
if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
r = req_slink(vp->v_fs_e, vp->v_inode_nr, user_fullpath, who_e,
return(r);
}
+/*===========================================================================*
+ * rdlink_direct *
+ *===========================================================================*/
+PUBLIC int rdlink_direct(orig_path, link_path, rfp)
+char *orig_path;
+char *link_path; /* should have length PATH_MAX+1 */
+struct fproc *rfp;
+{
+/* Perform a readlink()-like call from within the VFS */
+ int r;
+ struct vnode *vp;
+
+ /* Temporarily open the file containing the symbolic link */
+ strncpy(user_fullpath, orig_path, PATH_MAX);
+ if ((vp = eat_path(PATH_RET_SYMLINK, rfp)) == NULL) return(err_code);
+
+ /* Make sure this is a symbolic link */
+ if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
+ r = EINVAL;
+ else
+ r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, (endpoint_t) 0,
+ link_path, PATH_MAX+1, 1);
+
+ put_vnode(vp);
+ return r;
+}
/*===========================================================================*
* do_rdlink *
/* Temporarily open the file containing the symbolic link */
if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_RET_SYMLINK)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_RET_SYMLINK, fp)) == NULL) return(err_code);
/* Make sure this is a symbolic link */
if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
r = EINVAL;
else
- r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, copylen);
+ r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2,
+ copylen, 0);
put_vnode(vp);
return(r);
/* Now get the inode of the file to be mounted on. */
if (fetch_name(m_in.name2, m_in.name2_length, M1)!=OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
if (vp->v_ref_count != 1) {
put_vnode(vp);
return(EBUSY);
if(!replace_root) {
/* Get vnode of mountpoint */
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
if (vp->v_ref_count != 1) {
put_vnode(vp);
panic("unmount: strange fs endpoint: %d", vmp->m_fs_e);
if ((r = req_unmount(vmp->m_fs_e)) != OK) /* Not recoverable. */
- printf("VFS: ignoring failed umount attempt (%d)\n", r);
+ printf("VFS: ignoring failed umount attempt (%d) fs pid: %d\n", r,
+ _ENDPOINT_P(vmp->m_fs_e));
if (is_nonedev(vmp->m_dev))
free_nonedev(vmp->m_dev);
struct vnode *vp;
/* Request lookup */
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) {
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) {
return(NO_DEV);
}
flag is set this is an error */
} else {
/* Scan path name */
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
}
/* Claim the file descriptor and filp slot and fill them in. */
if (oflags & O_EXCL) flags |= PATH_RET_SYMLINK;
/* See if the path can be opened down to the last directory. */
- if ((dirp = last_dir()) == NULL) return(NULL);
+ if ((dirp = last_dir(fp)) == NULL) return(NULL);
/* The final directory is accessible. Get final component of the path. */
- vp = advance(dirp, flags);
+ vp = advance(dirp, flags, fp);
/* The combination of a symlink with absolute path followed by a danglink
* symlink results in a new path that needs to be re-resolved entirely. */
struct vnode *slp, *old_wd;
/* Resolve path up to symlink */
- slp = advance(dirp, PATH_RET_SYMLINK);
+ slp = advance(dirp, PATH_RET_SYMLINK, fp);
if (slp != NULL) {
if (S_ISLNK(slp->v_mode)) {
/* Get contents of link */
slp->v_inode_nr,
VFS_PROC_NR,
user_fullpath,
- max_linklen);
+ max_linklen, 0);
if (r < 0) {
/* Failed to read link */
put_vnode(slp);
/* Open directory that's going to hold the new node. */
if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- if((vp = last_dir()) == NULL) return(err_code);
+ if((vp = last_dir(fp)) == NULL) return(err_code);
/* Make sure that the object is a directory */
if((vp->v_mode & I_TYPE) != I_DIRECTORY) {
bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
/* Request lookup */
- if((vp = last_dir()) == NULL) return(err_code);
+ if((vp = last_dir(fp)) == NULL) return(err_code);
/* Make sure that the object is a directory */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
return(OK);
}
-
-/*===========================================================================*
- * close_filp *
- *===========================================================================*/
-PUBLIC void close_filp(fp)
-struct filp *fp;
-{
- int mode_word, rw;
- dev_t dev;
- struct vnode *vp;
-
- vp = fp->filp_vno;
- if (fp->filp_count - 1 == 0 && fp->filp_mode != FILP_CLOSED) {
- /* Check to see if the file is special. */
- mode_word = vp->v_mode & I_TYPE;
- if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
- dev = (dev_t) vp->v_sdev;
- if (mode_word == I_BLOCK_SPECIAL) {
- if (vp->v_bfs_e == ROOT_FS_E) {
- /* Invalidate the cache unless the special is
- * mounted. Assume that the root filesystem's
- * is open only for fsck.
- */
- req_flush(vp->v_bfs_e, dev);
- }
- }
- /* Do any special processing on device close. */
- (void) dev_close(dev, fp-filp);
- /* Ignore any errors, even SUSPEND. */
-
- fp->filp_mode = FILP_CLOSED;
- }
- }
-
- /* If the inode being closed is a pipe, release everyone hanging on it. */
- if (vp->v_pipe == I_PIPE) {
- rw = (fp->filp_mode & R_BIT ? WRITE : READ);
- release(vp, rw, NR_PROCS);
- }
-
- /* If a write has been done, the inode is already marked as DIRTY. */
- if (--fp->filp_count == 0) {
- if (vp->v_pipe == I_PIPE) {
- /* Last reader or writer is going. Tell PFS about latest
- * pipe size.
- */
- truncate_vnode(vp, vp->v_size);
- }
-
- put_vnode(fp->filp_vno);
- }
-}
-
-
/*===========================================================================*
* close_reply *
*===========================================================================*/
#include <unistd.h>
#include <assert.h>
#include <minix/vfsif.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <dirent.h>
#include "fproc.h"
#include "vmnt.h"
#include "vnode.h"
#define DO_POSIX_PATHNAME_RES 0
FORWARD _PROTOTYPE( int lookup, (struct vnode *dirp, int flags,
- node_details_t *node) );
+ node_details_t *node, struct fproc *rfp));
/*===========================================================================*
* advance *
*===========================================================================*/
-PUBLIC struct vnode *advance(dirp, flags)
+PUBLIC struct vnode *advance(dirp, flags, rfp)
struct vnode *dirp;
int flags;
+struct fproc *rfp;
{
/* Resolve a pathname (in user_fullpath) starting at dirp to a vnode. */
int r;
if((new_vp = get_free_vnode()) == NULL) return(NULL);
/* Lookup vnode belonging to the file. */
- if ((r = lookup(dirp, flags, &res)) != OK) {
+ if ((r = lookup(dirp, flags, &res, rfp)) != OK) {
err_code = r;
return(NULL);
}
/*===========================================================================*
* eat_path *
*===========================================================================*/
-PUBLIC struct vnode *eat_path(flags)
+PUBLIC struct vnode *eat_path(flags, rfp)
int flags;
+struct fproc *rfp;
{
/* Resolve 'user_fullpath' to a vnode. advance does the actual work. */
struct vnode *vp;
- vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
- return advance(vp, flags);
+ vp = (user_fullpath[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
+ return advance(vp, flags, rfp);
}
/*===========================================================================*
- * last_dir *
+ * last_dir *
*===========================================================================*/
-PUBLIC struct vnode *last_dir(void)
+PUBLIC struct vnode *last_dir(rfp)
+struct fproc *rfp;
{
/* Parse a path, 'user_fullpath', as far as the last directory, fetch the vnode
* for the last directory into the vnode table, and return a pointer to the
struct vnode *vp, *res;
/* Is the path absolute or relative? Initialize 'vp' accordingly. */
- vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
+ vp = (user_fullpath[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
len = strlen(user_fullpath);
cp--;
}
- res = advance(vp, PATH_NOFLAGS);
+ res = advance(vp, PATH_NOFLAGS, rfp);
if (res == NULL) return(NULL);
/* Copy the directory entry back to user_fullpath */
/*===========================================================================*
* lookup *
*===========================================================================*/
-PRIVATE int lookup(start_node, flags, node)
+PRIVATE int lookup(start_node, flags, node, rfp)
struct vnode *start_node;
int flags;
node_details_t *node;
+struct fproc *rfp;
{
/* Resolve a pathname (in user_fullpath) relative to start_node. */
return(ENOENT);
}
- if(!fp->fp_rd || !fp->fp_wd) {
- printf("VFS: lookup_rel %d: no rd/wd\n", fp->fp_endpoint);
+ if(!rfp->fp_rd || !rfp->fp_wd) {
+ printf("VFS: lookup_rel %d: no rd/wd\n", rfp->fp_endpoint);
return(ENOENT);
}
/* Is the process' root directory on the same partition?,
* if so, set the chroot directory too. */
- if (fp->fp_rd->v_dev == fp->fp_wd->v_dev)
- root_ino = fp->fp_rd->v_inode_nr;
+ if (rfp->fp_rd->v_dev == rfp->fp_wd->v_dev)
+ root_ino = rfp->fp_rd->v_inode_nr;
else
root_ino = 0;
/* Set user and group ids according to the system call */
- uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
- gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
+ uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
+ gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
symloop = 0; /* Number of symlinks seen so far */
/* Issue the request */
- r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res);
+ r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res, rfp);
if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
return(r); /* i.e., an error occured */
/* Symlink encountered with absolute path */
if (r == ESYMLINK) {
- dir_vp = fp->fp_rd;
+ dir_vp = rfp->fp_rd;
} else if (r == EENTERMOUNT) {
/* Entering a new partition */
dir_vp = 0;
/* Is the process' root directory on the same partition?,
* if so, set the chroot directory too. */
- if(dir_vp->v_dev == fp->fp_rd->v_dev)
- root_ino = fp->fp_rd->v_inode_nr;
+ if(dir_vp->v_dev == rfp->fp_rd->v_dev)
+ root_ino = rfp->fp_rd->v_inode_nr;
else
root_ino = 0;
- r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res);
+ r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res, rfp);
if(r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
return(r);
return(r);
}
+
+/*===========================================================================*
+ * get_name *
+ *===========================================================================*/
+PUBLIC int get_name(dirp, entry, ename)
+struct vnode *dirp;
+struct vnode *entry;
+char ename[NAME_MAX + 1];
+{
+ u64_t pos = {0, 0}, new_pos;
+ int r, consumed, totalbytes;
+ char buf[(sizeof(struct dirent) + NAME_MAX) * 8];
+ struct dirent *cur;
+
+ if ((dirp->v_mode & I_TYPE) != I_DIRECTORY) {
+ return(EBADF);
+ }
+
+ do {
+ r = req_getdents(dirp->v_fs_e, dirp->v_inode_nr, pos,
+ buf, sizeof(buf), &new_pos, 1);
+
+ if (r == 0) {
+ return(ENOENT); /* end of entries -- matching inode !found */
+ } else if (r < 0) {
+ return(r); /* error */
+ }
+
+ consumed = 0; /* bytes consumed */
+ totalbytes = r; /* number of bytes to consume */
+
+ do {
+ cur = (struct dirent *) (buf + consumed);
+ if (entry->v_inode_nr == cur->d_ino) {
+ /* found the entry we were looking for */
+ strncpy(ename, cur->d_name, NAME_MAX);
+ ename[NAME_MAX] = '\0';
+ return(OK);
+ }
+
+ /* not a match -- move on to the next dirent */
+ consumed += cur->d_reclen;
+ } while (consumed < totalbytes);
+
+ pos = new_pos;
+ } while (1);
+}
+
+/*===========================================================================*
+ * canonical_path *
+ *===========================================================================*/
+PUBLIC int canonical_path(orig_path, canon_path, rfp)
+char *orig_path;
+char *canon_path; /* should have length PATH_MAX+1 */
+struct fproc *rfp;
+{
+ int len = 0;
+ int r, symloop = 0;
+ struct vnode *dir_vp, *parent_dir;
+ char component[NAME_MAX+1];
+ char link_path[PATH_MAX+1];
+
+ dir_vp = NULL;
+ strncpy(user_fullpath, orig_path, PATH_MAX);
+
+ do {
+ if (dir_vp) put_vnode(dir_vp);
+
+ /* Resolve to the last directory holding the socket file */
+ if ((dir_vp = last_dir(rfp)) == NULL) {
+ return(err_code);
+ }
+
+ /* dir_vp points to dir and user_fullpath now contains only the
+ * filename.
+ */
+ strcpy(canon_path, user_fullpath); /* Store file name */
+
+ /* check if the file is a symlink, if so resolve it */
+ r = rdlink_direct(canon_path, link_path, rfp);
+ if (r <= 0) {
+ strcpy(user_fullpath, canon_path);
+ break;
+ }
+
+ /* encountered a symlink -- loop again */
+ strcpy(user_fullpath, link_path);
+
+ symloop++;
+ } while (symloop < SYMLOOP_MAX);
+
+ if (symloop >= SYMLOOP_MAX) {
+ if (dir_vp) put_vnode(dir_vp);
+ return ELOOP;
+ }
+
+ while(dir_vp != rfp->fp_rd) {
+
+ strcpy(user_fullpath, "..");
+
+ /* check if we're at the root node of the file system */
+ if (dir_vp->v_vmnt->m_root_node == dir_vp) {
+ put_vnode(dir_vp);
+ dir_vp = dir_vp->v_vmnt->m_mounted_on;
+ dup_vnode(dir_vp);
+ }
+
+ if ((parent_dir = advance(dir_vp, PATH_NOFLAGS, rfp)) == NULL) {
+ put_vnode(dir_vp);
+ return(err_code);
+ }
+
+ /* now we have to retrieve the name of the parent directory */
+ if (get_name(parent_dir, dir_vp, component) != OK) {
+ put_vnode(dir_vp);
+ put_vnode(parent_dir);
+ return(ENOENT);
+ }
+
+ len += strlen(component) + 1;
+ if (len > PATH_MAX) {
+ /* adding the component to canon_path would exceed PATH_MAX */
+ put_vnode(dir_vp);
+ put_vnode(parent_dir);
+ return(ENOMEM);
+ }
+
+ /* store result of component in canon_path */
+
+ /* first make space by moving the contents of canon_path to
+ * the right. Move strlen + 1 bytes to include the terminating '\0'.
+ */
+ memmove(canon_path+strlen(component)+1, canon_path,
+ strlen(canon_path) + 1);
+
+ /* Copy component into canon_path */
+ memmove(canon_path, component, strlen(component));
+
+ /* Put slash into place */
+ canon_path[strlen(component)] = '/';
+
+ /* Store parent_dir result, and continue the loop once more */
+ put_vnode(dir_vp);
+ dir_vp = parent_dir;
+ }
+
+ put_vnode(dir_vp);
+
+ /* add the leading slash */
+ if (strlen(canon_path) >= PATH_MAX) return(ENAMETOOLONG);
+ memmove(canon_path+1, canon_path, strlen(canon_path));
+ canon_path[0] = '/';
+
+ return(OK);
+}
+
+/*===========================================================================*
+ * check_perms *
+ *===========================================================================*/
+PUBLIC int check_perms(ep, io_gr, pathlen)
+endpoint_t ep;
+cp_grant_id_t io_gr;
+int pathlen;
+{
+ int r, i;
+ struct vnode *vp;
+ struct fproc *rfp;
+ char orig_path[PATH_MAX+1];
+ char canon_path[PATH_MAX+1];
+
+ i = _ENDPOINT_P(ep);
+ if (pathlen < UNIX_PATH_MAX || pathlen > PATH_MAX || i < 0 || i >= NR_PROCS) {
+ return EINVAL;
+ }
+ rfp = &(fproc[i]);
+
+ memset(canon_path, '\0', PATH_MAX+1);
+
+ r = sys_safecopyfrom(PFS_PROC_NR, io_gr, (vir_bytes) 0,
+ (vir_bytes) &user_fullpath, pathlen, D);
+ if (r != OK) {
+ return r;
+ }
+ user_fullpath[pathlen] = '\0';
+
+ /* save path from pfs before permissions checking modifies it */
+ memcpy(orig_path, user_fullpath, PATH_MAX+1);
+
+ /* get the canonical path to the socket file */
+ r = canonical_path(orig_path, canon_path, rfp);
+ if (r != OK) {
+ return r;
+ }
+
+ if (strlen(canon_path) >= pathlen) {
+ return ENAMETOOLONG;
+ }
+
+ /* copy canon_path back to PFS */
+ r = sys_safecopyto(PFS_PROC_NR, (cp_grant_id_t) io_gr, (vir_bytes) 0,
+ (vir_bytes) canon_path, strlen(canon_path)+1,
+ D);
+ if (r != OK) {
+ return r;
+ }
+
+ /* reload user_fullpath for permissions checking */
+ memcpy(user_fullpath, orig_path, PATH_MAX+1);
+ if ((vp = eat_path(PATH_NOFLAGS, rfp)) == NULL) {
+ return(err_code);
+ }
+
+ /* check permissions */
+ r = forbidden(vp, (R_BIT | W_BIT));
+
+ put_vnode(vp);
+ return(r);
+}
+
+/*===========================================================================*
+ * do_check_perms *
+ *===========================================================================*/
+PUBLIC int do_check_perms(void)
+{
+ return check_perms(m_in.IO_ENDPT, (cp_grant_id_t) m_in.IO_GRANT, m_in.COUNT);
+}
#include "vnode.h"
#include "vmnt.h"
-FORWARD _PROTOTYPE( int in_group, (gid_t grp) );
-
/*===========================================================================*
* do_chmod *
*===========================================================================*/
if (call_nr == CHMOD) {
/* Temporarily open the file */
if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
} else { /* call_nr == FCHMOD */
/* File is already opened; get a pointer to vnode from filp. */
if (!(flp = get_filp(m_in.fd))) return(err_code);
if (call_nr == CHOWN) {
/* Temporarily open the file. */
if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
} else { /* call_nr == FCHOWN */
/* File is already opened; get a pointer to the vnode from filp. */
if (!(flp = get_filp(m_in.fd))) return(err_code);
/* Temporarily open the file. */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
r = forbidden(vp, m_in.mode);
put_vnode(vp);
} else {
if (uid == vp->v_uid) shift = 6; /* owner */
else if (gid == vp->v_gid) shift = 3; /* group */
- else if (in_group(vp->v_gid) == OK) shift = 3; /* suppl. groups */
+ else if (in_group(fp, vp->v_gid) == OK) shift = 3; /* suppl. groups */
else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
}
return(r);
}
-
-/*===========================================================================*
- * in_group *
- *===========================================================================*/
-PRIVATE int in_group(gid_t grp)
-{
- int i;
-
- for (i = 0; i < fp->fp_ngroups; i++)
- if (fp->fp_sgroups[i] == grp)
- return(OK);
-
- return(EINVAL);
-}
-
-
/*===========================================================================*
* read_only *
*===========================================================================*/
struct vmnt;
struct vnode;
+typedef struct filp * filp_id_t;
+
/* device.c */
_PROTOTYPE( int dev_open, (dev_t dev, int proc, int flags) );
_PROTOTYPE( int dev_reopen, (dev_t dev, int filp_no, int flags) );
_PROTOTYPE( struct filp *get_filp, (int fild) );
_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild) );
_PROTOTYPE( int invalidate, (struct filp *) );
+_PROTOTYPE( filp_id_t verify_fd, (endpoint_t ep, int fd) );
+_PROTOTYPE( int do_verify_fd, (void) );
+_PROTOTYPE( int set_filp, (filp_id_t sfilp) );
+_PROTOTYPE( int do_set_filp, (void) );
+_PROTOTYPE( int copy_filp, (endpoint_t to_ep, filp_id_t cfilp) );
+_PROTOTYPE( int do_copy_filp, (void) );
+_PROTOTYPE( int put_filp, (filp_id_t pfilp) );
+_PROTOTYPE( int do_put_filp, (void) );
+_PROTOTYPE( int cancel_fd, (endpoint_t ep, int fd) );
+_PROTOTYPE( int do_cancel_fd, (void) );
+_PROTOTYPE( void close_filp, (struct filp *fp) );
/* fscall.c */
_PROTOTYPE( void nested_fs_call, (message *m) );
+_PROTOTYPE( void nested_dev_call, (message *m) );
/* link.c */
_PROTOTYPE( int do_link, (void) );
_PROTOTYPE( int do_rename, (void) );
_PROTOTYPE( int do_truncate, (void) );
_PROTOTYPE( int do_ftruncate, (void) );
-_PROTOTYPE( int truncate_vnode, (struct vnode *vp, off_t newsize) );
+_PROTOTYPE( int truncate_vnode, (struct vnode *vp, off_t newsize) );
+_PROTOTYPE( int rdlink_direct, (char *orig_path, char *link_path,
+ struct fproc *rfp) );
/* lock.c */
_PROTOTYPE( int lock_op, (struct filp *f, int req) );
/* open.c */
_PROTOTYPE( int do_close, (void) );
_PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr) );
-_PROTOTYPE( void close_filp, (struct filp *fp) );
_PROTOTYPE( void close_reply, (void) );
_PROTOTYPE( int do_creat, (void) );
_PROTOTYPE( int do_lseek, (void) );
_PROTOTYPE( int do_vm_close, (void) );
/* path.c */
-_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags) );
-_PROTOTYPE( struct vnode *eat_path, (int flags) );
-_PROTOTYPE( struct vnode *last_dir, (void) );
+_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags,
+ struct fproc *rfp) );
+_PROTOTYPE( struct vnode *eat_path, (int flags, struct fproc *rfp) );
+_PROTOTYPE( struct vnode *last_dir, (struct fproc *rfp) );
+_PROTOTYPE( int get_name, (struct vnode *dirp, struct vnode *entry,
+ char *_name) );
+_PROTOTYPE( int canonical_path, (char *orig_path, char *canon_path,
+ struct fproc *rfp) );
+_PROTOTYPE( int check_perms, (endpoint_t ep, cp_grant_id_t gid,
+ int strlen) );
+_PROTOTYPE( int do_check_perms, (void) );
/* pipe.c */
_PROTOTYPE( int do_pipe, (void) );
_PROTOTYPE( int req_statvfs, (int fs_e, int who_e, char *buf) );
_PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr,
off_t start, off_t end) );
-_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr, u64_t pos,
- char *buf, size_t size, u64_t *new_pos) );
+_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr,
+ u64_t pos, char *buf, size_t size,
+ u64_t *new_pos, int direct) );
_PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr) );
_PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent,
char *lastc, ino_t linked_file) );
_PROTOTYPE( int req_lookup, (endpoint_t fs_e, ino_t dir_ino, ino_t root_ino,
uid_t uid, gid_t gid, int flags,
- lookup_res_t *res) );
+ lookup_res_t *res, struct fproc *rfp) );
_PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr,
char *lastc, uid_t uid, gid_t gid, mode_t dmode) );
_PROTOTYPE( int req_mknod, (endpoint_t fs_e, ino_t inode_nr,
dev_t dev, struct node_details *res) );
_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) );
_PROTOTYPE( int req_rdlink, (endpoint_t fs_e, ino_t inode_nr,
- endpoint_t who_e, char *buf, size_t len) );
+ endpoint_t who_e, char *buf, size_t len,
+ int direct) );
_PROTOTYPE( int req_readsuper, (endpoint_t fs_e, char *driver_name,
dev_t dev, int readonly, int isroot,
struct node_details *res_nodep) );
_PROTOTYPE( int fetch_name, (char *path, int len, int flag) );
_PROTOTYPE( int no_sys, (void) );
_PROTOTYPE( int isokendpt_f, (char *f, int l, endpoint_t e, int *p, int ft));
+_PROTOTYPE( int in_group, (struct fproc *rfp, gid_t grp) );
#define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
#define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
panic("do_getdents: should handle large offsets");
r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
- rfilp->filp_pos, m_in.buffer, m_in.nbytes, &new_pos);
+ rfilp->filp_pos, m_in.buffer, m_in.nbytes, &new_pos, 0);
if (r > 0)
rfilp->filp_pos = new_pos;
u64_t pos,
char *buf,
size_t size,
- u64_t *new_pos
+ u64_t *new_pos,
+ int direct
)
{
int r;
message m;
cp_grant_id_t grant_id;
-
- grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size, CPF_WRITE);
+
+ if (direct) {
+ grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size,
+ CPF_WRITE);
+ } else {
+ grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
+ CPF_WRITE);
+ }
+
if (grant_id < 0)
- panic("req_getdents: cpf_grant_magic failed: %d", grant_id);
+ panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
+ grant_id);
m.m_type = REQ_GETDENTS;
m.REQ_INODE_NR = inode_nr;
return(r);
}
-
/*===========================================================================*
* req_inhibread *
*===========================================================================*/
uid_t uid,
gid_t gid,
int flags,
- lookup_res_t *res
+ lookup_res_t *res,
+ struct fproc *rfp
)
{
int r;
m.REQ_DIR_INO = dir_ino;
m.REQ_ROOT_INO = root_ino;
- if(fp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
+ if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
/* In that case the FS has to copy the uid/gid credentials */
int i;
/* Set credentials */
- credentials.vu_uid = fp->fp_effuid;
- credentials.vu_gid = fp->fp_effgid;
- credentials.vu_ngroups = fp->fp_ngroups;
- for (i = 0; i < fp->fp_ngroups; i++)
- credentials.vu_sgroups[i] = fp->fp_sgroups[i];
+ credentials.vu_uid = rfp->fp_effuid;
+ credentials.vu_gid = rfp->fp_effgid;
+ credentials.vu_ngroups = rfp->fp_ngroups;
+ for (i = 0; i < rfp->fp_ngroups; i++)
+ credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
sizeof(credentials), CPF_READ);
/* Send/rec request */
r = fs_sendrec(fs_e, &m);
cpf_revoke(grant_id);
- if(fp->fp_ngroups > 0) cpf_revoke(grant_id2);
+ if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2);
/* Fill in response according to the return value */
res->fs_e = m.m_source;
/*===========================================================================*
* req_rdlink *
*===========================================================================*/
-PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len)
+PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len, direct)
endpoint_t fs_e;
ino_t inode_nr;
endpoint_t who_e;
char *buf;
size_t len;
+int direct; /* set to 1 to use direct grants instead of magic grants */
{
message m;
int r;
cp_grant_id_t grant_id;
- grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len, CPF_WRITE);
+ if (direct) {
+ grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE);
+ } else {
+ grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len,
+ CPF_WRITE);
+ }
if(grant_id == -1)
panic("req_rdlink: cpf_grant_magic failed");
/* Try to open the directory */
if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
return change_into(iip, vp);
}
struct vnode *vp;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) 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);
put_vnode(vp);
struct vnode *vp;
if (fetch_name(m_in.STATVFS_NAME, m_in.STATVFS_LEN, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
r = req_statvfs(vp->v_fs_e, who_e, m_in.STATVFS_BUF);
put_vnode(vp);
int r;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_RET_SYMLINK)) == NULL) 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);
put_vnode(vp);
/* This should not fail with "array size is negative": */
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
+PUBLIC _PROTOTYPE (int (*pfs_call_vec[]), (void) ) = {
+
+ no_sys, /* 0 */
+ do_check_perms, /* 1 */
+ do_verify_fd, /* 2 */
+ do_set_filp, /* 3 */
+ do_copy_filp, /* 4 */
+ do_put_filp, /* 5 */
+ do_cancel_fd /* 6 */
+};
/* Temporarily open the file */
if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
- if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
/* Only the owner of a file or the super user can change its name. */
r = OK;
* panic: something awful has occurred; MINIX cannot continue
* conv2: do byte swapping on a 16-bit int
* conv4: do byte swapping on a 32-bit long
+ * in_group: determines if group 'grp' is in rfp->fp_sgroups[]
*/
#include "fs.h"
return( (time_t) (boottime + (uptime/system_hz)));
}
+/*===========================================================================*
+ * in_group *
+ *===========================================================================*/
+PUBLIC int in_group(struct fproc *rfp, gid_t grp)
+{
+ int i;
+
+ for (i = 0; i < rfp->fp_ngroups; i++) {
+ if (rfp->fp_sgroups[i] == grp) {
+ return(OK);
+ }
+ }
+
+ return(EINVAL);
+}
+