#define DIR_ENTRY_SIZE usizeof (struct direct) /* # bytes/dir entry */
#define NR_DIR_ENTRIES(b) ((b)/DIR_ENTRY_SIZE) /* # dir entries/blk */
#define SUPER_SIZE usizeof (struct super_block) /* super_block size */
-#define PIPE_SIZE(b) (V1_NR_DZONES*(b)) /* pipe size in bytes */
#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk */
#define FS_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT)
#define V2_INDIRECTS(b) ((b)/V2_ZONE_NUM_SIZE) /* # zones/indir block */
#define V2_INODES_PER_BLOCK(b) ((b)/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
-/* Args to dev_bio/dev_io */
+/* Args to dev_io */
#define VFS_DEV_READ 2001
#define VFS_DEV_WRITE 2002
#define VFS_DEV_SCATTER 2003
return;
}
-#if 0
-/*===========================================================================*
- * dev_bio *
- *===========================================================================*/
-PUBLIC int dev_bio(op, dev, proc_e, buf, pos, bytes)
-int op; /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
-dev_t dev; /* major-minor device number */
-int proc_e; /* in whose address space is buf? */
-void *buf; /* virtual address of the buffer */
-off_t pos; /* byte position */
-int bytes; /* how many bytes to transfer */
-{
-/* Read or write from a device. The parameter 'dev' tells which one. */
- struct dmap *dp;
- int r, safe;
- message m;
- iovec_t *v;
- cp_grant_id_t gid = GRANT_INVALID;
- int vec_grants;
-
- /* Determine task dmap. */
- dp = &dmap[(dev >> MAJOR) & BYTE];
-
- /* The io vector copying relies on this I/O being for FS itself. */
- if(proc_e != FS_PROC_NR)
- panic(__FILE__, "doing dev_bio for non-self", proc_e);
-
- for (;;)
- {
- int op_used;
- void *buf_used;
- static cp_grant_id_t gids[NR_IOREQS];
- cp_grant_id_t gid = GRANT_INVALID;
- int vec_grants;
-
- /* See if driver is roughly valid. */
- if (dp->dmap_driver == NONE) {
- printf("FS: dev_io: no driver for dev %x\n", dev);
- return ENXIO;
- }
-
- /* By default, these are right. */
- m.IO_ENDPT = proc_e;
- m.ADDRESS = buf;
- buf_used = buf;
-
- /* Convert parameters to 'safe mode'. */
- op_used = op;
- safe = safe_io_conversion(dp->dmap_driver, &gid,
- &op_used, gids, NR_IOREQS, &m.IO_ENDPT, &buf_used,
- &vec_grants, bytes, &pos);
-
- /* Set up rest of the message. */
- if(safe) m.IO_GRANT = (char *) gid;
-
- m.m_type = op_used;
- m.DEVICE = (dev >> MINOR) & BYTE;
- m.POSITION = pos;
- m.COUNT = bytes;
- m.HIGHPOS = 0;
-
- /* Call the task. */
- (*dp->dmap_io)(dp->dmap_driver, &m);
-
- /* As block I/O never SUSPENDs, safe cleanup must be done whether
- * the I/O succeeded or not.
- */
- if(safe) safe_io_cleanup(gid, gids, vec_grants);
-
- if(dp->dmap_driver == NONE) {
- /* Driver has vanished. Wait for a new one. */
- for (;;)
- {
- r= receive(RS_PROC_NR, &m);
- if (r != OK)
- {
- panic(__FILE__,
- "dev_bio: unable to receive from RS",
- r);
- }
- if (m.m_type == DEVCTL)
- {
- r= fs_devctl(m.ctl_req, m.dev_nr, m.driver_nr,
- m.dev_style, m.m_force);
- }
- else
- {
- panic(__FILE__,
- "dev_bio: got message from RS, type",
- m.m_type);
- }
- m.m_type= r;
- r= send(RS_PROC_NR, &m);
- if (r != OK)
- {
- panic(__FILE__,
- "dev_bio: unable to send to RS",
- r);
- }
- if (dp->dmap_driver != NONE)
- break;
- }
- printf("dev_bio: trying new driver\n");
- continue;
- }
-
- /* Task has completed. See if call completed. */
- if (m.REP_STATUS == SUSPEND) {
- panic(__FILE__, "dev_bio: driver returned SUSPEND", NO_NUM);
- }
-
- if(buf != buf_used) {
- memcpy(buf, buf_used, bytes * sizeof(iovec_t));
- }
-
- return(m.REP_STATUS);
- }
-}
-#endif
/*===========================================================================*
* dev_io *
if (dp->dmap_driver == NONE) {
- printf("FS: clone_opcl: no driver for dev %x\n", dev);
+ printf("vfs:clone_opcl: no driver for dev %x\n", dev);
return ENXIO;
}
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
- printf("FS: clone_opcl: old driver for dev %x (%d)\n",
+ printf("vfs:clone_opcl: bad driver endpoint for dev %x (%d)\n",
dev, dp->dmap_driver);
return ENXIO;
}
if (dev_mess.REP_STATUS != minor) {
struct vnode *vp;
struct vmnt *vmp;
-
- struct clone_opcl_req req;
struct node_details res;
+
/* A new minor device number has been returned.
- * Request root FS to create a temporary device file to hold it.
+ * Request the root FS to create a temporary device file to
+ * hold it.
*/
/* Device number of the new device. */
- dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
-
- /* Fill in request */
- req.fs_e = ROOT_FS_E;
- req.dev = dev;
+ dev = (dev & ~(BYTE << MINOR)) |
+ (dev_mess.REP_STATUS << MINOR);
/* Issue request */
- if ((r = req_clone_opcl(&req, &res)) != OK) {
+ r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid,
+ ALL_MODES | I_CHAR_SPECIAL, dev, &res);
+ if (r != OK) {
(void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
return r;
}
put_vnode(vp);
if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
- printf("VFSclone_opcl: failed to get a free vnode..\n");
+ printf(
+ "vfs:clone_opcl: failed to get a free vnode..\n");
vp = fp->fp_filp[m_in.fd]->filp_vno;
}
vp->v_fs_e = res.fs_e;
if ((vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
- printf("VFSclone_opcl: no vmnt found\n");
+ printf("vfs:clone_opcl: no vmnt found\n");
vp->v_vmnt = vmp;
vp->v_dev = vmp->m_dev;
+ vp->v_fs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr;
vp->v_mode = res.fmode;
vp->v_sdev = dev;
return(dev_mess.REP_STATUS);
}
+
/*===========================================================================*
* dev_up *
*===========================================================================*/
#include <ctype.h>
#include <unistd.h>
#include <minix/com.h>
+#include <minix/ds.h>
#include "param.h"
/* Some devices may or may not be there in the next table. */
-#define DT(enable, opcl, io, driver, flags) \
+#define DT(enable, opcl, io, driver, flags, label) \
{ (enable?(opcl):no_dev), (enable?(io):0), \
- (enable?(driver):0), (flags) },
+ (enable?(driver):0), (flags), label },
#define NC(x) (NR_CTRLRS >= (x))
/* The order of the entries here determines the mapping between major device
*/
struct dmap dmap[NR_DEVICES]; /* actual map */
PRIVATE struct dmap init_dmap[] = {
- DT(1, no_dev, 0, 0, 0) /* 0 = not used */
- DT(1, gen_opcl, gen_io, MEM_PROC_NR, 0) /* 1 = /dev/mem */
- DT(0, no_dev, 0, 0, DMAP_MUTABLE) /* 2 = /dev/fd0 */
- DT(0, no_dev, 0, 0, DMAP_MUTABLE) /* 3 = /dev/c0 */
- DT(1, tty_opcl, gen_io, TTY_PROC_NR, 0) /* 4 = /dev/tty00 */
- DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0) /* 5 = /dev/tty */
- DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 6 = /dev/lp */
+ DT(1, no_dev, 0, 0, 0, "") /* 0 = not used */
+ DT(1, gen_opcl, gen_io, MEM_PROC_NR, 0, "memory") /* 1 = /dev/mem */
+ DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /* 2 = /dev/fd0 */
+ DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /* 3 = /dev/c0 */
+ DT(1, tty_opcl, gen_io, TTY_PROC_NR, 0, "") /* 4 = /dev/tty00 */
+ DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0, "") /* 5 = /dev/tty */
+ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 6 = /dev/lp */
#if (MACHINE == IBM_PC)
- DT(1, no_dev, 0, 0, DMAP_MUTABLE) /* 7 = /dev/ip */
- DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 8 = /dev/c1 */
- DT(0, 0, 0, 0, DMAP_MUTABLE) /* 9 = not used */
- DT(0, no_dev, 0, 0, DMAP_MUTABLE) /*10 = /dev/c2 */
- DT(0, 0, 0, 0, DMAP_MUTABLE) /*11 = not used */
- DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*12 = /dev/c3 */
- DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*13 = /dev/audio */
- DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*14 = /dev/mixer */
- DT(1, gen_opcl, gen_io, LOG_PROC_NR, 0) /*15 = /dev/klog */
- DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*16 = /dev/random*/
- DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*17 = /dev/cmos */
+ DT(1, no_dev, 0, 0, DMAP_MUTABLE, "") /* 7 = /dev/ip */
+ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 8 = /dev/c1 */
+ DT(0, 0, 0, 0, DMAP_MUTABLE, "") /* 9 = not used */
+ DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /*10 = /dev/c2 */
+ DT(0, 0, 0, 0, DMAP_MUTABLE, "") /*11 = not used */
+ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*12 = /dev/c3 */
+ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*13 = /dev/audio */
+ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*14 = /dev/mixer */
+ DT(1, gen_opcl, gen_io, LOG_PROC_NR, 0, "") /*15 = /dev/klog */
+ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*16 = /dev/random*/
+ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*17 = /dev/cmos */
#endif /* IBM_PC */
};
+FORWARD _PROTOTYPE( int map_driverX, (char *label, int major,
+ endpoint_t proc_nr_e, int style, int force) );
+
/*===========================================================================*
* do_devctl *
*===========================================================================*/
return(result);
}
+
+/*===========================================================================*
+ * do_mapdriver *
+ *===========================================================================*/
+PUBLIC int do_mapdriver()
+{
+ int r, force, major, proc_nr_n;
+ unsigned long tasknr;
+ vir_bytes label_vir;
+ size_t label_len;
+ char label[16];
+
+ if (!super_user)
+ {
+ printf("FS: unauthorized call of do_mapdriver by proc %d\n",
+ who_e);
+ return(EPERM); /* only su (should be only RS or some drivers)
+ * may call do_mapdriver.
+ */
+ }
+
+ /* Get the label */
+ label_vir= (vir_bytes)m_in.md_label;
+ label_len= m_in.md_label_len;
+
+ if (label_len+1 > sizeof(label))
+ {
+ printf("vfs:do_mapdriver: label too long\n");
+ return EINVAL;
+ }
+
+ r= sys_vircopy(who_e, D, label_vir, SELF, D, (vir_bytes)label,
+ label_len);
+ if (r != OK)
+ {
+ printf("vfs:do_mapdriver: sys_vircopy failed: %d\n", r);
+ return EINVAL;
+ }
+
+ label[label_len]= '\0';
+
+ r= ds_retrieve_u32(label, &tasknr);
+ if (r != OK)
+ {
+ printf("vfs:do_mapdriver: ds doesn't know '%s'\n", label);
+ return EINVAL;
+ }
+
+ if (isokendpt(tasknr, &proc_nr_n) != OK)
+ return(EINVAL);
+
+ /* Try to update device mapping. */
+ major= m_in.md_major;
+ force= m_in.md_force;
+ r= map_driverX(label, major, tasknr, m_in.md_style, force);
+ if (r == OK)
+ {
+ /* If a driver has completed its exec(), it can be announced
+ * to be up.
+ */
+ if(force || fproc[proc_nr_n].fp_execced) {
+ dev_up(major);
+ } else {
+ dmap[major].dmap_flags |= DMAP_BABY;
+ }
+ }
+
+ return(r);
+}
+
+
/*===========================================================================*
* map_driver *
*===========================================================================*/
return(OK);
}
+
+/*===========================================================================*
+ * map_driverX *
+ *===========================================================================*/
+PRIVATE int map_driverX(label, major, proc_nr_e, style, force)
+char *label; /* name of the driver */
+int major; /* major number of the device */
+endpoint_t proc_nr_e; /* process number of the driver */
+int style; /* style of the device */
+int force;
+{
+/* Set a new device driver mapping in the dmap table. Given that correct
+ * arguments are given, this only works if the entry is mutable and the
+ * current driver is not busy. If the proc_nr is set to NONE, we're supposed
+ * to unmap it.
+ *
+ * Normal error codes are returned so that this function can be used from
+ * a system call that tries to dynamically install a new driver.
+ */
+ int proc_nr_n;
+ size_t len;
+ struct dmap *dp;
+
+ /* Get pointer to device entry in the dmap table. */
+ if (major < 0 || major >= NR_DEVICES) return(ENODEV);
+ dp = &dmap[major];
+
+ /* Check if we're supposed to unmap it. If so, do it even
+ * if busy or unmutable, as unmap is called when driver has
+ * exited.
+ */
+ if(proc_nr_e == NONE) {
+ dp->dmap_opcl = no_dev;
+ dp->dmap_io = no_dev_io;
+ dp->dmap_driver = NONE;
+ dp->dmap_flags = DMAP_MUTABLE; /* When gone, not busy or reserved. */
+ return(OK);
+ }
+
+ /* See if updating the entry is allowed. */
+ if (! (dp->dmap_flags & DMAP_MUTABLE)) return(EPERM);
+ if (dp->dmap_flags & DMAP_BUSY) return(EBUSY);
+
+ if (!force)
+ {
+ /* Check process number of new driver. */
+ if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
+ return(EINVAL);
+ }
+
+ len= strlen(label);
+ if (len+1 > sizeof(dp->dmap_label))
+ panic(__FILE__, "map_driver: label too long", len);
+ strcpy(dp->dmap_label, label);
+
+ /* Try to update the entry. */
+ switch (style) {
+ case STYLE_DEV: dp->dmap_opcl = gen_opcl; break;
+ case STYLE_TTY: dp->dmap_opcl = tty_opcl; break;
+ case STYLE_CLONE: dp->dmap_opcl = clone_opcl; break;
+ default: return(EINVAL);
+ }
+ dp->dmap_io = gen_io;
+ dp->dmap_driver = proc_nr_e;
+
+ return(OK);
+}
+
/*===========================================================================*
* dmap_unmap_by_endpt *
*===========================================================================*/
dp->dmap_io = init_dmap[i].dmap_io;
dp->dmap_driver = init_dmap[i].dmap_driver;
dp->dmap_flags = init_dmap[i].dmap_flags;
+ strcpy(dp->dmap_label, init_dmap[i].dmap_label);
} else { /* no default */
dp->dmap_opcl = no_dev;
dp->dmap_io = no_dev_io;
--- /dev/null
+/*
+dmap.h
+*/
+
+/*===========================================================================*
+ * Device <-> Driver Table *
+ *===========================================================================*/
+
+/* Device table. This table is indexed by major device number. It provides
+ * the link between major device numbers and the routines that process them.
+ * The table can be update dynamically. The field 'dmap_flags' describe an
+ * entry's current status and determines what control options are possible.
+ */
+#define DMAP_MUTABLE 0x01 /* mapping can be overtaken */
+#define DMAP_BUSY 0x02 /* driver busy with request */
+#define DMAP_BABY 0x04 /* driver exec() not done yet */
+
+extern struct dmap {
+ int _PROTOTYPE ((*dmap_opcl), (int, Dev_t, int, int) );
+ int _PROTOTYPE ((*dmap_io), (int, message *) );
+ int dmap_driver;
+ int dmap_flags;
+ char dmap_label[16];
+} dmap[];
char progname[PROC_NAME_LEN];
static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
- /* Request and response structures */
- struct lookup_req lookup_req;
- struct node_details Xres;
-
okendpt(proc_e, &proc_s);
rfp= fp= &fproc[proc_s];
who_e= proc_e;
for (round= 0; round < 2; round++)
/* round = 0 (first attempt), or 1 (interpreted script) */
{
+#if 0
+ printf("vfs:pm_exec: round %d, name '%s'\n", round, user_fullpath);
+#endif
+
/* Save the name of the program */
(cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);
strncpy(progname, cp, PROC_NAME_LEN-1);
progname[PROC_NAME_LEN-1] = '\0';
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup_vp(&lookup_req, &vp)) != OK)
- {
- put_vnode(vp);
+ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK)
return r;
- }
if ((vp->v_mode & I_TYPE) != I_REGULAR) {
put_vnode(vp);
}
/* Check access. */
- if ((r = forbidden(vp, X_BIT)) != OK)
+ if ((r = forbidden(vp, X_BIT, 0 /*!use_realuid*/)) != OK)
{
put_vnode(vp);
return r;
}
v_ctime = sb.st_ctime;
+#if 0
+ printf("vfs:pm_exec: round %d, mode 0%o, uid %d, gid %d\n",
+ round, vp->v_mode, vp->v_uid, vp->v_gid);
+#endif
if (round == 0)
{
/* Deal with setuid/setgid executables */
{
/* Read the header and extract the text, data, bss and total sizes from it. */
off_t pos;
+ int r;
+ u64_t new_pos;
+ unsigned int cum_io_incr;
struct exec hdr; /* a.out header is read in here */
/* Read the header and check the magic number. The standard MINIX header
* used here only. The symbol table is for the benefit of a debugger and
* is ignored here.
*/
-
- struct readwrite_req req;
- struct readwrite_res res;
- int r;
pos= 0; /* Read from the start of the file */
- /* Fill in request structure */
- req.fs_e = vp->v_fs_e;
- req.rw_flag = READING;
- req.inode_nr = vp->v_inode_nr;
- req.user_e = FS_PROC_NR;
- req.seg = D;
- req.pos = cvul64(pos);
- req.num_of_bytes = sizeof(hdr);
- req.user_addr = (char*)&hdr;
- req.inode_index = vp->v_index;
-
/* Issue request */
- if ((r = req_readwrite(&req, &res)) != OK) return r;
+ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index,
+ cvul64(pos), READING, FS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos,
+ &cum_io_incr);
+ if (r != OK) return r;
/* Interpreted script? */
if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2)
int n, r;
off_t pos;
char *sp, *interp = NULL;
+ u64_t new_pos;
+ unsigned int cum_io_incr;
char buf[_MAX_BLOCK_SIZE];
- struct readwrite_req req;
- struct readwrite_res res;
/* Make user_path the new argv[0]. */
if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) return(ENOMEM);
pos = 0; /* Read from the start of the file */
- /* Fill in request structure */
- req.fs_e = vp->v_fs_e;
- req.rw_flag = READING;
- req.inode_nr = vp->v_inode_nr;
- req.user_e = FS_PROC_NR;
- req.seg = D;
- req.pos = cvul64(pos);
- req.num_of_bytes = _MAX_BLOCK_SIZE;
- req.user_addr = buf;
- req.inode_index = vp->v_index;
-
/* Issue request */
- if ((r = req_readwrite(&req, &res)) != OK) return r;
+ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, cvul64(pos),
+ READING, FS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io_incr);
+ if (r != OK) return r;
n = vp->v_size;
- if (n > vp->v_vmnt->m_block_size)
- n = vp->v_vmnt->m_block_size;
+ if (n > _MAX_BLOCK_SIZE)
+ n = _MAX_BLOCK_SIZE;
if (n < 2) return ENOEXEC;
sp = &(buf[2]); /* just behind the #! */
* a segment is padded out to a click multiple, and the data segment is only
* partially initialized.
*/
- struct readwrite_req req;
- struct readwrite_res res;
int r;
+ unsigned n, o;
+ u64_t new_pos;
+ unsigned int cum_io_incr;
+ char buf[1024];
/* Make sure that the file is big enough */
if (vp->v_size < off+seg_bytes) return EIO;
+
+ if (seg != D)
+ {
+ /* We have to use a copy loop until safecopies support segments */
+ o= 0;
+ while (o < seg_bytes)
+ {
+ n= seg_bytes-o;
+ if (n > sizeof(buf))
+ n= sizeof(buf);
+
+#if 0
+printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n",
+ proc_e, seg, buf, n, off+o);
+#endif
+
+ /* Issue request */
+ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index,
+ cvul64(off+o), READING, FS_PROC_NR, buf, n, &new_pos,
+ &cum_io_incr);
+ if (r != OK) return r;
+
+ if (cum_io_incr != n)
+ {
+ printf(
+ "VFSread_seg segment has not been read properly by exec() \n");
+ return EIO;
+ }
+
+ r= sys_vircopy(FS_PROC_NR, D, (vir_bytes)buf, proc_e, seg, o,
+ n);
+ if (r != OK)
+ return r;
+
+ o += n;
+ }
+ return OK;
+ }
- /* Fill in request structure */
- req.fs_e = vp->v_fs_e;
- req.rw_flag = READING;
- req.inode_nr = vp->v_inode_nr;
- req.user_e = proc_e;
- req.seg = seg;
- req.pos = cvul64(off);
- req.num_of_bytes = seg_bytes;
- req.user_addr = 0;
- req.inode_index = vp->v_index;
+#if 0
+printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n",
+ proc_e, seg, 0, seg_bytes, off);
+#endif
/* Issue request */
- if ((r = req_readwrite(&req, &res)) != OK) return r;
+ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, cvul64(off),
+ READING, proc_e, 0, seg_bytes, &new_pos, &cum_io_incr);
+ if (r != OK) return r;
- if (r == OK && res.cum_io != seg_bytes)
+ if (r == OK && cum_io_incr != seg_bytes)
printf("VFSread_seg segment has not been read properly by exec() \n");
return r;
#include <minix/sysutil.h>
#include "const.h"
+#include "dmap.h"
#include "proto.h"
#include "glo.h"
EXTERN int ROOT_FS_E; /* kernel endpoint of the root FS proc */
EXTERN int last_login_fs_e; /* endpoint of the FS proc that logged in
before the corresponding mount request */
-EXTERN time_t boottime; /* time in seconds at system boot */
/* The parameters of the call are kept here. */
EXTERN message m_in; /* the input message itself */
PUBLIC int do_link()
{
/* Perform the link(name1, name2) system call. */
- int linked_fs_e;
- int linked_inode_nr;
- int link_lastdir_fs_e;
- int link_lastdir_inode_nr;
- char string[NAME_MAX];
- struct link_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
+ endpoint_t linked_fs_e, link_lastdir_fs_e;
+ struct vnode *vp_o, *vp_d;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK)
return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp_o)) != OK) return r;
- linked_fs_e = res.fs_e;
- req.linked_file = res.inode_nr;
+ linked_fs_e = vp_o->v_fs_e;
/* Does the final directory of 'name2' exist? */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+ put_vnode(vp_o);
return(err_code);
}
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = string;
- lookup_req.flags = LAST_DIR;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_d)) != OK)
+ {
+ put_vnode(vp_o);
+ return r;
+ }
+
+ link_lastdir_fs_e = vp_d->v_fs_e;
- link_lastdir_fs_e = res.fs_e;
- req.link_parent = res.inode_nr;
-
/* Check for links across devices. */
if (linked_fs_e != link_lastdir_fs_e)
+ {
+ put_vnode(vp_o);
+ put_vnode(vp_d);
return EXDEV;
+ }
- /* Send link request. */
- req.fs_e = linked_fs_e;
- /* Send the last component of the link name */
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
- req.lastc = string;
+ r= forbidden(vp_d, W_BIT|X_BIT, 0 /*!use_realuid*/);
+ if (r != OK)
+ {
+ put_vnode(vp_o);
+ put_vnode(vp_d);
+ return r;
+ }
/* Issue request */
- return req_link(&req);
+ r= req_link(linked_fs_e, vp_d->v_inode_nr, user_fullpath, vp_o->v_inode_nr);
+ put_vnode(vp_o);
+ put_vnode(vp_d);
+ return r;
}
* may be used by the superuser to do dangerous things; rmdir() may not.
*/
register struct fproc *rfp;
- char string[NAME_MAX];
struct vnode *vp;
- struct unlink_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
- string[0] = '\0';
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH_OPAQUE;
-
- /* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+ r= lookup_lastdir(0 /*!use_realuid*/, &vp);
+ if (r != OK)
+ return r;
+
+ /* The caller must have both search and execute permission */
+ r= forbidden(vp, X_BIT|W_BIT, 0 /*!use_realuid*/);
+ if (r != OK)
+ {
+ put_vnode(vp);
+ return r;
+ }
/* If a directory file has to be removed the following conditions have to met:
* - The directory must not be the root of a mounted file system
* - The directory must not be anybody's root/working directory
*/
- if ((res.fmode & I_TYPE) == I_DIRECTORY) {
- /* Only root can unlink a directory */
- if (call_nr == UNLINK && !super_user) return EPERM;
-
- /* Can't remove a root directory */
- if (res.inode_nr == ROOT_INODE) return EBUSY;
-
- /* Can't remove anybody's working directory */
- if ((vp = find_vnode(res.fs_e, res.inode_nr)) !=
- NIL_VNODE) {
- /* Check directories */
- for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS];
- rfp++) {
- if (rfp->fp_pid != PID_FREE &&
- (rfp->fp_wd == vp || rfp->fp_rd == vp))
- return(EBUSY);
- }
- }
- }
-
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = string;
- lookup_req.flags = LAST_DIR;
-
- /* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- /* Fill in request fields. */
- req.fs_e = res.fs_e;
- req.d_inode_nr = res.inode_nr;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
- req.lastc = string;
/* Issue request */
- return (call_nr == UNLINK) ? req_unlink(&req) : req_rmdir(&req);
+ r= ((call_nr == UNLINK) ? req_unlink : req_rmdir)(vp->v_fs_e,
+ vp->v_inode_nr, user_fullpath);
+
+ put_vnode(vp);
+
+ return r;
}
PUBLIC int do_rename()
{
/* Perform the rename(name1, name2) system call. */
+ int r;
int old_dir_inode;
int old_fs_e;
int new_dir_inode;
int new_fs_e;
- char old_name[NAME_MAX];
- char new_name[NAME_MAX];
- struct vnode *vp;
- struct fproc *rfp;
- struct rename_req req;
- struct lookup_req lookup_req;
- struct node_details res;
- int r;
+ size_t len;
+ struct vnode *vp_od, *vp_nd;
+ char old_name[PATH_MAX+1];
/* 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);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = old_name;
- lookup_req.flags = LAST_DIR;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_od)) != OK) return r;
+
+ r= forbidden(vp_od, W_BIT|X_BIT, 0 /*!use_realuid*/);
+ if (r != OK)
+ {
+ put_vnode(vp_od);
+ return r;
+ }
- /* Remeber inode number and FS endpoint */
- old_fs_e = res.fs_e;
- req.old_dir = res.inode_nr;
+ /* Remeber FS endpoint */
+ old_fs_e = vp_od->v_fs_e;
+
+ /* Save the last component of the old name */
+ len= strlen(user_fullpath);
+ if (len >= sizeof(old_name))
+ {
+ put_vnode(vp_od);
+ return ENAMETOOLONG;
+ }
+ memcpy(old_name, user_fullpath, len+1);
/* See if 'name2' (new name) exists. Get dir inode */
- if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) r = err_code;
+ if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
+ {
+ put_vnode(vp_od);
+ return err_code;
+ }
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH_OPAQUE;
-
/* Request lookup */
- r = lookup(&lookup_req, &res);
-
- /* If a directory file has to be removed the following conditions have to met:
- * - The directory must not be the root of a mounted file system
- * - The directory must not be anybody's root/working directory
- */
- if (r == OK && ((res.fmode & I_TYPE) == I_DIRECTORY)) {
- /* Can't remove a root directory */
- if (res.inode_nr == ROOT_INODE) return EBUSY;
-
- /* Can't remove anybody's working directory */
- if ((vp = find_vnode(res.fs_e, res.inode_nr)) !=
- NIL_VNODE) {
- /* Check directories */
- for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS];
- rfp++) {
- if (rfp->fp_pid != PID_FREE &&
- (rfp->fp_wd == vp || rfp->fp_rd == vp))
- return(EBUSY);
- }
- }
+ r = lookup_lastdir(0 /*!use_realuid*/, &vp_nd);
+ if (r != OK)
+ {
+ put_vnode(vp_od);
+ return r;
+ }
+
+ r= forbidden(vp_nd, W_BIT|X_BIT, 0 /*!use_realuid*/);
+ if (r != OK)
+ {
+ put_vnode(vp_od);
+ put_vnode(vp_nd);
+ return r;
}
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = new_name;
- lookup_req.flags = LAST_DIR;
-
- /* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
- /* Remeber inode number and FS endpoint */
- new_fs_e = res.fs_e;
- req.new_dir = res.inode_nr;
+ /* Remeber FS endpoint */
+ new_fs_e = vp_nd->v_fs_e;
/* Both parent directories must be on the same device. */
- if (old_fs_e != new_fs_e) return EXDEV;
-
- /* Send actual rename request */
- req.fs_e = old_fs_e;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
- req.old_name = &old_name[0];
- req.new_name = &new_name[0];
-
+ if (old_fs_e != new_fs_e)
+ {
+ put_vnode(vp_od);
+ put_vnode(vp_nd);
+ return EXDEV;
+ }
+
/* Issue request */
- return req_rename(&req);
+ r= req_rename(old_fs_e, vp_od->v_inode_nr, old_name, vp_nd->v_inode_nr,
+ user_fullpath);
+ put_vnode(vp_od);
+ put_vnode(vp_nd);
+ return r;
}
* work.
*/
struct vnode *vp;
- struct trunc_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
printf("in do_truncate\n");
if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code;
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- /* Check whether the file is in use or not */
- vp = find_vnode(res.fs_e, res.inode_nr);
-
- /* Fill in request message fields.*/
- req.fs_e = res.fs_e;
- req.length = m_in.m2_l1;
- req.inode_nr = res.inode_nr;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
+ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
- /* Issue request */
- if ((r = req_trunc(&req)) != OK) return r;
-
- /* Change vnode's size if found */
- if (vp != NIL_VNODE)
- vp->v_size = m_in.m2_l1;
-
- return OK;
+ r= truncate_vn(vp, m_in.m2_l1);
+
+ put_vnode(vp);
+
+ return r;
}
off_t newsize;
{
int r;
- struct ftrunc_req req;
if ( (vp->v_mode & I_TYPE) != I_REGULAR &&
(vp->v_mode & I_TYPE) != I_NAMED_PIPE) {
return EINVAL;
}
- /* Fill in FS request */
- req.fs_e = vp->v_fs_e;
- req.inode_nr = vp->v_inode_nr;
- req.start = newsize;
- req.end = 0; /* Indicate trunc in fs_freesp_trunc */
-
/* Issue request */
- if ((r = req_ftrunc(&req)) != OK) return r;
+ if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) != OK) return r;
vp->v_size = newsize;
return OK;
PUBLIC int do_slink()
{
/* Perform the symlink(name1, name2) system call. */
- char string[NAME_MAX]; /* last component of the new dir's path name */
- struct slink_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
+ struct vnode *vp;
+ char string[NAME_MAX]; /* last component of the new dir's path name */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
return(err_code);
if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE)
return(ENAMETOOLONG);
-
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = string;
- lookup_req.flags = LAST_DIR;
-
+
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- /* Fill in request message */
- req.fs_e = res.fs_e;
- req.parent_dir = res.inode_nr;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
- req.lastc = string;
- req.who_e = who_e;
- req.path_addr = m_in.name1;
- req.path_length = m_in.name1_length - 1;
+ if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK)
+ {
+ printf("vfs:do_slink: lookup_lastdir failed with %d\n", r);
+ return r;
+ }
+
+ printf("vfs:do_slink: got dir inode %d on dev 0x%x, fs %d\n",
+ vp->v_inode_nr, vp->v_dev, vp->v_fs_e);
+
+ r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
+ if (r != OK)
+ {
+ put_vnode(vp);
+ return r;
+ }
/* Issue request */
- return req_slink(&req);
+ r= req_slink(vp->v_fs_e, vp->v_inode_nr, user_fullpath, who_e, m_in.name1,
+ m_in.name1_length - 1, fp->fp_effuid, fp->fp_effgid);
+
+ put_vnode(vp);
+
+ return r;
}
/*===========================================================================*
PUBLIC int do_rdlink()
{
/* Perform the readlink(name, buf) system call. */
- int copylen;
- struct rdlink_req req;
- struct lookup_req lookup_req;
- struct node_details res;
- int r;
+ int r, copylen;
+ struct vnode *vp;
copylen = m_in.m1_i2;
if(copylen < 0) return EINVAL;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH_OPAQUE;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- /* Fill in request message */
- req.fs_e = res.fs_e;
- req.inode_nr = res.inode_nr;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
- req.who_e = who_e;
- req.path_buffer = m_in.name2;
- req.max_length = copylen;
+ r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp);
+ if (r != OK) return r;
/* Issue request */
- return req_rdlink(&req);
+ r= req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, (vir_bytes)m_in.name2,
+ copylen);
+
+ put_vnode(vp);
+
+ return r;
}
if (who_e == PM_PROC_NR && call_nr != PROC_EVENT)
printf("FS: strange, got message %d from PM\n", call_nr);
+#if 0
+ printf("VFS: got call %d from %d\n", call_nr, who_e);
+#endif
+
/* Check for special control messages first. */
if ((call_nr & NOTIFY_MESSAGE)) {
if (call_nr == PROC_EVENT)
if (error != SUSPEND) reply(who_e, error);
break;
+ case MAPDRIVER:
+ error= do_mapdriver();
+ if (error != SUSPEND) reply(who_e, error);
+ break;
+
default:
/* Call the internal function that does the work. */
if (call_nr < 0 || call_nr >= NCALLS) {
/* Normally wait for new input. However, if 'reviving' is
* nonzero, a suspended process must be awakened.
*/
+ int r, found_one, fd_nr;
+ struct filp *f;
register struct fproc *rp;
- if (reviving != 0) {
+ while (reviving != 0) {
+ found_one= FALSE;
+
/* Revive a suspended process. */
for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++)
if (rp->fp_pid != PID_FREE && rp->fp_revived == REVIVING) {
+ found_one= TRUE;
who_p = (int)(rp - fproc);
who_e = rp->fp_endpoint;
call_nr = rp->fp_fd & BYTE;
+
m_in.fd = (rp->fp_fd >>8) & BYTE;
m_in.buffer = rp->fp_buffer;
m_in.nbytes = rp->fp_nbytes;
* If it is, it'll 'leak' grants.
*/
assert(!GRANT_VALID(rp->fp_grant));
+
+ if (rp->fp_task == -XPIPE)
+ {
+ fp= rp;
+ fd_nr= (rp->fp_fd >> 8);
+ f= get_filp(fd_nr);
+ assert(f != NULL);
+ r= rw_pipe((call_nr == READ) ? READING :
+ WRITING, who_e, fd_nr, f,
+ rp->fp_buffer, rp->fp_nbytes);
+ if (r != SUSPEND)
+ reply(who_e, r);
+ continue;
+ }
+
return;
}
- panic(__FILE__,"get_work couldn't revive anyone", NO_NUM);
+ if (!found_one)
+ panic(__FILE__,"get_work couldn't revive anyone", NO_NUM);
}
for(;;) {
{
/* Send a reply to a user process. If the send fails, just ignore it. */
int s;
+
+ if (call_nr == SYMLINK)
+ printf("vfs:reply: replying %d for call %d\n", result, call_nr);
+
m_out.reply_type = result;
s = send(whom, &m_out);
if (s != OK) printf("VFS: couldn't send reply %d to %d: %d\n",
PRIVATE void fs_init()
{
/* Initialize global variables, tables, etc. */
- register struct inode *rip;
+ int s;
register struct fproc *rfp;
+ struct vmnt *vmp;
+ struct vnode *root_vp;
message mess;
- int s;
/* Clear endpoint field */
last_login_fs_e = NONE;
init_root(); /* init root device and load super block */
init_select(); /* init select() structures */
+
+ vmp = &vmnt[0]; /* Should be the root filesystem */
+ if (vmp->m_dev == NO_DEV)
+ panic(__FILE__, "vfs:fs_init: no root filesystem", NO_NUM);
+ root_vp= vmp->m_root_node;
+
/* The root device can now be accessed; set process directories. */
for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
FD_ZERO(&(rfp->fp_filp_inuse));
if (rfp->fp_pid != PID_FREE) {
- rfp->fp_rd = get_vnode_x(ROOT_FS_E, ROOT_INODE);
- rfp->fp_wd = get_vnode_x(ROOT_FS_E, ROOT_INODE);
+ dup_vnode(root_vp);
+ rfp->fp_rd = root_vp;
+ dup_vnode(root_vp);
+ rfp->fp_wd = root_vp;
} else rfp->fp_endpoint = NONE;
}
*===========================================================================*/
PRIVATE void init_root()
{
+ int r = OK;
struct vmnt *vmp;
struct vnode *root_node;
struct dmap *dp;
+ char *label;
message m;
- int r = OK;
- struct readsuper_req sreq;
- struct readsuper_res sres;
+ struct node_details resX;
/* Open the root device. */
root_dev = DEV_IMGRD;
panic(__FILE__,"No driver for root device", r);
}
- /* Open the device the file system lives on. */
- if ((r = dev_open(root_dev, ROOT_FS_E, (R_BIT|W_BIT))) != OK)
- panic(__FILE__,"Cannot open root device", r);
-
+ label= dp->dmap_label;
+ if (strlen(label) == 0)
+ {
+ panic(__FILE__, "vfs:init_root: no label for major", root_dev >> MAJOR);
+ }
- /* Request for reading superblock and root inode */
- sreq.fs_e = ROOT_FS_E;
- sreq.readonly = 0;
- sreq.boottime = boottime;
- sreq.driver_e = dp->dmap_driver;
- sreq.dev = root_dev;
- sreq.slink_storage = user_fullpath;
- sreq.isroot = 1;
-
/* Issue request */
- if ((r = req_readsuper(&sreq, &sres)) != OK) {
- dev_close(root_dev);
+ r = req_readsuper(ROOT_FS_E, label, root_dev, 0 /*!readonly*/,
+ 1 /*isroot*/, &resX);
+ if (r != OK) {
panic(__FILE__,"Cannot read superblock from root", r);
}
/* Fill in root node's fields */
- root_node->v_fs_e = sres.fs_e;
- root_node->v_inode_nr = sres.inode_nr;
- root_node->v_mode = sres.fmode;
- root_node->v_size = sres.fsize;
+ root_node->v_fs_e = resX.fs_e;
+ root_node->v_inode_nr = resX.inode_nr;
+ root_node->v_mode = resX.fmode;
+ root_node->v_size = resX.fsize;
root_node->v_sdev = NO_DEV;
- root_node->v_fs_count = 0; /* Is this correct? */
+ root_node->v_fs_count = 1;
root_node->v_ref_count = 1;
/* Fill in max file size and blocksize for the vmnt */
- vmp->m_fs_e = sres.fs_e;
+ vmp->m_fs_e = resX.fs_e;
vmp->m_dev = root_dev;
- vmp->m_block_size = sres.blocksize;
- vmp->m_max_file_size = sres.maxsize;
vmp->m_driver_e = dp->dmap_driver;
vmp->m_flags = 0;
call= m.m_type;
switch(call)
{
- case PM_STIME:
- boottime = m.PM_STIME_TIME;
-
- /* Send new time for all FS processes */
- for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
- if (vmp->m_fs_e)
- req_stime(vmp->m_fs_e, boottime);
- }
- /* No need to report status to PM */
- break;
case PM_SETSID:
pm_setsid(m.PM_SETSID_PROC);
long cloexec_mask; /* bit map for the FD_CLOEXEC flag */
long clo_value; /* FD_CLOEXEC flag in proper position */
struct filp *dummy;
- struct ftrunc_req req;
/* Is the file descriptor valid? */
if ((f = get_filp(m_in.fd)) == NIL_FILP) {
end = 0;
}
- /* Fill in FS request */
- req.fs_e = f->filp_vno->v_fs_e;
- req.inode_nr = f->filp_vno->v_inode_nr;
- req.start = start;
- req.end = end;
-
/* Issue request */
- return req_ftrunc(&req);
+ return req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,
+ start, end);
}
default:
{
/* Perform the mount(name, mfile, rd_only) system call. */
int rdir, mdir; /* TRUE iff {root|mount} file is dir */
- int i, r, found;
+ int i, r, found, isroot, replace_root;
struct fproc *tfp;
struct dmap *dp;
dev_t dev;
message m;
- struct vnode *vp, *root_node, *mounted_on, *bspec;
+ struct vnode *vp, *root_node, *Xmounted_on, *bspec;
struct vmnt *vmp, *vmp2;
- struct mountpoint_req mreq;
- struct node_details res;
- struct readsuper_req sreq;
- struct readsuper_res sres;
- struct lookup_req lookup_req;
- node_req_t node_req;
+ char *label;
+ struct node_details resX;
/* Only the super-user may do MOUNT. */
if (!super_user) return(EPERM);
/* If 'name' is not for a block special file, return error. */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- /* Get free vnode for the mountpoint */
- if ((mounted_on = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
- printf("VFSmount: not free vnode available\n");
- return ENFILE;
- }
-
- /* Mark it as used so that we won't find the same for the root_node */
- mounted_on->v_ref_count = 1;
-
/* Convert name to device number */
if ((dev = name_to_dev()) == NO_DEV) return(err_code);
/* Partition was/is already mounted */
if (found) {
- /* It is possible that we have an old root lying around that
- * needs to be remounted. */
- if (vmp->m_mounted_on != vmp->m_root_node ||
- vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) {
- /* Normally, m_mounted_on refers to the mount point. For a root
- * filesystem, m_mounted_on is equal to the root vnode. We assume
- * that the root of FS is always the real root. If the two
- * vnodes are different or if the root of FS is equal two the
- * root of the filesystem we found, we found a filesystem that
- * is in use. */
- mounted_on->v_ref_count = 0;
- return EBUSY; /* already mounted */
- }
-
- if (root_dev == vmp->m_dev)
- panic("fs", "inconsistency remounting old root", NO_NUM);
-
- /* 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);
- }
-
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
- /* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- /* Fill in request message fields.*/
- mreq.fs_e = res.fs_e;
- mreq.inode_nr = res.inode_nr;
- mreq.uid = fp->fp_effuid;
- mreq.gid = fp->fp_effgid;
-
- /* Issue request */
- if ((r = req_mountpoint(&mreq, &res)) != OK) return r;
-
- mounted_on->v_fs_e = res.fs_e;
- mounted_on->v_inode_nr = res.inode_nr;
- mounted_on->v_mode = res.fmode;
- mounted_on->v_size = res.fsize;
- mounted_on->v_sdev = NO_DEV;
- mounted_on->v_fs_count = 1;
- mounted_on->v_ref_count = 1;
-
- /* Find the vmnt for the vnode */
- if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT)
- printf("VFS: vmnt not found by mount()\n");
- mounted_on->v_vmnt = vmp2;
- mounted_on->v_dev = vmp2->m_dev;
-
- /* Get the root inode of the mounted file system. */
- root_node = vmp->m_root_node;
-
- /* File types may not conflict. */
- if (r == OK) {
- mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY);
- /* TRUE iff dir */
- rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
- if (!mdir && rdir) r = EISDIR;
- }
-
- /* If error, return the mount point. */
- if (r != OK) {
- put_vnode(mounted_on);
+ /* It is possible that we have an old root lying around that
+ * needs to be remounted. */
+ if (vmp->m_mounted_on != vmp->m_root_node ||
+ vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) {
+ /* Normally, m_mounted_on refers to the mount point. For a
+ * root filesystem, m_mounted_on is equal to the root vnode.
+ * We assume that the root of FS is always the real root. If
+ * the two vnodes are different or if the root of FS is equal
+ * to the root of the filesystem we found, we found a
+ * filesystem that is in use.
+ */
+ return EBUSY; /* already mounted */
+ }
+
+ if (root_dev == vmp->m_dev)
+ panic("fs", "inconsistency remounting old root", NO_NUM);
+
+ /* 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);
+ }
+
+ /* Request lookup */
+ r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &Xmounted_on);
+ if (r != OK) return r;
+
+ if (vp->v_ref_count != 1)
+ {
+ put_vnode(vp);
+ printf("vfs:mount_fs: mount point is busy\n");
+ return EBUSY;
+ }
+
+ /* Issue mountpoint request */
+ r = req_mountpoint(Xmounted_on->v_fs_e, Xmounted_on->v_inode_nr);
+ if (r != OK)
+ {
+ put_vnode(Xmounted_on);
+ printf("vfs:mount_fs: req_mountpoint_s failed with %d\n", r);
+ return r;
+ }
+
+ /* Get the root inode of the mounted file system. */
+ root_node = vmp->m_root_node;
+
+ /* File types may not conflict. */
+ if (r == OK) {
+ mdir = ((Xmounted_on->v_mode & I_TYPE) == I_DIRECTORY);
+ /* TRUE iff dir */
+ rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
+ if (!mdir && rdir) r = EISDIR;
+ }
+
+ /* If error, return the mount point. */
+ if (r != OK) {
+ put_vnode(Xmounted_on);
+
+ return(r);
+ }
+
+ /* Nothing else can go wrong. Perform the mount. */
+ put_vnode(vmp->m_mounted_on);
+ vmp->m_mounted_on = Xmounted_on;
+ vmp->m_flags = m_in.rd_only;
+ allow_newroot = 0; /* The root is now fixed */
+
+ return(OK);
+ }
- return(r);
- }
+ /* Fetch the name of the mountpoint */
+ if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+ return(err_code);
+ }
- /* Nothing else can go wrong. Perform the mount. */
- put_vnode(vmp->m_mounted_on);
- vmp->m_mounted_on = mounted_on;
- vmp->m_flags = m_in.rd_only;
- allow_newroot = 0; /* The root is now fixed */
+ isroot= (strcmp(user_fullpath, "/") == 0);
+ replace_root= (isroot && allow_newroot);
- return(OK);
+ if (!replace_root)
+ {
+ /* Get mount point and inform the FS it is on. */
+#if 0
+ printf("vfs:mount_fs: mount point at '%s'\n", user_fullpath);
+#endif
+
+ r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &Xmounted_on);
+ if (r != OK)
+ return r;
+
+ /* Issue mountpoint request */
+ r = req_mountpoint(Xmounted_on->v_fs_e, Xmounted_on->v_inode_nr);
+ if (r != OK) {
+ put_vnode(Xmounted_on);
+ printf("vfs:mount_fs: req_mountpoint_s failed with %d\n", r);
+ return r;
+ }
}
/* We'll need a vnode for the root inode, check whether there is one */
return ENFILE;
}
- /* Set it back to zero so that if st goes wrong it won't be kept in use */
- mounted_on->v_ref_count = 0;
-
- /* Fetch the name of the mountpoint */
- if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
- return(err_code);
- }
/* Get driver process' endpoint */
dp = &dmap[(dev >> MAJOR) & BYTE];
printf("VFSmount: no driver for dev %x\n", dev);
return(EINVAL);
}
-
- /* Open the device the file system lives on. */
- if (dev_open(dev, fs_e, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK) {
- return(EINVAL);
+ label= dp->dmap_label;
+ if (strlen(label) == 0)
+ {
+ panic(__FILE__, "vfs:mount_fs: no label for major", dev >> MAJOR);
}
+#if 0
+ printf("vfs:mount_fs: label = '%s'\n", label);
+#endif
- /* Request for reading superblock and root inode */
- sreq.fs_e = fs_e;
- sreq.readonly = m_in.rd_only;
- sreq.boottime = boottime;
- sreq.driver_e = dp->dmap_driver;
- sreq.dev = dev;
- sreq.slink_storage = user_fullpath;
-
- if (!strcmp(user_fullpath, "/")) sreq.isroot = 1;
- else sreq.isroot = 0;
-
/* Issue request */
- if ((r = req_readsuper(&sreq, &sres)) != OK) {
- dev_close(dev);
+ r = req_readsuper(fs_e, label, dev, m_in.rd_only, isroot, &resX);
+ if (r != OK) {
return r;
}
- /* Fill in request message fields.*/
- node_req.fs_e = sres.fs_e;
- node_req.inode_nr = sres.inode_nr;
-
- /* Issue request */
- if ((r = req_getnode(&node_req, &res)) != OK)
- {
- printf("mount: req_getnode failed: %d\n", r);
- dev_close(dev);
- return r;
- }
-
/* Fill in root node's fields */
- root_node->v_fs_e = res.fs_e;
- root_node->v_inode_nr = res.inode_nr;
- root_node->v_mode = res.fmode;
- root_node->v_uid = res.uid;
- root_node->v_gid = res.gid;
- root_node->v_size = res.fsize;
+ root_node->v_fs_e = resX.fs_e;
+ root_node->v_inode_nr = resX.inode_nr;
+ root_node->v_mode = resX.fmode;
+ root_node->v_uid = resX.uid;
+ root_node->v_gid = resX.gid;
+ root_node->v_size = resX.fsize;
root_node->v_sdev = NO_DEV;
- root_node->v_fs_count = 2;
+ root_node->v_fs_count = 1;
root_node->v_ref_count = 1;
/* Fill in max file size and blocksize for the vmnt */
- vmp->m_fs_e = sres.fs_e;
+ vmp->m_fs_e = resX.fs_e;
vmp->m_dev = dev;
- vmp->m_block_size = sres.blocksize;
- vmp->m_max_file_size = sres.maxsize;
vmp->m_flags = m_in.rd_only;
vmp->m_driver_e = dp->dmap_driver;
root_node->v_vmnt = vmp;
root_node->v_dev = vmp->m_dev;
- if (strcmp(user_fullpath, "/") == 0 && allow_newroot) {
+ if (replace_root) {
printf("Replacing root\n");
/* Superblock and root node already read.
return(OK);
}
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
- /* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) {
- put_vnode(root_node);
- return r;
- }
-
- /* Fill in request fields.*/
- mreq.fs_e = res.fs_e;
- mreq.inode_nr = res.inode_nr;
- mreq.uid = fp->fp_effuid;
- mreq.gid = fp->fp_effgid;
-
- /* Issue request */
- if ((r = req_mountpoint(&mreq, &res)) != OK) {
- put_vnode(root_node);
- return r;
- }
-
- /* Fill in vnode's fields */
- mounted_on->v_fs_e = res.fs_e;
- mounted_on->v_inode_nr = res.inode_nr;
- mounted_on->v_mode = res.fmode;
- mounted_on->v_size = res.fsize;
- mounted_on->v_sdev = NO_DEV;
- mounted_on->v_fs_count = 1;
- mounted_on->v_ref_count = 1;
-
- /* Find the vmnt for the vnode */
- if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT)
- printf("VFS: vmnt not found by mount()");
- mounted_on->v_vmnt = vmp2;
- mounted_on->v_dev = vmp2->m_dev;
-
/* File types may not conflict. */
if (r == OK) {
- mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir */
+ mdir = ((Xmounted_on->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir */
rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
if (!mdir && rdir) r = EISDIR;
}
/* If error, return the super block and both inodes; release the vmnt. */
if (r != OK) {
- put_vnode(mounted_on);
+ put_vnode(Xmounted_on);
put_vnode(root_node);
vmp->m_dev = NO_DEV;
- dev_close(dev);
return(r);
}
/* Nothing else can go wrong. Perform the mount. */
- vmp->m_mounted_on = mounted_on;
+ vmp->m_mounted_on = Xmounted_on;
vmp->m_root_node = root_node;
/* The root is now fixed */
panic(__FILE__, "unmount: strange fs endpoint", vmp->m_fs_e);
if ((r = req_unmount(vmp->m_fs_e)) != OK) return r;
- /* Close the device the file system lives on. */
- dev_close(dev);
-
/* Is there a block special file that was handled by that partition? */
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL &&
printf("VFSunmount: moving block spec %d to root FS\n", dev);
vp->v_bfs_e = ROOT_FS_E;
- vp->v_blocksize = _MIN_BLOCK_SIZE;
/* Send the driver endpoint (even if it is known already...) */
if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver))
{
/* Convert the block special file 'path' to a device number. If 'path'
* is not a block special file, return error code in 'err_code'. */
- struct lookup_req lookup_req;
- struct node_details res;
int r;
+ dev_t dev;
+ struct vnode *vp;
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
- if ((res.fmode & I_TYPE) != I_BLOCK_SPECIAL) {
+ if ((vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) {
err_code = ENOTBLK;
- return NO_DEV;
+ dev= NO_DEV;
}
+ else
+ dev= vp->v_sdev;
+
+ put_vnode(vp);
- return res.dev;
+ return dev;
}
FORWARD _PROTOTYPE( int x_open, (int bits, int oflags, int omode,
char *lastc, struct vnode **vpp) );
FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) );
+FORWARD _PROTOTYPE( int create_open, (_mnx_Mode_t omode,
+ struct vnode **vpp, int *created) );
+FORWARD _PROTOTYPE( int y_open, (struct vnode *vp, _mnx_Mode_t bits,
+ int oflags));
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
/*===========================================================================*
PRIVATE int common_open(register int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */
- int r, b, found;
- dev_t dev;
+ int b, m, r, created, found;
mode_t bits;
- off_t pos;
- struct dmap *dp;
struct filp *fil_ptr, *filp2;
- struct vnode *vp, *vp2;
+ struct vnode *vp;
struct vmnt *vmp;
- char Xlastc[NAME_MAX];
- char *pathrem;
- int m;
-
- /* Request and response structures */
- struct lookup_req Xlookup_req;
- struct open_req Xreq;
+ struct dmap *dp;
/* Remap the bottom two bits of oflags. */
m = oflags & O_ACCMODE;
omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
}
- vp= NULL;
-
- /* Fill in lookup request fields */
- Xlookup_req.path = user_fullpath;
- Xlookup_req.lastc = Xlastc;
- Xlookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR :
- LAST_DIR_EATSYM) : EAT_PATH;
- Xlookup_req.flags = ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) ?
- LAST_DIR : EAT_PATH;
- Xlastc[0]= '\0'; /* Clear lastc, it will be filled with the part of the
- * path that cannot be resolved.
- */
-
- /* Request lookup */
- r = Xlookup_vp(&Xlookup_req, &vp, &pathrem);
-
- if (r == OK && ((oflags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL)))
- {
- /* Clear lastc */
- Xlastc[0]= '\0';
- }
-
- /* Hide ENOENT for O_CREAT */
- if (r == ENOENT && (oflags & O_CREAT))
+ if (oflags & O_CREAT)
+ r= create_open(omode, &vp, &created);
+ else
{
- if (pathrem == NULL)
- panic(__FILE__, "no pathrem", NO_NUM);
-
- /* If any path remains, but no '/', O_CREAT can continue.
- * If no path remains, a null filename was provided so ENOENT
- * remains.
- */
- if(*pathrem) {
- if (strchr(pathrem, '/') == 0)
- r= OK;
#if 0
- else
- {
- printf("common_open: / in pathrem\n");
- }
+ printf("vfs:common_open: path '%s'\n", user_fullpath);
#endif
- }
+ created= FALSE;
+ r= lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
}
-
if (r != OK)
- {
- if (vp)
- {
- put_vnode(vp);
- vp= NULL;
- }
return r;
- }
-
- if (!vp) panic(__FILE__, "common_open: no vp", NO_NUM);
- r= x_open(bits, oflags, omode, Xlastc, &vp);
- if (r != OK)
+ if (!created)
{
- if (vp)
+ r= y_open(vp, bits, oflags);
+ if (r != OK)
{
put_vnode(vp);
- vp= NULL;
+ return r;
}
- return r;
}
-#if 0
- /* Lookup was okay, fill in request fields for
- * the actual open request. */
- req.inode_nr = res.inode_nr;
- req.fs_e = res.fs_e;
- req.oflags = oflags;
- req.omode = omode;
- req.lastc = lastc;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
-
- /* Issue request */
- if ((r = req_open(&req, &res)) != OK) return r;
-
- /* Check whether the vnode is already in use */
- if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
- vp = vp2;
- vp->v_size = res.fsize; /* In case of trunc... */
- vp->v_ref_count++;
- vp->v_fs_count++;
- }
- /* Otherwise use the free one */
- else {
- vp->v_fs_e = res.fs_e;
- if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
- printf("VFS: vmnt not found by open()");
-
- vp->v_dev = vmp->m_dev;
- vp->v_inode_nr = res.inode_nr;
- vp->v_mode = res.fmode;
- vp->v_uid = res.uid;
- vp->v_gid = res.gid;
- vp->v_size = res.fsize;
- vp->v_sdev = res.dev;
- vp->v_fs_count = 1;
- vp->v_ref_count = 1;
- vp->v_vmnt = vmp;
- vp->v_index = res.inode_index;
- }
-#endif
-
/* Claim the file descriptor and filp slot and fill them in. */
fp->fp_filp[m_in.fd] = fil_ptr;
FD_SET(m_in.fd, &fp->fp_filp_inuse);
/* Who is going to be responsible for this device? */
if (found) {
vp->v_bfs_e = vmp->m_fs_e;
- vp->v_blocksize - vmp->m_block_size;
}
else { /* To be handled in the root FS proc if not mounted */
vp->v_bfs_e = ROOT_FS_E;
- vp->v_blocksize = _MIN_BLOCK_SIZE;
}
/* Get the driver endpoint of the block spec device */
return(m_in.fd);
}
+
+/*===========================================================================*
+ * create_open *
+ *===========================================================================*/
+PRIVATE int create_open(omode, vpp, created)
+mode_t omode;
+struct vnode **vpp;
+int *created;
+{
+ int i, r, r1;
+ size_t len;
+ struct vnode *vp, *dir_vp, *new_vp, *start_vp;
+
+ struct node_details res;
+ char lastc[PATH_MAX+1];
+
+ start_vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
+ dup_vnode(start_vp);
+
+ for (i= 0; i<SYMLOOP_MAX; i++)
+ {
+#if 0
+ printf("vfs:create_open: path #%d '%s'\n", i+1, user_fullpath);
+#endif
+ r= lookup_lastdir_rel(start_vp, 0 /*!use_realuid*/, &dir_vp);
+ put_vnode(start_vp);
+ if (r != OK)
+ return r;
+
+ /* Save the last component of the path */
+ len= strlen(user_fullpath)+1;
+ if (len > sizeof(lastc))
+ {
+ put_vnode(dir_vp);
+ return ENAMETOOLONG;
+ }
+ memcpy(lastc, user_fullpath, len);
+
+ /* Get a free vnode */
+ new_vp = get_free_vnode(__FILE__, __LINE__);
+ if (new_vp == NIL_VNODE) {
+ put_vnode(dir_vp);
+ printf("vfs:create_open: no free vnode available\n");
+ return EINVAL;
+ }
+
+ r= forbidden(dir_vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
+ if (r == OK)
+ {
+ /* Try to create the file */
+ r= req_create(dir_vp->v_fs_e, dir_vp->v_inode_nr,
+ omode, fp->fp_effuid, fp->fp_effgid, lastc,
+ &res);
+ }
+
+ if (r != EEXIST && r != EACCES)
+ {
+ put_vnode(dir_vp);
+
+ if (r != OK)
+ return r;
+
+ /* Check whether vnode is already in use or not */
+ vp = find_vnode(res.fs_e, res.inode_nr);
+ if (vp != NIL_VNODE) {
+ vp->v_ref_count++;
+ vp->v_fs_count++;
+ }
+ else
+ {
+ vp= new_vp;
+
+ /* Fill in the free vnode's fields */
+ vp->v_fs_e = res.fs_e;
+ vp->v_inode_nr = res.inode_nr;
+ vp->v_mode = res.fmode;
+ vp->v_size = res.fsize;
+ vp->v_uid = res.uid;
+ vp->v_gid = res.gid;
+ vp->v_sdev = res.dev;
+
+ vp->v_vmnt = dir_vp->v_vmnt;
+ vp->v_dev = vp->v_vmnt->m_dev;
+ vp->v_fs_count = 1;
+ vp->v_ref_count = 1;
+ }
+
+ *vpp= vp;
+ *created= TRUE;
+
+ return OK;
+
+ }
+
+ /* Try a regular lookup */
+ memcpy(user_fullpath, lastc, len);
+ r1= lookup_rel_vp(dir_vp, 0 /*flags*/, 0 /*!use_realuid*/, &vp);
+ if (r1 != ENOENT)
+ {
+ put_vnode(dir_vp);
+ if (r1 == OK)
+ {
+ *vpp= vp;
+ *created= FALSE;
+ }
+
+ return r1;
+ }
+ if (r == EACCES)
+ {
+ /* We cannot create a new file and the file does not
+ * already exist.
+ */
+ put_vnode(dir_vp);
+ return r;
+ }
+
+ /* The create failed with EEXIST and the regular lookup
+ * failed with ENOENT. We have to see whether the object
+ * we try to access actually exists, but is a symlink that
+ * cannot be resolved. If the symlink exists, we start
+ * with the contents of the symlink.
+ */
+ memcpy(user_fullpath, lastc, len);
+ r= lookup_rel_vp(dir_vp, PATH_RET_SYMLINK, 0 /*!use_realuid*/,
+ &vp);
+ if (r != OK)
+ {
+ put_vnode(dir_vp);
+ return r;
+ }
+
+ if (!S_ISLNK(vp->v_mode))
+ {
+ /* Strange, we got an object, but it is not a symlink.
+ * Well, just return the object.
+ */
+ put_vnode(dir_vp);
+ *vpp= vp;
+ *created= FALSE;
+ return OK;
+ }
+
+ /* Get the contents of the link */
+ len= sizeof(user_fullpath);
+ r= req_rdlink(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR,
+ (vir_bytes)user_fullpath, len-1);
+ put_vnode(vp);
+ if (r < 0)
+ {
+ printf("vfs:create_open: req_rdlink failed with %d\n",
+ r);
+ put_vnode(dir_vp);
+ return r;
+ }
+ if (r >= len)
+ {
+ printf(
+ "vfs:create_open: got bad length %d from req_rdlink\n",
+ r);
+ r= len-1;
+ }
+ user_fullpath[r]= '\0';
+
+ printf("got link target '%s'\n", user_fullpath);
+ if (user_fullpath[0] == '/')
+ {
+ put_vnode(dir_vp);
+ start_vp= fp->fp_rd;
+ dup_vnode(start_vp);
+ }
+ else
+ start_vp= dir_vp;
+ }
+
+ put_vnode(start_vp);
+ return ELOOP;
+}
+
+
/*===========================================================================*
* x_open *
*===========================================================================*/
vp->v_sdev = res.dev;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
- panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM);
+ panic(__FILE__, "x_open: vmnt not found", NO_NUM);
vp->v_vmnt = vmp;
vp->v_dev = vmp->m_dev;
return OK;
/* Check protections. */
- if ((r = forbidden(vp, bits)) != OK)
+ if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK)
return r;
/* Opening reg. files directories and special files differ. */
case I_REGULAR:
/* Truncate regular file if O_TRUNC. */
if (oflags & O_TRUNC) {
- if ((r = forbidden(vp, W_BIT)) !=OK) break;
+ if ((r = forbidden(vp, W_BIT, 0 /*!use_realuid*/)) !=OK) break;
truncate_vn(vp, 0);
}
break;
}
+/*===========================================================================*
+ * y_open *
+ *===========================================================================*/
+PRIVATE int y_open(vp, bits, oflags /*, omode, lastc, vpp */)
+struct vnode *vp;
+mode_t bits;
+int oflags;
+
+#if 0
+mode_t omode;
+char *lastc;
+struct vnode **vpp;
+#endif
+{
+ int r;
+#if 0
+ int r, b, exist = TRUE;
+ struct vnode *vp, *dvp, *tmp_vp;
+ struct vmnt *vmp;
+ struct node_details res;
+#endif
+
+ /* Check protections. */
+ if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK)
+ return r;
+
+ /* Opening reg. files directories and special files differ. */
+ switch (vp->v_mode & I_TYPE) {
+ case I_REGULAR:
+ /* Truncate regular file if O_TRUNC. */
+ if (oflags & O_TRUNC) {
+ if ((r = forbidden(vp, W_BIT, 0 /*!use_realuid*/)) !=OK) break;
+ truncate_vn(vp, 0);
+ }
+ break;
+
+ case I_DIRECTORY:
+ /* Directories may be read but not written. */
+ r = (bits & W_BIT ? EISDIR : OK);
+ break;
+
+ case I_CHAR_SPECIAL:
+ case I_BLOCK_SPECIAL:
+ if (vp->v_sdev == (dev_t)-1)
+ panic(__FILE__, "y_open: bad special", NO_NUM);
+ break;
+
+ case I_NAMED_PIPE:
+ if (vp->v_ref_count == 1)
+ {
+ if (vp->v_size != 0)
+ {
+ r= truncate_vn(vp, 0);
+ if (r != OK)
+ {
+ printf(
+ "x_open (fifo): truncate_vn failed: %d\n",
+ r);
+ }
+ }
+ }
+ break;
+ }
+
+ return(r);
+}
+
+
/*===========================================================================*
* pipe_open *
*===========================================================================*/
{
/* Perform the mknod(name, mode, addr) system call. */
register mode_t bits, mode_bits;
- char lastc[NAME_MAX]; /* last component of the path */
- struct mknod_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
+ struct vnode *vp;
/* Only the super_user may make nodes other than fifos. */
mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = lastc;
- lookup_req.flags = LAST_DIR;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- /* Lookup was okay, fill in request fields for the actual
- * mknod request. */
- req.fs_e = res.fs_e;
- req.inode_nr = res.inode_nr;
- req.rmode = bits;
- req.dev = m_in.mk_z0;
- req.lastc = lastc;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
-
+ if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK) return r;
+
+ r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
+ if (r != OK)
+ {
+ put_vnode(vp);
+ return r;
+ }
+
/* Issue request */
- return req_mknod(&req);
+ r= req_mknod(vp->v_fs_e, vp->v_inode_nr, user_fullpath,
+ fp->fp_effuid, fp->fp_effgid, bits, m_in.mk_z0);
+ put_vnode(vp);
+ return r;
}
{
/* Perform the mkdir(name, mode) system call. */
mode_t bits; /* mode bits for the new inode */
- char lastc[NAME_MAX];
- struct mkdir_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
+ struct vnode *vp;
/*printf("VFS: mkdir() START:");*/
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = lastc;
- lookup_req.flags = LAST_DIR;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK) return r;
+
+ r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
+ if (r != OK)
+ {
+ put_vnode(vp);
+ return r;
+ }
- /* Lookup was okay, fill in request message fields
- * for the actual mknod request. */
- req.fs_e = res.fs_e;
- req.d_inode_nr = res.inode_nr;
- req.rmode = bits;
- req.lastc = lastc;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
-
/* Issue request */
- return req_mkdir(&req);
+ r= req_mkdir(vp->v_fs_e, vp->v_inode_nr, user_fullpath,
+ fp->fp_effuid, fp->fp_effgid, bits);
+ put_vnode(vp);
+ return r;
}
int r;
long offset;
u64_t pos, newpos;
- struct node_req req;
/* Check to see if the file descriptor is valid. */
if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
return EINVAL;
if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
- /* Fill in request message */
- req.fs_e = rfilp->filp_vno->v_fs_e;
- req.inode_nr = rfilp->filp_vno->v_inode_nr;
-
- /* Issue request */
- if ((r = req_inhibread(&req)) != OK) return r;
+ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
+ if (r != OK) return r;
}
rfilp->filp_pos = newpos;
/* Perform the llseek(ls_fd, offset, whence) system call. */
register struct filp *rfilp;
u64_t pos, newpos;
- struct node_req req;
int r;
/* Check to see if the file descriptor is valid. */
return(EINVAL);
if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
- /* Fill in request message */
- req.fs_e = rfilp->filp_vno->v_fs_e;
- req.inode_nr = rfilp->filp_vno->v_inode_nr;
-
- /* Issue request */
- if ((r = req_inhibread(&req)) != OK) return r;
+ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
+ if (r != OK) return r;
}
rfilp->filp_pos = newpos;
#define pm_stime m1_i1
#define info_what m1_i1
#define info_where m1_p1
+#define md_label m2_p1
+#define md_label_len m2_l1
+#define md_major m2_i1
+#define md_style m2_i2
+#define md_force m2_i3
/* The following names are synonyms for the variables in the output message. */
#define reply_type m_type
#include "vnode.h"
#include "param.h"
-FORWARD _PROTOTYPE( int Xlookup, (lookup_req_t *lookup_req,
- node_details_t *node, char **pathrem) );
+FORWARD _PROTOTYPE( int lookup_rel, (struct vnode *start_node,
+ int flags, int use_realuid, node_details_t *node) );
+
/*===========================================================================*
- * lookup *
+ * lookup_rel_vp *
*===========================================================================*/
-PUBLIC int lookup(lookup_req, node)
-lookup_req_t *lookup_req;
-node_details_t *node;
+PUBLIC int lookup_rel_vp(start_node, flags, use_realuid, vpp)
+struct vnode *start_node;
+int flags;
+int use_realuid;
+struct vnode **vpp;
{
+ /* Resolve a pathname (in user_fullpath) starting at start_node to a vnode. */
+ int r, lookup_res;
+ struct vnode *new_vp, *vp;
struct vmnt *vmp;
- struct vnode *start_node;
- struct lookup_res res;
- int r, symloop = 0;
- int cum_path_processed = 0;
-
- /* Make a copy of the request so that the original values will be kept */
- struct lookup_req req = *lookup_req;
- char *fullpath = lookup_req->path;
+ struct node_details res;
- /* Empty (start) path? */
- if (fullpath[0] == '\0') {
- node->inode_nr = 0;
- return ENOENT;
+ /* See if free vnode is available */
+ if ((new_vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
+ printf("vfs:lookup_rel_vp: no free vnode available\n");
+ *vpp= NULL;
+ return EINVAL;
}
- /* Set user and group ids according to the system call */
- req.uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
- req.gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
+ lookup_res = lookup_rel(start_node, flags, use_realuid, &res);
- /* Set the starting directories inode number and FS endpoint */
- start_node = (fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
- req.start_dir = start_node->v_inode_nr;
- req.fs_e = start_node->v_fs_e;
+ if (lookup_res != OK)
+ {
+#if 0
+ printf("vfs:lookup_rel_vp: lookup_rel failed with %d\n", lookup_res);
+#endif
+ return lookup_res;
+ }
- /* 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)
- req.root_dir = fp->fp_rd->v_inode_nr;
- else
- req.root_dir = 0;
+ /* Check whether vnode is already in use or not */
+ if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
+ vp->v_ref_count++;
+ vp->v_fs_count++; /* We got a reference from the FS */
+ *vpp= vp;
+ return OK;
+ }
- req.symloop = symloop;
+ /* Fill in the free vnode's fields */
+ new_vp->v_fs_e = res.fs_e;
+ new_vp->v_inode_nr = res.inode_nr;
+ new_vp->v_mode = res.fmode;
+ new_vp->v_size = res.fsize;
+ new_vp->v_uid = res.uid;
+ new_vp->v_gid = res.gid;
+ new_vp->v_sdev = res.dev;
+
+ if ( (vmp = find_vmnt(new_vp->v_fs_e)) == NIL_VMNT)
+ panic(__FILE__, "vfs:lookup_rel_vp: vmnt not found", NO_NUM);
+
+ new_vp->v_vmnt = vmp;
+ new_vp->v_dev = vmp->m_dev;
+ new_vp->v_fs_count = 1;
+ new_vp->v_ref_count = 1;
+
+ *vpp= new_vp;
+ return OK;
+}
- /* Issue the request */
- r = req_lookup(&req, &res);
- /* While the response is related to mount control set the
- * new requests respectively */
- while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
-
- /* If a symlink was encountered during the lookup the
- * new path has been copied back and the number of characters
- * processed has been started over. */
- if (r == ESYMLINK || res.symloop > symloop) {
- /* The link's content is copied back to the user_fullpath
- * array. Use it as the path argument from now on... */
- fullpath = user_fullpath;
- cum_path_processed = res.char_processed;
- }
- else {
- /* Otherwise, cumulate the characters already processsed from
- * the path */
- cum_path_processed += res.char_processed;
- }
-
- /* Remember the current value of the symloop counter */
- symloop = res.symloop;
-
- /* Symlink encountered with absolute path */
- if (r == ESYMLINK) {
- start_node = fp->fp_rd;
- }
- /* Entering a new partition */
- else if (r == EENTERMOUNT) {
- start_node = 0;
- /* Start node is now the mounted partition's root node */
- for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
- if (vmp->m_mounted_on->v_inode_nr == res.inode_nr
- && vmp->m_mounted_on->v_fs_e == res.fs_e) {
- start_node = vmp->m_root_node;
- break;
- }
- }
- if (!start_node) {
- printf("VFSlookup: mounted partition couldn't be found\n");
- printf("VFSlookup: res.inode_nr = %d, res.fs_e = %d\n",
- res.inode_nr, res.fs_e);
- return ENOENT;
- }
-
- }
- /* Climbing up mount */
- else {
- /* Find the vmnt that represents the partition on
- * which we "climb up". */
- if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
- printf("VFS: couldn't find vmnt during the climbup!\n");
- return ENOENT;
- }
- /* Start node is the vnode on which the partition is
- * mounted */
- start_node = vmp->m_mounted_on;
- }
- /* Fill in the request fields */
- req.start_dir = start_node->v_inode_nr;
- req.fs_e = start_node->v_fs_e;
-
- /* Is the process' root directory on the same partition?*/
- if (start_node->v_dev == fp->fp_rd->v_dev)
- req.root_dir = fp->fp_rd->v_inode_nr;
- else
- req.root_dir = 0;
-
- /* Fill in the current path name */
- req.path = &fullpath[cum_path_processed];
- req.symloop = symloop;
-
- /* Issue the request */
- r = req_lookup(&req, &res);
- }
+/*===========================================================================*
+ * lookup_vp *
+ *===========================================================================*/
+PUBLIC int lookup_vp(flags, use_realuid, vpp)
+int flags;
+int use_realuid;
+struct vnode **vpp;
+{
+ /* Resolve a pathname (in user_fullpath) starting to a vnode. Call
+ * lookup_rel_vp to do the actual work.
+ */
+ struct vnode *vp;
- /* Fill in response fields */
- node->inode_nr = res.inode_nr;
- node->fmode = res.fmode;
- node->fsize = res.fsize;
- node->dev = res.dev;
- node->fs_e = res.fs_e;
- node->uid = res.uid;
- node->gid = res.gid;
-
- return r;
+ vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
+
+ return lookup_rel_vp(vp, flags, use_realuid, vpp);
}
/*===========================================================================*
- * Xlookup *
+ * lookup_lastdir_rel *
*===========================================================================*/
-PRIVATE int Xlookup(lookup_req, node, pathrem)
-lookup_req_t *lookup_req;
-node_details_t *node;
-char **pathrem;
+PUBLIC int lookup_lastdir_rel(start_node, use_realuid, vpp)
+struct vnode *start_node;
+int use_realuid;
+struct vnode **vpp;
{
- struct vmnt *vmp;
- struct vnode *start_node;
- struct lookup_res res;
- int r, symloop = 0;
- int cum_path_processed = 0;
+ /* This function is for calls that insert or delete entries from a
+ * directory. The path name (implicitly taken from user_fullpath)
+ * is split into to parts: the name of the directory and the
+ * directory entry. The name of the directory is resolved to a
+ * vnode. The directory entry is copied back to user_fullpath.
+ * The lookup starts at start_node.
+ */
+ int r;
+ char *cp;
+ char dir_entry[PATH_MAX+1];
+
+ if (strlen(user_fullpath) == 0)
+ {
+ /* Empty path, always fail */
+ return ENOENT;
+ }
+
+ cp= strrchr(user_fullpath, '/');
+ if (cp == NULL)
+ {
+ /* Just one entry in the current working directory */
+ dup_vnode(start_node);
+ *vpp= start_node;
+
+ return OK;
+ }
+ else if (cp[1] == '\0')
+ {
+ /* Path ends in a slash. The directory entry is '.' */
+ }
+ else
+ {
+ /* A path name for the directory and a directory entry */
+ strcpy(dir_entry, cp+1);
+ cp[1]= '\0';
+ }
+
+ /* Remove trailing slashes */
+ while(cp > user_fullpath && cp[0] == '/')
+ {
+ cp[0]= '\0';
+ cp--;
+ }
+
+ /* Request lookup */
+ r = lookup_rel_vp(start_node, 0 /*no flags*/, use_realuid, vpp);
+ if (r != OK)
+ return r;
+
+ /* Copy the directory entry back to user_fullpath */
+ strcpy(user_fullpath, dir_entry);
+
+ return OK;
+}
+
- /* Make a copy of the request so that the original values will be kept */
- struct lookup_req req = *lookup_req;
- char *fullpath = lookup_req->path;
+/*===========================================================================*
+ * lookup_lastdir *
+ *===========================================================================*/
+PUBLIC int lookup_lastdir(use_realuid, vpp)
+int use_realuid;
+struct vnode **vpp;
+{
+ /* This function is for calls that insert or delete entries from a
+ * directory. The path name (implicitly taken from user_fullpath)
+ * is split into to parts: the name of the directory and the
+ * directory entry. The name of the directory is resolved to a
+ * vnode. The directory entry is copied back to user_fullpath.
+ * Just call lookup_lastdir_rel with the appropriate starting vnode.
+ */
+ struct vnode *vp;
+
+ vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
+ return lookup_lastdir_rel(vp, use_realuid, vpp);
+}
- /* Clear pathrem */
- *pathrem= NULL;
+/*===========================================================================*
+ * lookup_rel *
+ *===========================================================================*/
+PRIVATE int lookup_rel(start_node, flags, use_realuid, node)
+struct vnode *start_node;
+int flags;
+int use_realuid;
+node_details_t *node;
+{
+ /* Resolve a pathname (in user_fullpath) relative to start_node. */
+ int r, symloop;
+ endpoint_t fs_e;
+ size_t path_off;
+ ino_t dir_ino, root_ino;
+ uid_t uid;
+ gid_t gid;
+ struct vnode *dir_vp;
+ struct vmnt *vmp;
+ struct lookup_res res;
+
/* Empty (start) path? */
- if (fullpath[0] == '\0') {
- node->inode_nr = 0;
- *pathrem = fullpath;
- return ENOENT;
+ if (user_fullpath[0] == '\0') {
+ node->inode_nr = 0;
+ printf("vfs:lookup_rel: returning ENOENT\n");
+ return ENOENT;
}
- /* Set user and group ids according to the system call */
- req.uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
- req.gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
-
- /* Set the starting directories inode number and FS endpoint */
- start_node = (fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
- req.start_dir = start_node->v_inode_nr;
- req.fs_e = start_node->v_fs_e;
-
+ fs_e = start_node->v_fs_e;
+ path_off = 0;
+ dir_ino = start_node->v_inode_nr;
/* 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)
- req.root_dir = fp->fp_rd->v_inode_nr;
+ root_ino = fp->fp_rd->v_inode_nr;
else
- req.root_dir = 0;
+ root_ino = 0;
- req.symloop = symloop;
+ /* Set user and group ids according to the system call */
+ uid = (use_realuid ? fp->fp_realuid : fp->fp_effuid);
+ gid = (use_realuid ? fp->fp_realgid : fp->fp_effgid);
+
+ symloop= 0; /* Number of symlinks seen so far */
/* Issue the request */
- r = req_lookup(&req, &res);
+ r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags, &res);
+
+ if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
+ {
+#if 0
+ printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r);
+#endif
+ return r;
+ }
/* While the response is related to mount control set the
* new requests respectively */
while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
-
- /* If a symlink was encountered during the lookup the
- * new path has been copied back and the number of characters
- * processed has been started over. */
- if (r == ESYMLINK || res.symloop > symloop) {
- /* The link's content is copied back to the user_fullpath
- * array. Use it as the path argument from now on... */
- fullpath = user_fullpath;
- cum_path_processed = res.char_processed;
- }
- else {
- /* Otherwise, cumulate the characters already processsed from
- * the path */
- cum_path_processed += res.char_processed;
- }
-
- /* Remember the current value of the symloop counter */
- symloop = res.symloop;
-
- /* Symlink encountered with absolute path */
- if (r == ESYMLINK) {
- start_node = fp->fp_rd;
- }
- /* Entering a new partition */
- else if (r == EENTERMOUNT) {
- start_node = 0;
- /* Start node is now the mounted partition's root node */
- for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
- if (vmp->m_mounted_on->v_inode_nr == res.inode_nr
- && vmp->m_mounted_on->v_fs_e == res.fs_e) {
- start_node = vmp->m_root_node;
- break;
- }
- }
- if (!start_node) {
- printf("VFSlookup: mounted partition couldn't be found\n");
- printf("VFSlookup: res.inode_nr = %d, res.fs_e = %d\n",
- res.inode_nr, res.fs_e);
- return ENOENT;
- }
-
- }
- /* Climbing up mount */
- else {
- /* Find the vmnt that represents the partition on
- * which we "climb up". */
- if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
- printf("VFS: couldn't find vmnt during the climbup!\n");
- return ENOENT;
- }
- /* Start node is the vnode on which the partition is
- * mounted */
- start_node = vmp->m_mounted_on;
- }
- /* Fill in the request fields */
- req.start_dir = start_node->v_inode_nr;
- req.fs_e = start_node->v_fs_e;
-
- /* Is the process' root directory on the same partition?*/
- if (start_node->v_dev == fp->fp_rd->v_dev)
- req.root_dir = fp->fp_rd->v_inode_nr;
- else
- req.root_dir = 0;
-
- /* Fill in the current path name */
- req.path = &fullpath[cum_path_processed];
- req.symloop = symloop;
-
- /* Issue the request */
- r = req_lookup(&req, &res);
- }
-
- if (r == ENOENT)
- {
- cum_path_processed += res.char_processed;
- *pathrem= &fullpath[cum_path_processed];
+ /* Save the place in the (possibly updated) path where we have to
+ * continue witht henext lookup request.
+ */
+ path_off= res.char_processed;
+
+ /* Update the current value of the symloop counter */
+ symloop += res.symloop;
+ if (symloop > SYMLOOP_MAX)
+ {
+ printf("vfs:lookup_rel: returning ELOOP\n");
+ return ELOOP;
+ }
+
+ /* Symlink encountered with absolute path */
+ if (r == ESYMLINK) {
+ dir_vp = fp->fp_rd;
+ }
+ else if (r == EENTERMOUNT) {
+ /* Entering a new partition */
+ dir_vp = 0;
+ /* Start node is now the mounted partition's root node */
+ for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
+ if (vmp->m_mounted_on->v_inode_nr == res.inode_nr &&
+ vmp->m_mounted_on->v_fs_e == res.fs_e) {
+ dir_vp = vmp->m_root_node;
+ break;
+ }
+ }
+ if (!dir_vp) {
+ printf(
+ "vfs:lookup_rel: res.inode_nr = %d, res.fs_e = %d\n",
+ res.inode_nr, res.fs_e);
+ panic(__FILE__,
+ "vfs:lookup_s: mounted partition couldn't be found",
+ NO_NUM);
+ }
+
+ }
+ else {
+ /* Climbing up mount */
+ /* Find the vmnt that represents the partition on
+ * which we "climb up". */
+ if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
+ panic(__FILE__,
+ "vfs:lookup_s: couldn't find vmnt during the climbup",
+ NO_NUM);
+ }
+ /* Start node is the vnode on which the partition is
+ * mounted */
+ dir_vp = vmp->m_mounted_on;
+ }
+
+ /* Set the starting directories inode number and FS endpoint */
+ fs_e = dir_vp->v_fs_e;
+ dir_ino = dir_vp->v_inode_nr;
+ /* 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;
+ else
+ root_ino = 0;
+
+ /* Issue the request */
+ r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags,
+ &res);
+
+ if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
+ {
+#if 0
+ printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r);
+#endif
+ return r;
+ }
}
/* Fill in response fields */
return r;
}
-
-
-/*===========================================================================*
- * lookup_vp *
- *===========================================================================*/
-PUBLIC int lookup_vp(lookup_req, vpp)
-lookup_req_t *lookup_req;
-struct vnode **vpp;
-{
- int r, lookup_res;
- struct vnode *vp;
- struct vmnt *vmp;
- node_req_t node_req;
- struct node_details res;
-
- lookup_res = lookup(lookup_req, &res);
-
- if (res.inode_nr == 0)
- {
-#if 0
- printf("lookup_vp: lookup returned no inode\n");
- printf("lookup_res = %d, last = '%s'\n\n",
- lookup_res, lookup_req->lastc);
-#endif
- *vpp= NULL;
- return lookup_res;
- }
-
- /* Check whether vnode is already in use or not */
- if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
- vp->v_ref_count++;
- *vpp= vp;
- return lookup_res;
- }
-
- /* See if free vnode is available */
- if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
- printf("VFS lookup_vp: no free vnode available\n");
- *vpp= NULL;
- return EINVAL;
- }
-
- /* Fill in request message fields.*/
- node_req.fs_e = res.fs_e;
- node_req.inode_nr = res.inode_nr;
-
- /* Issue request */
- if ((r = req_getnode(&node_req, &res)) != OK)
- {
- printf("lookup_vp: req_getnode failed: %d\n", r);
- *vpp= NULL;
- return r;
- }
-
- /* Fill in the free vnode's fields */
- vp->v_fs_e = res.fs_e;
- vp->v_inode_nr = res.inode_nr;
- vp->v_mode = res.fmode;
- vp->v_size = res.fsize;
- vp->v_uid = res.uid;
- vp->v_gid = res.gid;
- vp->v_sdev = res.dev;
-
- if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
- panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM);
-
- vp->v_vmnt = vmp;
- vp->v_dev = vmp->m_dev;
- vp->v_fs_count = 1;
- vp->v_ref_count = 1;
-
- *vpp= vp;
- return lookup_res;
-}
-
-/*===========================================================================*
- * Xlookup_vp *
- *===========================================================================*/
-PUBLIC int Xlookup_vp(lookup_req, vpp, pathrem)
-lookup_req_t *lookup_req;
-struct vnode **vpp;
-char **pathrem;
-{
- int r, lookup_res;
- struct vnode *vp;
- struct vmnt *vmp;
- node_req_t node_req;
- struct node_details res;
-
- lookup_res = Xlookup(lookup_req, &res, pathrem);
-
- if (res.inode_nr == 0)
- {
-#if 0
- printf("Xlookup_vp: lookup returned no inode\n");
- printf("lookup_res = %d, last = '%s'\n\n",
- lookup_res, lookup_req->lastc);
-#endif
- *vpp= NULL;
- return lookup_res;
- }
-
- /* Check whether vnode is already in use or not */
- if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
- vp->v_ref_count++;
- *vpp= vp;
- return lookup_res;
- }
-
- /* See if free vnode is available */
- if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
- printf("VFS Xlookup_vp: no free vnode available\n");
- *vpp= NULL;
- return EINVAL;
- }
-
- /* Fill in request message fields.*/
- node_req.fs_e = res.fs_e;
- node_req.inode_nr = res.inode_nr;
-
- /* Issue request */
- if ((r = req_getnode(&node_req, &res)) != OK)
- {
- printf("Xlookup_vp: req_getnode failed: %d\n", r);
- *vpp= NULL;
- return r;
- }
-
- /* Fill in the free vnode's fields */
- vp->v_fs_e = res.fs_e;
- vp->v_inode_nr = res.inode_nr;
- vp->v_mode = res.fmode;
- vp->v_size = res.fsize;
- vp->v_uid = res.uid;
- vp->v_gid = res.gid;
- vp->v_sdev = res.dev;
-
- if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
- panic(__FILE__, "Xlookup_vp: vmnt not found", NO_NUM);
-
- vp->v_vmnt = vmp;
- vp->v_dev = vmp->m_dev;
- vp->v_fs_count = 1;
- vp->v_ref_count = 1;
-
- *vpp= vp;
- return lookup_res;
-}
-
int r;
struct filp *fil_ptr0, *fil_ptr1;
int fil_des[2]; /* reply goes here */
-
struct vnode *vp;
struct vmnt *vmp;
-
- struct pipe_req req;
struct node_details res;
/* See if a free vnode is available */
FD_SET(fil_des[1], &rfp->fp_filp_inuse);
fil_ptr1->filp_count = 1;
- /* Fill in FS request */
- req.fs_e = ROOT_FS_E;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
-
/* Send request */
- r = req_pipe(&req, &res);
+ r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE,
+ (dev_t)0, &res);
/* Handle error */
if (r != OK) {
vp->v_mode = res.fmode;
vp->v_index = res.inode_index;
vp->v_pipe = I_PIPE;
- vp->v_fs_count = 2; /* Double usage */
- vp->v_ref_count = 2; /* Double usage */
+ vp->v_fs_count = 1;
+ vp->v_ref_count = 1;
vp->v_size = 0;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) {
/* Fill in filp objects */
fil_ptr0->filp_vno = vp;
+ dup_vnode(vp);
fil_ptr1->filp_vno = vp;
fil_ptr0->filp_flags = O_RDONLY;
fil_ptr1->filp_flags = O_WRONLY;
/*===========================================================================*
* pipe_check *
*===========================================================================*/
-PUBLIC int pipe_check(vp, rw_flag, oflags, bytes, position, canwrite, notouch)
+PUBLIC int Xpipe_check(vp, rw_flag, oflags, bytes, position, notouch)
register struct vnode *vp; /* the inode of the pipe */
int rw_flag; /* READING or WRITING */
int oflags; /* flags set by open or fcntl */
register int bytes; /* bytes to be read or written (all chunks) */
u64_t position; /* current file position */
-int *canwrite; /* return: number of bytes we can write */
int notouch; /* check only */
{
/* Pipes are a little different. If a process reads from an empty pipe for
if (oflags & O_NONBLOCK) {
r = EAGAIN;
} else {
- if (!notouch)
- suspend(XPIPE); /* block reader */
r = SUSPEND;
}
/* If need be, activate sleeping writers. */
}
return(r);
}
- } else {
- /* Process is writing to a pipe. */
- if (find_filp(vp, R_BIT) == NIL_FILP) {
- /* Tell kernel to generate a SIGPIPE signal. */
- if (!notouch) {
- sys_kill(fp->fp_endpoint, SIGPIPE);
- }
- return(EPIPE);
+
+ return bytes;
+ }
+
+ /* Process is writing to a pipe. */
+ if (find_filp(vp, R_BIT) == NIL_FILP) {
+ /* Tell kernel to generate a SIGPIPE signal. */
+ if (!notouch) {
+ sys_kill(fp->fp_endpoint, SIGPIPE);
}
+ return(EPIPE);
+ }
- if (pos + bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) {
- if ((oflags & O_NONBLOCK)
- && bytes <= PIPE_SIZE(vp->v_vmnt->m_block_size)) {
+ if (pos + bytes > PIPE_BUF) {
+ if (oflags & O_NONBLOCK)
+ {
+ if (bytes <= PIPE_BUF) {
+ /* Write has to be atomic */
return(EAGAIN);
}
- else if ((oflags & O_NONBLOCK)
- && bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) {
- if ( (*canwrite = (PIPE_SIZE(vp->v_vmnt->m_block_size)
- - pos)) > 0) {
- /* Do a partial write. Need to wakeup reader */
- if (!notouch)
- release(vp, READ, susp_count);
- return(1);
- } else {
- return(EAGAIN);
- }
- }
- if (bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) {
- if ((*canwrite = PIPE_SIZE(vp->v_vmnt->m_block_size)
- - pos) > 0) {
- /* Do a partial write. Need to wakeup reader
- * since we'll suspend ourself in read_write()
- */
- if (!notouch)
- release(vp, READ, susp_count);
- return(1);
- }
+
+ /* Compute available space */
+ bytes= PIPE_BUF-pos;
+
+ if (bytes > 0) {
+ /* Do a partial write. Need to wakeup reader */
+ if (!notouch)
+ release(vp, READ, susp_count);
+ return(bytes);
+ } else {
+ /* Pipe is full */
+ return(EAGAIN);
+ }
+ }
+
+ if (bytes > PIPE_BUF) {
+ /* Compute available space */
+ bytes= PIPE_BUF-pos;
+
+ if (bytes > 0) {
+ /* Do a partial write. Need to wakeup reader
+ * since we'll suspend ourself in read_write()
+ */
+ if (!notouch)
+ release(vp, READ, susp_count);
+ return(bytes);
}
- if (!notouch)
- suspend(XPIPE); /* stop writer -- pipe full */
- return(SUSPEND);
}
- /* Writing to an empty pipe. Search for suspended reader. */
- if (pos == 0 && !notouch)
- release(vp, READ, susp_count);
+ /* Pipe is full, or we need an atomic write */
+ return(SUSPEND);
}
- *canwrite = 0;
- return(1);
+ /* Writing to an empty pipe. Search for suspended reader. */
+ if (pos == 0 && !notouch)
+ release(vp, READ, susp_count);
+
+ /* Requested amount fits */
+ return bytes;
}
/*===========================================================================*
* The SUSPEND pseudo error should be returned after calling suspend().
*/
- if (task == XPIPE || task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
+ if (task == XPIPE)
+ panic(__FILE__, "suspend: called for XPIPE", NO_NUM);
+
+ if (task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
fp->fp_suspended = SUSPENDED;
assert(!GRANT_VALID(fp->fp_grant));
fp->fp_fd = m_in.fd << 8 | call_nr;
}
}
+/*===========================================================================*
+ * pipe_suspend *
+ *===========================================================================*/
+PUBLIC void pipe_suspend(rw_flag, fd_nr, buf, size)
+int rw_flag;
+int fd_nr;
+char *buf;
+size_t size;
+{
+/* Take measures to suspend the processing of the present system call.
+ * Store the parameters to be used upon resuming in the process table.
+ * (Actually they are not used when a process is waiting for an I/O device,
+ * but they are needed for pipes, and it is not worth making the distinction.)
+ * The SUSPEND pseudo error should be returned after calling suspend().
+ */
+
+ susp_count++; /* #procs susp'ed on pipe*/
+ fp->fp_suspended = SUSPENDED;
+ assert(!GRANT_VALID(fp->fp_grant));
+ fp->fp_fd = (fd_nr << 8) | ((rw_flag == READING) ? READ : WRITE);
+ fp->fp_task = -XPIPE;
+ fp->fp_buffer = buf;
+ fp->fp_nbytes = size;
+}
+
/*===========================================================================*
* unsuspend_by_endpt *
*===========================================================================*/
register struct fproc *rp;
struct filp *f;
+#if 0
+ printf("vfs:release: vp 0x%x, call %d, count %d\n", vp, call_nr, count);
+#endif
+
/* Trying to perform the call also includes SELECTing on it with that
* operation.
*/
int orig_ops, r = 0, err, canwrite;
orig_ops = *ops;
if ((*ops & (SEL_RD|SEL_ERR))) {
- if ((err = pipe_check(f->filp_vno, READING, 0,
- 1, f->filp_pos, &canwrite, 1)) != SUSPEND)
+ if ((err = Xpipe_check(f->filp_vno, READING, 0,
+ 1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_RD;
if (err < 0 && err != SUSPEND)
r |= SEL_ERR;
}
if ((*ops & (SEL_WR|SEL_ERR))) {
- if ((err = pipe_check(f->filp_vno, WRITING, 0,
- 1, f->filp_pos, &canwrite, 1)) != SUSPEND)
+ if ((err = Xpipe_check(f->filp_vno, WRITING, 0,
+ 1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_WR;
if (err < 0 && err != SUSPEND)
r |= SEL_ERR;
PUBLIC int do_chmod()
{
struct filp *flp;
- struct chmod_req req;
- struct lookup_req lookup_req;
- struct node_details res;
struct vnode *vp;
- int r, ch_mode;
+ int r;
+ uid_t uid;
+ gid_t gid;
+ mode_t new_mode;
if (call_nr == CHMOD) {
/* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- req.inode_nr = res.inode_nr;
- req.fs_e = res.fs_e;
+ r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
+ if (r != OK) return r;
}
else if (call_nr == FCHMOD) {
if (!(flp = get_filp(m_in.m3_i1))) return err_code;
- req.inode_nr = flp->filp_vno->v_inode_nr;
- req.fs_e = flp->filp_vno->v_fs_e;
+ vp= flp->filp_vno;
+ dup_vnode(vp);
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
- /* Find vnode, if it's in use. */
- vp = find_vnode(req.fs_e, req.inode_nr);
+ uid= fp->fp_effuid;
+ gid= fp->fp_effgid;
+
+ /* Only the owner or the super_user may change the mode of a file.
+ * No one may change the mode of a file on a read-only file system.
+ */
+ if (vp->v_uid != uid && uid != SU_UID)
+ r = EPERM;
+ else
+ r = read_only(vp);
+
+ /* If error, return inode. */
+ if (r != OK) {
+ put_vnode(vp);
+ return(r);
+ }
+
+ /* Now make the change. Clear setgid bit if file is not in caller's grp */
+ if (uid != SU_UID && vp->v_gid != gid)
+ m_in.mode &= ~I_SET_GID_BIT;
- /* Fill in request message fields.*/
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
- req.rmode = m_in.mode;
-
/* Issue request */
- if((r = req_chmod(&req, &ch_mode)) != OK) return r;
+ r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode);
- if(vp != NIL_VNODE)
- vp->v_mode = ch_mode;
+ if (r == OK)
+ vp->v_mode = new_mode;
+ put_vnode(vp);
return OK;
}
int inode_nr;
int fs_e;
struct filp *flp;
- struct chown_req req;
- struct lookup_req lookup_req;
- struct node_details res;
struct vnode *vp;
- int r, ch_mode;
+ int r;
+ uid_t uid;
+ gid_t gid;
+ mode_t new_mode;
if (call_nr == CHOWN) {
/* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- req.inode_nr = res.inode_nr;
- req.fs_e = res.fs_e;
+ r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
+ if (r != OK) return r;
}
else if (call_nr == FCHOWN) {
if (!(flp = get_filp(m_in.m1_i1))) return err_code;
- req.inode_nr = flp->filp_vno->v_inode_nr;
- req.fs_e = flp->filp_vno->v_fs_e;
+ vp= flp->filp_vno;
+ dup_vnode(vp);
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
- /* Find vnode, if it's in use. */
- vp = find_vnode(req.fs_e, req.inode_nr);
+ uid= fp->fp_effuid;
+ gid= fp->fp_effgid;
+
+ r= OK;
+ if (uid == SU_UID) {
+ /* The super user can do anything. */
+ } else {
+ /* Regular users can only change groups of their own files. */
+ if (vp->v_uid != uid)
+ r = EPERM; /* File does not belong to the caller */
+ if (vp->v_uid != m_in.owner)
+ r = EPERM; /* no giving away */
+ if (gid != m_in.group)
+ r = EPERM; /* only change to the current gid */
+ }
+ if (r != OK) {
+ put_vnode(vp);
+ return r;
+ }
- /* Fill in request message fields.*/
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
- req.newuid = m_in.owner;
- req.newgid = m_in.group;
-
/* Issue request */
- r = req_chown(&req, &ch_mode);
+ r = req_chown(vp->v_fs_e, vp->v_inode_nr, m_in.owner, m_in.group, &new_mode);
- if(r == OK && vp) {
+ if(r == OK) {
vp->v_uid = m_in.owner;
vp->v_gid = m_in.group;
- vp->v_mode = ch_mode;
+ vp->v_mode = new_mode;
}
+ put_vnode(vp);
+
return r;
}
PUBLIC int do_access()
{
/* Perform the access(name, mode) system call. */
- struct access_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
+ struct vnode *vp;
/* First check to see if the mode is correct. */
if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
-
- /* Fill in request fields */
- req.fs_e = res.fs_e;
- req.amode = m_in.mode;
- req.inode_nr = res.inode_nr;
- req.uid = fp->fp_realuid; /* real user and group id */
- req.gid = fp->fp_realgid;
-
- /* Issue request */
- return req_access(&req);
+ r = lookup_vp(0 /*flags*/, TRUE /*use_realuid*/, &vp);
+ if (r != OK) return r;
+
+ r= forbidden(vp, m_in.mode, 1 /*use_realuid*/);
+ put_vnode(vp);
+ return r;
}
/*===========================================================================*
* forbidden *
*===========================================================================*/
-PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
+PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid)
{
/* Given a pointer to an inode, 'rip', and the access desired, determine
* if the access is allowed, and if not why not. The routine looks up the
register struct super_block *sp;
register mode_t bits, perm_bits;
+ uid_t uid;
+ gid_t gid;
int r, shift, type;
if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1)
{
- printf("forbidden: bad uid/gid in vnode\n");
+ printf("forbidden: bad uid/gid in vnode: inode %d on dev 0x%x\n",
+ vp->v_inode_nr, vp->v_dev);
printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line);
return EACCES;
}
/* Isolate the relevant rwx bits from the mode. */
bits = vp->v_mode;
- if (fp->fp_effuid == SU_UID) {
+ if (use_realuid)
+ {
+ uid= fp->fp_realuid;
+ gid= fp->fp_realgid;
+ }
+ else
+ {
+ uid= fp->fp_effuid;
+ gid= fp->fp_effgid;
+ }
+ if (uid == SU_UID) {
/* Grant read and write permission. Grant search permission for
* directories. Grant execute permission (for non-directories) if
* and only if one of the 'X' bits is set.
else
perm_bits = R_BIT | W_BIT;
} else {
- if (fp->fp_effuid == vp->v_uid) shift = 6; /* owner */
- else if (fp->fp_effgid == vp->v_gid ) shift = 3; /* group */
+ if (uid == vp->v_uid) shift = 6; /* owner */
+ else if (gid == vp->v_gid ) shift = 3; /* group */
else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
}
/* device.c */
_PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags) );
_PROTOTYPE( void dev_close, (Dev_t dev) );
-_PROTOTYPE( int dev_bio, (int op, Dev_t dev, int proc, void *buf,
- off_t pos, int bytes) );
_PROTOTYPE( int dev_io, (int op, Dev_t dev, int proc, void *buf,
u64_t pos, int bytes, int flags) );
_PROTOTYPE( int gen_opcl, (int op, Dev_t dev, int proc, int flags) );
_PROTOTYPE( int do_devctl, (void) );
_PROTOTYPE( int fs_devctl, (int req, int dev, int proc_nr_e, int style,
int force) );
+_PROTOTYPE( int do_mapdriver, (void) );
_PROTOTYPE( void build_dmap, (void) );
_PROTOTYPE( int map_driver, (int major, int proc_nr, int dev_style,
int force) );
_PROTOTYPE( int do_slink, (void) );
/* path.c */
-_PROTOTYPE( int lookup, (lookup_req_t *request, node_details_t *node) );
-_PROTOTYPE( int lookup_vp, (lookup_req_t *request, struct vnode **vpp) );
-_PROTOTYPE( int Xlookup_vp, (lookup_req_t *request, struct vnode **vpp,
- char **pathrem) );
+_PROTOTYPE( int lookup_rel_vp, (struct vnode *start_node, int flags,
+ int use_realuid, struct vnode **vpp) );
+_PROTOTYPE( int lookup_vp, (int flags, int use_realuid,
+ struct vnode **vpp) );
+_PROTOTYPE( int lookup_lastdir_rel, (struct vnode *start_node,
+ int use_realuid, struct vnode **vpp) );
+_PROTOTYPE( int lookup_lastdir, (int use_realuid, struct vnode **vpp) );
/* pipe.c */
_PROTOTYPE( int do_pipe, (void) );
_PROTOTYPE( int do_unpause, (void) );
_PROTOTYPE( int unpause, (int proc_nr_e) );
-_PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
- int oflags, int bytes, u64_t position, int *canwrite, int notouch));
+_PROTOTYPE( int Xpipe_check, (struct vnode *vp, int rw_flag,
+ int oflags, int bytes, u64_t position, int notouch) );
_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) );
_PROTOTYPE( void revive, (int proc_nr, int bytes) );
_PROTOTYPE( void suspend, (int task) );
+_PROTOTYPE( void pipe_suspend, (int rw_flag, int fd_nr, char *buf,
+ size_t size) );
_PROTOTYPE( int select_request_pipe, (struct filp *f, int *ops, int bl) );
_PROTOTYPE( int select_cancel_pipe, (struct filp *f) );
_PROTOTYPE( int select_match_pipe, (struct filp *f) );
_PROTOTYPE( int do_chmod, (void) );
_PROTOTYPE( int do_chown, (void) );
_PROTOTYPE( int do_umask, (void) );
-_PROTOTYPE( int forbidden, (struct vnode *vp, mode_t access_desired) );
+_PROTOTYPE( int forbidden, (struct vnode *vp,
+ mode_t access_desired, int use_realuid) );
_PROTOTYPE( int read_only, (struct vnode *vp) );
/* read.c */
_PROTOTYPE( int do_read, (void) );
_PROTOTYPE( int do_getdents, (void) );
_PROTOTYPE( int read_write, (int rw_flag) );
+_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr,
+ int fd_nr, struct filp *f, char *buf, size_t req_size) );
/* request.c */
-#define req_getnode(req, res) req_getnode_f(__FILE__, __LINE__, (req), (res))
-_PROTOTYPE( int req_getnode_f, (char *file, int line, node_req_t *req, node_details_t *res) );
-_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) );
-_PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res) );
+_PROTOTYPE( int req_breadwrite, (endpoint_t fs_e, endpoint_t user_e,
+ Dev_t dev, u64_t pos, unsigned int num_of_bytes,
+ char *user_addr, int rw_flag,
+ u64_t *new_posp, unsigned int *cum_iop) );
+_PROTOTYPE( int req_chmod, (int fs_e, ino_t inode_nr, _mnx_Mode_t rmode,
+ mode_t *new_modep) );
+_PROTOTYPE( int req_chown, (endpoint_t fs_e, ino_t inode_nr,
+ _mnx_Uid_t newuid, _mnx_Gid_t newgid, mode_t *new_modep) );
_PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode,
int uid, int gid, char *path, node_details_t *res) );
-_PROTOTYPE( int req_readwrite, (readwrite_req_t *req,
- readwrite_res_t *res) );
-_PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_t *res) );
-_PROTOTYPE( int req_clone_opcl, (clone_opcl_req_t *req,
- node_details_t *res) );
-_PROTOTYPE( int req_ftrunc, (ftrunc_req_t *req) );
-_PROTOTYPE( int req_chown, (chown_req_t *req, int *mode) );
-_PROTOTYPE( int req_chmod, (chmod_req_t *req, int *mode) );
-_PROTOTYPE( int req_access, (access_req_t *req) );
-_PROTOTYPE( int req_mknod, (mknod_req_t *req) );
-_PROTOTYPE( int req_mkdir, (mkdir_req_t *req) );
-_PROTOTYPE( int req_inhibread, (node_req_t *req) );
-_PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e,
- char *buf, int pos) );
+_PROTOTYPE( int req_flush, (endpoint_t fs_e, Dev_t dev) );
_PROTOTYPE( int req_fstatfs, (int fs_e, ino_t inode_nr, int who_e,
char *buf) );
-_PROTOTYPE( int req_unlink, (unlink_req_t *req) );
-_PROTOTYPE( int req_rmdir, (unlink_req_t *req) );
-_PROTOTYPE( int req_utime, (utime_req_t *req) );
-_PROTOTYPE( int req_stime, (endpoint_t fs_e, time_t boottime) );
+_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,
+ off_t pos, cp_grant_id_t gid, size_t size, off_t *pos_change) );
+_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, size_t path_off,
+ ino_t dir_ino, ino_t root_ino, _mnx_Uid_t uid,
+ _mnx_Gid_t gid, int flags, lookup_res_t *res) );
+_PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr,
+ char *lastc, _mnx_Uid_t uid, _mnx_Gid_t gid, _mnx_Mode_t dmode) );
+_PROTOTYPE( int req_mknod, (endpoint_t fs_e, ino_t inode_nr,
+ char *lastc, _mnx_Uid_t uid, _mnx_Gid_t gid,
+ _mnx_Mode_t dmode, Dev_t dev) );
+_PROTOTYPE( int req_mountpoint, (endpoint_t fs_e, ino_t inode_nr) );
+_PROTOTYPE( int req_newnode, (endpoint_t fs_e, _mnx_Uid_t uid,
+ _mnx_Gid_t gid, _mnx_Mode_t dmode,
+ 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, vir_bytes buf, size_t len) );
+_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 req_readwrite, (endpoint_t fs_e, ino_t inode_nr,
+ int inode_index, u64_t pos, int rw_flag,
+ endpoint_t user_e, char *user_addr,
+ unsigned int num_of_bytes, u64_t *new_posp,
+ unsigned int *cum_iop) );
+_PROTOTYPE( int req_rename, (endpoint_t fs_e, ino_t old_dir,
+ char *old_name, ino_t new_dir, char *new_name) );
+_PROTOTYPE( int req_rmdir, (endpoint_t fs_e, ino_t inode_nr,
+ char *lastc) );
+_PROTOTYPE(int req_slink, (endpoint_t fs_e, ino_t inode_nr, char *lastc,
+ endpoint_t who_e, char *path_addr,
+ int path_length, _mnx_Uid_t uid, _mnx_Gid_t gid) );
+_PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e,
+ char *buf, int pos) );
_PROTOTYPE( int req_sync, (endpoint_t fs_e) );
-_PROTOTYPE( int req_link, (link_req_t *req) );
-_PROTOTYPE( int req_slink, (slink_req_t *req) );
-_PROTOTYPE( int req_rdlink, (rdlink_req_t *req) );
-_PROTOTYPE( int req_rename, (rename_req_t *req) );
-_PROTOTYPE( int req_mountpoint, (mountpoint_req_t *req,
- node_details_t *res) );
-_PROTOTYPE( int req_readsuper, (readsuper_req_t *req,
- readsuper_res_t *res) );
+_PROTOTYPE( int req_unlink, (endpoint_t fs_e, ino_t inode_nr,
+ char *lastc) );
_PROTOTYPE( int req_unmount, (endpoint_t fs_e) );
-_PROTOTYPE( int req_trunc, (trunc_req_t *req) );
-_PROTOTYPE( int req_lookup, (lookup_req_t *req, lookup_res_t *res) );
+_PROTOTYPE( int req_utime, (endpoint_t fs_e, ino_t inode_nr,
+ time_t actime, time_t modtime) );
_PROTOTYPE( int req_newdriver, (endpoint_t fs_e, Dev_t dev,
endpoint_t driver_e) );
-_PROTOTYPE( int req_breadwrite, (breadwrite_req_t *req,
- readwrite_res_t *res) );
-_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr,
- off_t pos, cp_grant_id_t gid, size_t size, off_t *pos_change) );
-_PROTOTYPE( int req_flush, (endpoint_t fs_e, Dev_t) );
/* stadir.c */
_PROTOTYPE( int do_chdir, (void) );
_PROTOTYPE( int do_lstat, (void) );
/* time.c */
-_PROTOTYPE( int do_stime, (void) );
_PROTOTYPE( int do_utime, (void) );
/* utility.c */
_PROTOTYPE( void dup_vnode, (struct vnode *vp) );
_PROTOTYPE( void put_vnode, (struct vnode *vp) );
_PROTOTYPE( void vnode_clean_refs, (struct vnode *vp) );
+#if 0
_PROTOTYPE( struct vnode *get_vnode, (int fs_e, int inode_nr) );
_PROTOTYPE( struct vnode *get_vnode_x, (int fs_e, int inode_nr) );
+#endif
#if 0
_PROTOTYPE( void mark_vn, (struct vnode *vp, char *file, int line) );
_PROTOTYPE( int check_vrefs, (void) );
#include "vnode.h"
#include "vmnt.h"
-
/*===========================================================================*
* do_read *
*===========================================================================*/
register struct filp *f;
register struct vnode *vp;
off_t bytes_left;
- u64_t position;
- unsigned int off, cum_io;
- int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
- int regular, partial_pipe = 0, partial_cnt = 0;
+ u64_t position, res_pos, new_pos;
+ unsigned int off, cum_io, cum_io_incr, res_cum_io, num_of_bytes;
+ int op, oflags, r, chunk, usr, block_spec, char_spec;
+ int regular;
mode_t mode_word;
- struct filp *wf;
phys_bytes p;
struct dmap *dp;
- /* Request and response structures */
- struct readwrite_req req;
- struct readwrite_res res;
-
- /* For block spec files */
- struct breadwrite_req breq;
-
/* PM loads segments by putting funny things in other bits of the
* message, indicated by a high bit in fd. */
if (who_e == PM_PROC_NR && (m_in.fd & _PM_SEG_FLAG)) {
- seg = (int) m_in.m1_p2;
- usr = (int) m_in.m1_p3;
- m_in.fd &= ~(_PM_SEG_FLAG); /* get rid of flag bit */
+ panic(__FILE__,
+ "read_write: special read/write calls by PM no longer supported",
+ NO_NUM);
}
else {
usr = who_e; /* normal case */
- seg = D;
}
/* If the file descriptor is valid, get the vnode, size and mode. */
- if (m_in.nbytes < 0) return(EINVAL);
- if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+ if (m_in.nbytes < 0)
+ return(EINVAL);
+
+ if ((f = get_filp(m_in.fd)) == NIL_FILP)
+ {
+ printf("vfs:read_write: returning %d\n", err_code);
+ return(err_code);
+ }
if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
+ printf("vfs:read_write: returning error\n");
return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
}
if (m_in.nbytes == 0)
return(0); /* so char special files need not check for 0*/
- /* check if user process has the memory it needs.
- * if not, copying will fail later.
- * do this after 0-check above because umap doesn't want to map 0 bytes. */
- if ((r = sys_umap(usr, seg, (vir_bytes) m_in.buffer, m_in.nbytes, &p)) != OK)
- {
- printf("VFS: read_write: umap failed for process %d\n", usr);
- return r;
- }
-
position = f->filp_pos;
oflags = f->filp_flags;
vp = f->filp_vno;
- r = OK;
- if (vp->v_pipe == I_PIPE) {
- /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
- cum_io = fp->fp_cum_io_partial;
- }
- else {
- cum_io = 0;
+ if (vp->v_pipe)
+ {
+ if (rw_flag == WRITING)
+ {
+ if (vp->v_w_pipe_busy)
+ {
+ panic(__FILE__,
+ "read_write: pipe already has a writer",
+ NO_NUM);
+ }
+ if (fp->fp_cum_io_partial != 0)
+ {
+ panic(__FILE__,
+ "read_write: fp_cum_io_partial not clear for new pipe writer",
+ NO_NUM);
+ }
+ vp->v_w_pipe_busy= TRUE;
+ }
+ return rw_pipe(rw_flag, usr, m_in.fd, f, m_in.buffer, m_in.nbytes);
}
+ r = OK;
+ cum_io = 0;
+
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
mode_word = vp->v_mode & I_TYPE;
- regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
+ regular = mode_word == I_REGULAR;
if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
if (vp->v_sdev == NO_DEV)
}
/* Block special files. */
else if (block_spec) {
- /* Fill in the fields of the request */
- breq.rw_flag = rw_flag;
- breq.fs_e = vp->v_bfs_e;
- breq.blocksize = vp->v_blocksize;
- breq.dev = vp->v_sdev;
- breq.user_e = usr;
- breq.pos = position;
- breq.num_of_bytes = m_in.nbytes;
- breq.user_addr = m_in.buffer;
/* Issue request */
- r = req_breadwrite(&breq, &res);
+ r = req_breadwrite(vp->v_bfs_e, usr, vp->v_sdev, position,
+ m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io);
- position = res.new_pos;
- cum_io += res.cum_io;
+ position = res_pos;
+ cum_io += res_cum_io;
}
- /* Regular files (and pipes) */
+ /* Regular files */
else {
if (rw_flag == WRITING && block_spec == 0) {
/* Check for O_APPEND flag. */
if (oflags & O_APPEND) position = cvul64(vp->v_size);
-
- /* Check in advance to see if file will grow too big. */
- if (cmp64ul(position, vp->v_vmnt->m_max_file_size - m_in.nbytes) > 0)
- return(EFBIG);
-
}
- /* Pipes are a little different. Check. */
- if (vp->v_pipe == I_PIPE) {
- r = pipe_check(vp, rw_flag, oflags,
- m_in.nbytes, position, &partial_cnt, 0);
- if (r <= 0) return(r);
- }
-
- if (partial_cnt > 0) {
- /* So that we don't need to deal with partial count
- * in the FS process.
- */
- m_in.nbytes = MIN(m_in.nbytes, partial_cnt);
- partial_pipe = 1;
- }
/* Fill in request structure */
- req.fs_e = vp->v_fs_e;
- req.rw_flag = rw_flag;
- req.inode_nr = vp->v_inode_nr;
- req.user_e = usr;
- req.seg = seg;
- req.pos = position;
- req.num_of_bytes = m_in.nbytes;
- req.user_addr = m_in.buffer;
- req.inode_index = vp->v_index;
+ num_of_bytes = m_in.nbytes;
/* Truncate read request at size (mustn't do this for special files). */
if((rw_flag == READING) &&
- cmp64ul(add64ul(position, req.num_of_bytes), vp->v_size) > 0) {
- /* Position always should fit in an off_t (LONG_MAX). */
- off_t pos32;
- assert(cmp64ul(position, LONG_MAX) <= 0);
- pos32 = cv64ul(position);
- assert(pos32 >= 0);
- assert(pos32 <= LONG_MAX);
- req.num_of_bytes = vp->v_size - pos32;
- assert(req.num_of_bytes >= 0);
+ cmp64ul(add64ul(position, num_of_bytes), vp->v_size) > 0) {
+ /* Position always should fit in an off_t (LONG_MAX). */
+ off_t pos32;
+ assert(cmp64ul(position, LONG_MAX) <= 0);
+ pos32 = cv64ul(position);
+ assert(pos32 >= 0);
+ assert(pos32 <= LONG_MAX);
+ num_of_bytes = vp->v_size - pos32;
+ assert(num_of_bytes >= 0);
}
/* Issue request */
- r = req_readwrite(&req, &res);
+ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, position,
+ rw_flag, usr, m_in.buffer, num_of_bytes, &new_pos, &cum_io_incr);
if (r >= 0)
{
- if (ex64hi(res.new_pos))
+ if (ex64hi(new_pos))
panic(__FILE__, "read_write: bad new pos", NO_NUM);
- position = res.new_pos;
- cum_io += res.cum_io;
+ position = new_pos;
+ cum_io += cum_io_incr;
}
}
}
}
}
- else {
- if (vp->v_pipe == I_PIPE) {
- if (cmp64ul(position, vp->v_size) >= 0) {
- /* Reset pipe pointers */
- vp->v_size = 0;
- position = cvu64(0);
- wf = find_filp(vp, W_BIT);
- if (wf != NIL_FILP) wf->filp_pos = cvu64(0);
- }
- }
- }
f->filp_pos = position;
if (r == OK) {
- if (partial_pipe) {
- partial_pipe = 0;
- /* partial write on pipe with */
- /* O_NONBLOCK, return write count */
- if (!(oflags & O_NONBLOCK)) {
- fp->fp_cum_io_partial = cum_io;
- suspend(XPIPE); /* partial write on pipe with */
- return(SUSPEND); /* nbyte > PIPE_SIZE - non-atomic */
- }
- }
- fp->fp_cum_io_partial = 0;
return cum_io;
}
}
-/* Original "uncached" code for block spec files */
-#if 0
- else if (block_spec) {
- char buf[_MIN_BLOCK_SIZE];
- block_t b;
- int bleft = m_in.nbytes;
- dev_t dev = vp->v_sdev;
-
- b = position / _MIN_BLOCK_SIZE;
- off = position % _MIN_BLOCK_SIZE;
-
- while (bleft) {
- /* First read the whole block */
- r = dev_bio(VFS_DEV_READ, dev, FS_PROC_NR, buf,
- b * _MIN_BLOCK_SIZE, _MIN_BLOCK_SIZE);
-
- if (r != _MIN_BLOCK_SIZE)
- break;
-
- /* How many bytes to copy? */
- chunk = MIN(bleft, _MIN_BLOCK_SIZE - off);
-
- if (rw_flag == READING) {
- /* Copy a chunk from the buffer to user space. */
- r = sys_vircopy(FS_PROC_NR, D, (phys_bytes) (&buf[off]),
- usr, seg, (phys_bytes) m_in.buffer,
- (phys_bytes) chunk);
- }
- else {
- /* Copy a chunk from user space to the buffer. */
- r = sys_vircopy(usr, seg, (phys_bytes) m_in.buffer,
- FS_PROC_NR, D, (phys_bytes) (&buf[off]),
- (phys_bytes) chunk);
- }
-
- /* Write back if WRITE */
- if (rw_flag == WRITING) {
- r = dev_bio(DEV_WRITE, dev, FS_PROC_NR, buf,
- b * _MIN_BLOCK_SIZE, _MIN_BLOCK_SIZE);
-
- if (r != _MIN_BLOCK_SIZE)
- break;
- }
-
- bleft -= chunk;
- m_in.buffer += chunk;
-
- /* 0 offset in the next block */
- b++;
- off = 0;
- }
-
- cum_io = m_in.nbytes - bleft;
- position += cum_io;
- r = OK;
- }
-#endif
-
-
/*===========================================================================*
* do_getdents *
*===========================================================================*/
}
+/*===========================================================================*
+ * rw_pipe *
+ *===========================================================================*/
+PUBLIC int rw_pipe(rw_flag, usr, fd_nr, f, buf, req_size)
+int rw_flag; /* READING or WRITING */
+endpoint_t usr;
+int fd_nr;
+struct filp *f;
+char *buf;
+size_t req_size;
+{
+ int r, oflags, op, partial_pipe;
+ size_t size, cum_io, cum_io_incr;
+ struct filp *wf;
+ struct vnode *vp;
+ u64_t position, new_pos;
+
+ position = f->filp_pos;
+ oflags = f->filp_flags;
+
+ vp = f->filp_vno;
+
+#if 0
+ printf("vfs:rw_pipe: pipe %s, buf 0x%x, size %d\n",
+ rw_flag == READING ? "read" : "write", buf, req_size);
+ printf("vfs:rw_pipe: pipe vp 00x%x, dev/num 0x%x/%d size %d, pos 0x%x:%08x\n",
+ vp, vp->v_dev, vp->v_inode_nr,
+ vp->v_size, ex64hi(position), ex64lo(position));
+#endif
+
+ /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
+ cum_io = fp->fp_cum_io_partial;
+
+ op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
+
+ r = Xpipe_check(vp, rw_flag, oflags, req_size, position, 0);
+ if (r <= 0)
+ {
+ if (r == SUSPEND)
+ pipe_suspend(rw_flag, fd_nr, buf, req_size);
+ return(r);
+ }
+
+ size = r;
+ if (r < req_size)
+ partial_pipe = 1;
+ else
+ partial_pipe = 0;
+
+ /* Truncate read request at size. */
+ if((rw_flag == READING) &&
+ cmp64ul(add64ul(position, size), vp->v_size) > 0) {
+ /* Position always should fit in an off_t (LONG_MAX). */
+ off_t pos32;
+
+ assert(cmp64ul(position, LONG_MAX) <= 0);
+ pos32 = cv64ul(position);
+ assert(pos32 >= 0);
+ assert(pos32 <= LONG_MAX);
+ size = vp->v_size - pos32;
+ }
+ /* Issue request */
+ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, position,
+ rw_flag, usr, buf, size, &new_pos, &cum_io_incr);
+
+ if (r >= 0)
+ {
+ if (ex64hi(new_pos))
+ panic(__FILE__, "read_write: bad new pos", NO_NUM);
+
+ position = new_pos;
+ cum_io += cum_io_incr;
+ buf += cum_io_incr;
+ req_size -= cum_io_incr;
+ }
+
+ /* On write, update file size and access time. */
+ if (rw_flag == WRITING) {
+ if (cmp64ul(position, vp->v_size) > 0)
+ {
+ if (ex64hi(position) != 0)
+ {
+ panic(__FILE__,
+ "read_write: file size too big for v_size",
+ NO_NUM);
+ }
+ vp->v_size = ex64lo(position);
+ }
+ }
+ else {
+ if (cmp64ul(position, vp->v_size) >= 0) {
+ /* Reset pipe pointers */
+ vp->v_size = 0;
+ position = cvu64(0);
+ wf = find_filp(vp, W_BIT);
+ if (wf != NIL_FILP) wf->filp_pos = cvu64(0);
+ }
+ }
+
+ f->filp_pos = position;
+
+ if (r == OK) {
+ if (partial_pipe) {
+ /* partial write on pipe with */
+ /* O_NONBLOCK, return write count */
+ if (!(oflags & O_NONBLOCK)) {
+ /* partial write on pipe with req_size > PIPE_SIZE,
+ * non-atomic
+ */
+ fp->fp_cum_io_partial = cum_io;
+ pipe_suspend(rw_flag, fd_nr, buf, req_size);
+ return(SUSPEND);
+ }
+ }
+ fp->fp_cum_io_partial = 0;
+ if (rw_flag == WRITING)
+ vp->v_w_pipe_busy= FALSE;
+ return cum_io;
+ }
+
+ return r;
+}
+
+
-/* This file contains the wrapper functions for issueing a request
- * and receiving response from FS processes.
- * Each function builds a request message according to the request
- * parameter, calls the most low-level fs_sendrec and copies
- * back the response.
- * The low-level fs_sendrec handles the recovery mechanism from
- * a dead driver and reissues the request.
+/* This file deals with protection in the file system. It contains the code
+ * for four system calls that relate to protection.
*
- * Sep 2006 (Balazs Gerofi)
+ * The entry points into this file are
+ * do_chmod: perform the CHMOD and FCHMOD system calls
+ * do_chown: perform the CHOWN and FCHOWN system calls
+ * do_umask: perform the UMASK system call
+ * do_access: perform the ACCESS system call
+ *
+ * Changes for VFS:
+ * Jul 2006 (Balazs Gerofi)
*/
#include "fs.h"
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/keymap.h>
-#include <minix/const.h>
-#include <minix/endpoint.h>
-#include <minix/u64.h>
#include <unistd.h>
+#include <minix/callnr.h>
+#include "file.h"
+#include "fproc.h"
+#include "param.h"
#include <minix/vfsif.h>
-#include "fproc.h"
-#include "vmnt.h"
#include "vnode.h"
-#include "param.h"
+#include "vmnt.h"
-FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, message *reqm));
-#define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m))
/*===========================================================================*
- * req_getnode *
+ * do_chmod *
*===========================================================================*/
-PUBLIC int req_getnode_f(file, line, req, res)
-char *file;
-int line;
-node_req_t *req;
-node_details_t *res;
+PUBLIC int do_chmod()
{
- int r;
- message m;
-
- /* Fill in request message */
- m.m_type = REQ_GETNODE;
- m.REQ_INODE_NR = req->inode_nr;
+ struct filp *flp;
+ struct vnode *vp;
+ int r;
+ uid_t uid;
+ gid_t gid;
+ mode_t new_mode;
+
+ if (call_nr == CHMOD) {
+ /* Perform the chmod(name, mode) system call. */
+ if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+
+ /* Request lookup */
+ r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
+ if (r != OK) return r;
+ }
+ else if (call_nr == FCHMOD) {
+ if (!(flp = get_filp(m_in.m3_i1))) return err_code;
+ vp= flp->filp_vno;
+ dup_vnode(vp);
+ }
+ else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
- /* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+ uid= fp->fp_effuid;
+ gid= fp->fp_effgid;
- /* Fill in response structure */
- res->fs_e = m.m_source;
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
- res->dev = m.RES_DEV;
- res->uid = m.RES_UID;
- res->gid = m.RES_GID;
+ /* Only the owner or the super_user may change the mode of a file.
+ * No one may change the mode of a file on a read-only file system.
+ */
+ if (vp->v_uid != uid && uid != SU_UID)
+ r = EPERM;
+ else
+ r = read_only(vp);
- return OK;
-}
+ /* If error, return inode. */
+ if (r != OK) {
+ put_vnode(vp);
+ return(r);
+ }
+ /* Now make the change. Clear setgid bit if file is not in caller's grp */
+ if (uid != SU_UID && vp->v_gid != gid)
+ m_in.mode &= ~I_SET_GID_BIT;
-/*===========================================================================*
- * req_putnode *
- *===========================================================================*/
-PUBLIC int req_putnode(fs_e, inode_nr, count)
-int fs_e;
-ino_t inode_nr;
-int count;
-{
- message m;
+ /* Issue request */
+ r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode);
- /* Fill in request message */
- m.m_type = REQ_PUTNODE;
- m.REQ_INODE_NR = inode_nr;
- m.REQ_COUNT = count;
+ if (r == OK)
+ vp->v_mode = new_mode;
+ put_vnode(vp);
- /* Send/rec request */
- return fs_sendrec(fs_e, &m);
+ return OK;
}
/*===========================================================================*
- * req_open *
+ * do_chown *
*===========================================================================*/
-int req_open(req, res)
-open_req_t *req;
-node_details_t *res;
+PUBLIC int do_chown()
{
- int r;
- message m;
+ int inode_nr;
+ int fs_e;
+ struct filp *flp;
+ struct vnode *vp;
+ int r;
+ uid_t uid;
+ gid_t gid;
+ mode_t new_mode;
+
+ if (call_nr == CHOWN) {
+ /* Perform the chmod(name, mode) system call. */
+ if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+
+ /* Request lookup */
+ r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
+ if (r != OK) return r;
+ }
+ else if (call_nr == FCHOWN) {
+ if (!(flp = get_filp(m_in.m1_i1))) return err_code;
+ vp= flp->filp_vno;
+ dup_vnode(vp);
+ }
+ else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
+
+ uid= fp->fp_effuid;
+ gid= fp->fp_effgid;
+
+ r= OK;
+ if (uid == SU_UID) {
+ /* The super user can do anything. */
+ } else {
+ /* Regular users can only change groups of their own files. */
+ if (vp->v_uid != uid)
+ r = EPERM; /* File does not belong to the caller */
+ if (vp->v_uid != m_in.owner)
+ r = EPERM; /* no giving away */
+ if (gid != m_in.group)
+ r = EPERM; /* only change to the current gid */
+ }
+ if (r != OK) {
+ put_vnode(vp);
+ return r;
+ }
- /* Fill in request message */
- m.m_type = REQ_OPEN;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_FLAGS = req->oflags;
- m.REQ_MODE = req->omode;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->lastc;
- m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+ /* Issue request */
+ r = req_chown(vp->v_fs_e, vp->v_inode_nr, m_in.owner, m_in.group, &new_mode);
- /* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+ if(r == OK) {
+ vp->v_uid = m_in.owner;
+ vp->v_gid = m_in.group;
+ vp->v_mode = new_mode;
+ }
- /* Fill in response structure */
- res->fs_e = m.m_source;
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
- res->dev = m.RES_DEV;
- res->inode_index = m.RES_INODE_INDEX;
- /* For exec */
- res->uid = m.RES_UID;
- res->gid = m.RES_GID;
- res->ctime = m.RES_CTIME;
+ put_vnode(vp);
- return OK;
+ return r;
}
/*===========================================================================*
- * req_create *
+ * do_umask *
*===========================================================================*/
-int req_create(fs_e, inode_nr, omode, uid, gid, path, res)
-int fs_e;
-ino_t inode_nr;
-int omode;
-uid_t uid;
-gid_t gid;
-char *path;
-node_details_t *res;
+PUBLIC int do_umask()
{
- int r;
- message m;
-
- /* Fill in request message */
- m.m_type = REQ_CREATE;
- m.REQ_INODE_NR = inode_nr;
- m.REQ_MODE = omode;
- m.REQ_UID = uid;
- m.REQ_GID = gid;
- m.REQ_PATH = path;
- m.REQ_PATH_LEN = strlen(path) + 1;
-
- /* Send/rec request */
- if ((r = fs_sendrec(fs_e, &m)) != OK) return r;
-
- /* Fill in response structure */
- res->fs_e = m.m_source;
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
- res->dev = m.RES_DEV;
- res->inode_index = m.RES_INODE_INDEX;
- /* For exec */
- res->uid = m.RES_UID;
- res->gid = m.RES_GID;
- res->ctime = m.RES_CTIME;
+/* Perform the umask(co_mode) system call. */
+ register mode_t r;
- return OK;
+ r = ~fp->fp_umask; /* set 'r' to complement of old mask */
+ fp->fp_umask = ~(m_in.co_mode & RWX_MODES);
+ return(r); /* return complement of old mask */
}
/*===========================================================================*
- * req_readwrite *
+ * do_access *
*===========================================================================*/
-int req_readwrite(req, res)
-readwrite_req_t *req;
-readwrite_res_t *res;
+PUBLIC int do_access()
{
- int r;
- message m;
-
- if (ex64hi(req->pos) != 0)
- panic(__FILE__, "req_readwrite: pos too large", NO_NUM);
-
- /* Fill in request message */
- m.m_type = req->rw_flag == READING ? REQ_READ : REQ_WRITE;
- m.REQ_FD_INODE_NR = req->inode_nr;
- m.REQ_FD_WHO_E = req->user_e;
- m.REQ_FD_SEG = req->seg;
- m.REQ_FD_POS = ex64lo(req->pos);
- m.REQ_FD_NBYTES = req->num_of_bytes;
- m.REQ_FD_USER_ADDR = req->user_addr;
- m.REQ_FD_INODE_INDEX = req->inode_index;
+/* Perform the access(name, mode) system call. */
+ int r;
+ struct vnode *vp;
- /* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+ /* First check to see if the mode is correct. */
+ if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
+ return(EINVAL);
- /* Fill in response structure */
- res->new_pos = cvul64(m.RES_FD_POS);
- res->cum_io = m.RES_FD_CUM_IO;
+ if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
- return OK;
-}
+ /* Request lookup */
+ r = lookup_vp(0 /*flags*/, TRUE /*use_realuid*/, &vp);
+ if (r != OK) return r;
+ r= forbidden(vp, m_in.mode, 1 /*use_realuid*/);
+ put_vnode(vp);
+ return r;
+}
/*===========================================================================*
- * req_pipe *
+ * forbidden *
*===========================================================================*/
-PUBLIC int req_pipe(req, res)
-pipe_req_t *req;
-node_details_t *res;
+PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid)
{
- int r;
- message m;
+/* Given a pointer to an inode, 'rip', and the access desired, determine
+ * if the access is allowed, and if not why not. The routine looks up the
+ * caller's uid in the 'fproc' table. If access is allowed, OK is returned
+ * if it is forbidden, EACCES is returned.
+ */
- /* Fill in request message */
- m.m_type = REQ_PIPE;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
+ register struct super_block *sp;
+ register mode_t bits, perm_bits;
+ uid_t uid;
+ gid_t gid;
+ int r, shift, type;
- /* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+ if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1)
+ {
+ printf("forbidden: bad uid/gid in vnode: inode %d on dev 0x%x\n",
+ vp->v_inode_nr, vp->v_dev);
+ printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line);
+ return EACCES;
+ }
- /* Fill in response structure */
- res->fs_e = m.m_source;
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
- res->dev = m.RES_DEV;
- res->inode_index = m.RES_INODE_INDEX;
-
- return OK;
+ /* Isolate the relevant rwx bits from the mode. */
+ bits = vp->v_mode;
+ if (use_realuid)
+ {
+ uid= fp->fp_realuid;
+ gid= fp->fp_realgid;
+ }
+ else
+ {
+ uid= fp->fp_effuid;
+ gid= fp->fp_effgid;
+ }
+ if (uid == SU_UID) {
+ /* Grant read and write permission. Grant search permission for
+ * directories. Grant execute permission (for non-directories) if
+ * and only if one of the 'X' bits is set.
+ */
+ if ( (bits & I_TYPE) == I_DIRECTORY ||
+ bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
+ perm_bits = R_BIT | W_BIT | X_BIT;
+ else
+ perm_bits = R_BIT | W_BIT;
+ } else {
+ if (uid == vp->v_uid) shift = 6; /* owner */
+ else if (gid == vp->v_gid ) shift = 3; /* group */
+ else shift = 0; /* other */
+ perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
+ }
+
+ /* If access desired is not a subset of what is allowed, it is refused. */
+ r = OK;
+ if ((perm_bits | access_desired) != perm_bits) {
+ r = EACCES;
+ }
+
+ /* Check to see if someone is trying to write on a file system that is
+ * mounted read-only.
+ */
+ if (r == OK)
+ if (access_desired & W_BIT)
+ r = read_only(vp);
+
+ return(r);
}
/*===========================================================================*
- * req_clone_opcl *
+ * read_only *
*===========================================================================*/
-PUBLIC int req_clone_opcl(req, res)
-clone_opcl_req_t *req;
-node_details_t *res;
+PUBLIC int read_only(vp)
+struct vnode *vp; /* ptr to inode whose file sys is to be cked */
{
- int r;
- message m;
-
- /* Fill in request message */
- m.m_type = REQ_CLONE_OPCL;
- m.REQ_DEV = req->dev;
+/* Check to see if the file system on which the inode 'ip' resides is mounted
+ * read only. If so, return EROFS, else return OK.
+ */
+ register struct vmnt *mp;
- /* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
-
- /* Fill in response structure */
- res->fs_e = m.m_source;
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
- res->dev = m.RES_DEV;
- res->inode_index = m.RES_INODE_INDEX;
-
- return OK;
+ mp = vp->v_vmnt;
+ return(mp->m_flags ? EROFS : OK);
}
+/* This file contains the wrapper functions for issueing a request
+ * and receiving response from FS processes.
+ * Each function builds a request message according to the request
+ * parameter, calls the most low-level fs_sendrec and copies
+ * back the response.
+ * The low-level fs_sendrec handles the recovery mechanism from
+ * a dead driver and reissues the request.
+ *
+ * Sep 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/keymap.h>
+#include <minix/const.h>
+#include <minix/endpoint.h>
+#include <minix/u64.h>
+#include <unistd.h>
+
+#include <minix/vfsif.h>
+#include "fproc.h"
+#include "vmnt.h"
+#include "vnode.h"
+#include "param.h"
+
+FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, message *reqm));
+
+#define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m))
+
/*===========================================================================*
- * req_ftrunc *
+ * req_breadwrite *
*===========================================================================*/
-PUBLIC int req_ftrunc(req)
-ftrunc_req_t *req;
+PUBLIC int req_breadwrite(fs_e, user_e, dev, pos, num_of_bytes, user_addr,
+ rw_flag, new_posp, cum_iop)
+endpoint_t fs_e;
+endpoint_t user_e;
+dev_t dev;
+u64_t pos;
+unsigned int num_of_bytes;
+char *user_addr;
+int rw_flag;
+u64_t *new_posp;
+unsigned int *cum_iop;
{
+ int r;
+ cp_grant_id_t gid;
message m;
+ gid= cpf_grant_magic(fs_e, user_e, (vir_bytes)user_addr,
+ num_of_bytes, (rw_flag == READING ? CPF_WRITE : CPF_READ));
+ if (gid == -1)
+ panic(__FILE__, "req_breadwrite: cpf_grant_magic failed", NO_NUM);
+
/* Fill in request message */
- m.m_type = REQ_FTRUNC;
- m.REQ_FD_INODE_NR = req->inode_nr;
- m.REQ_FD_START = req->start;
- m.REQ_FD_END = req->end;
+ m.m_type = rw_flag == READING ? REQ_BREAD_S : REQ_BWRITE_S;
+ m.REQ_XFD_BDEV = dev;
+ m.REQ_XFD_GID = gid;
+ m.REQ_XFD_POS_LO = ex64lo(pos);
+ m.REQ_XFD_POS_HI = ex64hi(pos);
+ m.REQ_XFD_NBYTES = num_of_bytes;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
+
+ cpf_revoke(gid);
+
+ if (r != OK) return r;
+
+ /* Fill in response structure */
+ *new_posp = make64(m.RES_XFD_POS_LO, m.RES_XFD_POS_HI);
+ *cum_iop = m.RES_XFD_CUM_IO;
+
+ return OK;
}
/*===========================================================================*
- * req_chmod *
+ * req_chmod *
*===========================================================================*/
-PUBLIC int req_chmod(req, ch_mode)
-chmod_req_t *req;
-int *ch_mode;
+PUBLIC int req_chmod(fs_e, inode_nr, rmode, new_modep)
+int fs_e;
+ino_t inode_nr;
+mode_t rmode;
+mode_t *new_modep;
{
message m;
int r;
/* Fill in request message */
m.m_type = REQ_CHMOD;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_MODE = req->rmode;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_MODE = rmode;
+ m.REQ_UID = fp->fp_effuid;
+ m.REQ_GID = fp->fp_effgid;
/* Send/rec request */
- r = fs_sendrec(req->fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
/* Copy back actual mode. */
- if(ch_mode) *ch_mode = m.RES_MODE;
+ if (r == OK)
+ *new_modep = m.RES_MODE;
return r;
}
+/* Structure for REQ_CHOWN request */
+typedef struct chown_req {
+ int fs_e;
+ ino_t inode_nr;
+ uid_t uid;
+ gid_t gid;
+ uid_t newuid;
+ gid_t newgid;
+} chown_req_t;
+
+
/*===========================================================================*
* req_chown *
*===========================================================================*/
-PUBLIC int req_chown(req, ch_mode)
-chown_req_t *req;
-int *ch_mode;
+PUBLIC int req_chown(fs_e, inode_nr, newuid, newgid, new_modep)
+endpoint_t fs_e;
+ino_t inode_nr;
+uid_t newuid;
+gid_t newgid;
+mode_t *new_modep;
{
message m;
int r;
/* Fill in request message */
m.m_type = REQ_CHOWN;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_NEW_UID = req->newuid;
- m.REQ_NEW_GID = req->newgid;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_UID = fp->fp_effuid;
+ m.REQ_GID = fp->fp_effgid;
+ m.REQ_NEW_UID = newuid;
+ m.REQ_NEW_GID = newgid;
/* Send/rec request */
- r = fs_sendrec(req->fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
/* Return new mode to caller. */
- if(ch_mode) *ch_mode = m.RES_MODE;
+ *new_modep = m.RES_MODE;
return r;
}
/*===========================================================================*
- * req_access *
+ * req_create *
*===========================================================================*/
-PUBLIC int req_access(req)
-access_req_t *req;
+int req_create(fs_e, inode_nr, omode, uid, gid, path, res)
+int fs_e;
+ino_t inode_nr;
+int omode;
+uid_t uid;
+gid_t gid;
+char *path;
+node_details_t *res;
{
+ int r;
+ cp_grant_id_t grant_id;
+ size_t len;
message m;
- /* Fill in request message */
- m.m_type = REQ_ACCESS;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_MODE = req->amode;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
-
- /* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
-}
-
-
-/*===========================================================================*
- * req_mknod *
- *===========================================================================*/
-PUBLIC int req_mknod(req)
-mknod_req_t *req;
-{
- message m;
+ len= strlen(path) + 1;
+ grant_id= cpf_grant_direct(fs_e, (vir_bytes)path, len, CPF_READ);
+ if (grant_id == -1)
+ panic(__FILE__, "req_create: cpf_grant_direct failed", NO_NUM);
/* Fill in request message */
- m.m_type = REQ_MKNOD;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_MODE = req->rmode;
- m.REQ_DEV = req->dev;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->lastc;
- m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+ m.m_type = REQ_CREATE_S;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_MODE = omode;
+ m.REQ_UID = uid;
+ m.REQ_GID = gid;
+ m.REQ_GRANT = grant_id;
+ m.REQ_PATH_LEN = len;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
-}
+ r = fs_sendrec(fs_e, &m);
+ cpf_revoke(grant_id);
-/*===========================================================================*
- * req_mkdir *
- *===========================================================================*/
-PUBLIC int req_mkdir(req)
-mkdir_req_t *req;
-{
- message m;
+ if (r != OK) return r;
- /* Fill in request message */
- m.m_type = REQ_MKDIR;
- m.REQ_INODE_NR = req->d_inode_nr;
- m.REQ_MODE = req->rmode;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->lastc;
- m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+ /* Fill in response structure */
+ res->fs_e = m.m_source;
+ res->inode_nr = m.RES_INODE_NR;
+ res->fmode = m.RES_MODE;
+ res->fsize = m.RES_FILE_SIZE;
+ res->uid = m.RES_UID;
+ res->gid = m.RES_GID;
+ res->dev = m.RES_DEV;
+ res->inode_index = m.RES_INODE_INDEX;
- /* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ return OK;
}
-
/*===========================================================================*
- * req_inhibread *
+ * req_flush *
*===========================================================================*/
-PUBLIC int req_inhibread(req)
-node_req_t *req;
+PUBLIC int req_flush(fs_e, dev)
+endpoint_t fs_e;
+dev_t dev;
{
message m;
/* Fill in request message */
- m.m_type = REQ_INHIBREAD;
- m.REQ_INODE_NR = req->inode_nr;
-
+ m.m_type = REQ_FLUSH;
+ m.REQ_DEV = dev;
+
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ return fs_sendrec(fs_e, &m);
}
/*===========================================================================*
- * req_stat *
+ * req_fstatfs *
*===========================================================================*/
-PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos)
+PUBLIC int req_fstatfs(fs_e, inode_nr, who_e, buf)
int fs_e;
ino_t inode_nr;
int who_e;
char *buf;
-int pos;
{
- cp_grant_id_t gid;
int r;
+ cp_grant_id_t gid;
message m;
- struct stat sb;
- if (pos != 0)
- {
- gid= cpf_grant_direct(fs_e, (vir_bytes)&sb, sizeof(struct stat),
- CPF_WRITE);
- }
- else
- {
- gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct stat),
+ gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct statfs),
CPF_WRITE);
- }
if (gid < 0)
return gid;
/* Fill in request message */
- m.m_type = REQ_STAT;
+ m.m_type = REQ_FSTATFS;
m.REQ_INODE_NR = inode_nr;
m.REQ_GRANT = gid;
cpf_revoke(gid);
- if (r == OK && pos != 0)
- {
- sb.st_size -= pos;
- r= sys_vircopy(SELF, D, (vir_bytes)&sb, who_e, D, (vir_bytes)buf,
- sizeof(struct stat));
- }
-
return r;
}
/*===========================================================================*
- * req_fstatfs *
+ * req_ftrunc *
*===========================================================================*/
-PUBLIC int req_fstatfs(fs_e, inode_nr, who_e, buf)
-int fs_e;
+PUBLIC int req_ftrunc(fs_e, inode_nr, start, end)
+endpoint_t fs_e;
ino_t inode_nr;
-int who_e;
-char *buf;
+off_t start;
+off_t end;
{
- int r;
- cp_grant_id_t gid;
- message m;
+ message m;
- gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct statfs),
- CPF_WRITE);
- if (gid < 0)
- return gid;
+ /* Fill in request message */
+ m.m_type = REQ_FTRUNC;
+ m.REQ_FD_INODE_NR = inode_nr;
+ m.REQ_FD_START = start;
+ m.REQ_FD_END = end;
- /* Fill in request message */
- m.m_type = REQ_FSTATFS;
- m.REQ_INODE_NR = inode_nr;
- m.REQ_GRANT = gid;
+ /* Send/rec request */
+ return fs_sendrec(fs_e, &m);
+}
- /* Send/rec request */
- r= fs_sendrec(fs_e, &m);
- cpf_revoke(gid);
+/*===========================================================================*
+ * req_getdents *
+ *===========================================================================*/
+PUBLIC int req_getdents(fs_e, inode_nr, pos, gid, size, pos_change)
+endpoint_t fs_e;
+ino_t inode_nr;
+off_t pos;
+cp_grant_id_t gid;
+size_t size;
+off_t *pos_change;
+{
+ int r;
+ message m;
- return r;
+ m.m_type= REQ_GETDENTS;
+ m.REQ_GDE_INODE= inode_nr;
+ m.REQ_GDE_GRANT= gid;
+ m.REQ_GDE_SIZE= size;
+ m.REQ_GDE_POS= pos;
+
+ r = fs_sendrec(fs_e, &m);
+ *pos_change= m.RES_GDE_POS_CHANGE;
+ return r;
}
/*===========================================================================*
- * req_unlink *
+ * req_inhibread *
*===========================================================================*/
-PUBLIC int req_unlink(req)
-unlink_req_t *req;
+PUBLIC int req_inhibread(fs_e, inode_nr)
+endpoint_t fs_e;
+ino_t inode_nr;
{
message m;
/* Fill in request message */
- m.m_type = REQ_UNLINK;
- m.REQ_INODE_NR = req->d_inode_nr;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->lastc;
- m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+ m.m_type = REQ_INHIBREAD;
+ m.REQ_INODE_NR = inode_nr;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ return fs_sendrec(fs_e, &m);
}
/*===========================================================================*
- * req_rmdir *
+ * req_link *
*===========================================================================*/
-PUBLIC int req_rmdir(req)
-unlink_req_t *req;
+PUBLIC int req_link(fs_e, link_parent, lastc, linked_file)
+endpoint_t fs_e;
+ino_t link_parent;
+char *lastc;
+ino_t linked_file;
{
+ int r;
+ cp_grant_id_t gid;
+ size_t len;
message m;
+ len= strlen(lastc) + 1;
+ gid= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
+ if (gid == -1)
+ panic(__FILE__, "req_link: cpf_grant_direct failed", NO_NUM);
+
/* Fill in request message */
- m.m_type = REQ_RMDIR;
- m.REQ_INODE_NR = req->d_inode_nr;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->lastc;
- m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+ m.m_type = REQ_LINK_S;
+ m.REQ_LINKED_FILE = linked_file;
+ m.REQ_LINK_PARENT = link_parent;
+ m.REQ_GRANT = gid;
+ m.REQ_PATH_LEN = len;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
-}
+ r = fs_sendrec(fs_e, &m);
+ cpf_revoke(gid);
+
+ return r;
+}
+
/*===========================================================================*
- * req_utime *
+ * req_lookup *
*===========================================================================*/
-PUBLIC int req_utime(req)
-utime_req_t *req;
+PUBLIC int req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags, res)
+endpoint_t fs_e;
+size_t path_off;
+ino_t dir_ino;
+ino_t root_ino;
+uid_t uid;
+gid_t gid;
+int flags;
+lookup_res_t *res;
{
+ int r;
+ size_t len;
+ cp_grant_id_t grant_id;
message m;
+#if 0
+ printf("req_lookup_s: fs %d, ino %d, root %d, string (off %d) '%s'\n",
+ fs_e, dir_ino, root_ino, path_off, user_fullpath+path_off);
+#endif
+
+ grant_id= cpf_grant_direct(fs_e, (vir_bytes)user_fullpath,
+ sizeof(user_fullpath), CPF_READ|CPF_WRITE);
+ if (grant_id == -1)
+ panic(__FILE__, "req_lookup_s: cpf_grant_direct failed", NO_NUM);
+ len= strlen(user_fullpath+path_off) + 1;
+
/* Fill in request message */
- m.m_type = REQ_UTIME;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_ACTIME = req->actime;
- m.REQ_MODTIME = req->modtime;
+ m.m_type = REQ_LOOKUP_S;
+ m.REQ_L_GRANT = grant_id;
+ m.REQ_L_PATH_LEN = len;
+ m.REQ_L_PATH_SIZE = sizeof(user_fullpath);
+ m.REQ_L_PATH_OFF = path_off;
+ m.REQ_L_DIR_INO = dir_ino;
+ m.REQ_L_ROOT_INO = root_ino;
+ m.REQ_L_FLAGS = flags;
+ m.REQ_L_UID = uid;
+ m.REQ_L_GID = gid;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
+
+ cpf_revoke(grant_id);
+
+ /* Fill in response according to the return value */
+ res->fs_e = m.m_source;
+ switch (r) {
+ case OK:
+ res->inode_nr = m.RES_INODE_NR;
+ res->fmode = m.RES_MODE;
+ res->fsize = m.RES_FILE_SIZE;
+ res->dev = m.RES_DEV;
+ res->uid= m.RES_UID;
+ res->gid= m.RES_GID;
+ break;
+ case EENTERMOUNT:
+ res->inode_nr = m.RES_INODE_NR;
+ res->char_processed = m.RES_OFFSET;
+ res->symloop = m.RES_SYMLOOP2;
+ break;
+ case ELEAVEMOUNT:
+ res->char_processed = m.RES_OFFSET;
+ res->symloop = m.RES_SYMLOOP2;
+ break;
+ case ESYMLINK:
+ res->char_processed = m.RES_OFFSET;
+ res->symloop = m.RES_SYMLOOP2;
+ break;
+ default:
+ break;
+ }
+
+ return r;
}
/*===========================================================================*
- * req_stime *
+ * req_mkdir *
*===========================================================================*/
-PUBLIC int req_stime(fs_e, boottime)
-endpoint_t fs_e;
-time_t boottime;
+PUBLIC int req_mkdir(fs_e, inode_nr, lastc, uid, gid, dmode)
+endpoint_t fs_e;
+ino_t inode_nr;
+char *lastc;
+uid_t uid;
+gid_t gid;
+mode_t dmode;
{
+ int r;
+ cp_grant_id_t grant_id;
+ size_t len;
message m;
+ len= strlen(lastc) + 1;
+ grant_id= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
+ if (gid == -1)
+ panic(__FILE__, "req_mkdir: cpf_grant_direct failed", NO_NUM);
+
/* Fill in request message */
- m.m_type = REQ_STIME;
- m.REQ_BOOTTIME = boottime;
-
+ m.m_type = REQ_MKDIR_S;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_MODE = dmode;
+ m.REQ_UID = uid;
+ m.REQ_GID = gid;
+ m.REQ_GRANT = grant_id;
+ m.REQ_PATH_LEN = len;
+
/* Send/rec request */
- return fs_sendrec(fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
+
+ cpf_revoke(grant_id);
+
+ return r;
}
+/* Structure for REQ_MKNOD request */
+typedef struct mknod_req {
+ int fs_e;
+ ino_t inode_nr;
+ uid_t uid;
+ gid_t gid;
+ mode_t rmode;
+ dev_t dev;
+ char *lastc;
+} mknod_req_t;
+
+
+
/*===========================================================================*
- * req_sync *
+ * req_newnode *
*===========================================================================*/
-PUBLIC int req_sync(fs_e)
-endpoint_t fs_e;
+PUBLIC int req_newnode(fs_e, uid, gid, dmode, dev, res)
+endpoint_t fs_e;
+uid_t uid;
+gid_t gid;
+mode_t dmode;
+dev_t dev;
+struct node_details *res;
{
+ int r;
message m;
/* Fill in request message */
- m.m_type = REQ_SYNC;
-
+ m.m_type = REQ_NEWNODE;
+ m.REQ_MODE = dmode;
+ m.REQ_DEVx = dev;
+ m.REQ_UID = uid;
+ m.REQ_GID = gid;
+
/* Send/rec request */
- return fs_sendrec(fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
+
+ res->fs_e = m.m_source;
+ res->inode_nr = m.RES_INODE_NR;
+ res->fmode = m.RES_MODE;
+ res->fsize = m.RES_FILE_SIZE;
+ res->dev = m.RES_DEV;
+ res->uid= m.RES_UID;
+ res->gid= m.RES_GID;
+
+ return r;
}
/*===========================================================================*
- * req_link *
+ * req_mountpoint *
*===========================================================================*/
-PUBLIC int req_link(req)
-link_req_t *req;
+PUBLIC int req_mountpoint(fs_e, inode_nr)
+endpoint_t fs_e;
+ino_t inode_nr;
{
+ int r;
message m;
/* Fill in request message */
- m.m_type = REQ_LINK;
- m.REQ_LINKED_FILE = req->linked_file;
- m.REQ_LINK_PARENT = req->link_parent;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->lastc;
- m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+ m.m_type = REQ_MOUNTPOINT_S;
+ m.REQ_INODE_NR = inode_nr;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ return fs_sendrec(fs_e, &m);
}
-
+
/*===========================================================================*
- * req_slink *
+ * req_mknod *
*===========================================================================*/
-PUBLIC int req_slink(req)
-slink_req_t *req;
+PUBLIC int req_mknod(fs_e, inode_nr, lastc, uid, gid, dmode, dev)
+endpoint_t fs_e;
+ino_t inode_nr;
+char *lastc;
+uid_t uid;
+gid_t gid;
+mode_t dmode;
+dev_t dev;
{
+ int r;
+ size_t len;
+ cp_grant_id_t grant_id;
message m;
+ len= strlen(lastc) + 1;
+ grant_id= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
+ if (gid == -1)
+ panic(__FILE__, "req_mknod: cpf_grant_direct failed", NO_NUM);
+
/* Fill in request message */
- m.m_type = REQ_SLINK;
- m.REQ_INODE_NR = req->parent_dir;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->lastc;
- m.REQ_PATH_LEN = strlen(req->lastc) + 1;
- m.REQ_WHO_E = req->who_e;
- m.REQ_USER_ADDR = req->path_addr;
- m.REQ_SLENGTH = req->path_length;
+ m.m_type = REQ_MKNOD_S;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_MODE = dmode;
+ m.REQ_DEVx = dev;
+ m.REQ_UID = uid;
+ m.REQ_GID = gid;
+ m.REQ_GRANT = grant_id;
+ m.REQ_PATH_LEN = len;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
+
+ cpf_revoke(grant_id);
+
+ return r;
}
/*===========================================================================*
- * req_rdlink *
+ * req_putnode *
*===========================================================================*/
-PUBLIC int req_rdlink(req)
-rdlink_req_t *req;
+PUBLIC int req_putnode(fs_e, inode_nr, count)
+int fs_e;
+ino_t inode_nr;
+int count;
{
message m;
/* Fill in request message */
- m.m_type = REQ_RDLINK;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_WHO_E = req->who_e;
- m.REQ_USER_ADDR = req->path_buffer;
- m.REQ_SLENGTH = req->max_length;
+ m.m_type = REQ_PUTNODE;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_COUNT = count;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ return fs_sendrec(fs_e, &m);
}
/*===========================================================================*
- * req_rename *
+ * req_rdlink *
*===========================================================================*/
-PUBLIC int req_rename(req)
-rename_req_t *req;
+PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len)
+endpoint_t fs_e;
+ino_t inode_nr;
+endpoint_t who_e;
+vir_bytes buf;
+size_t len;
{
message m;
+ int r;
+ cp_grant_id_t gid;
+
+ gid= cpf_grant_magic(fs_e, who_e, buf, len, CPF_WRITE);
+ if (gid == -1)
+ panic(__FILE__, "req_rdlink: cpf_grant_magic failed", NO_NUM);
/* Fill in request message */
- m.m_type = REQ_RENAME;
- m.REQ_OLD_DIR = req->old_dir;
- m.REQ_NEW_DIR = req->new_dir;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_PATH = req->old_name;
- m.REQ_PATH_LEN = strlen(req->old_name) + 1;
- m.REQ_USER_ADDR = req->new_name;
- m.REQ_SLENGTH = strlen(req->new_name) + 1;
+ m.m_type = REQ_RDLINK_S;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_GRANT = gid;
+ m.REQ_SLENGTH = len;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ r= fs_sendrec(fs_e, &m);
+
+ cpf_revoke(gid);
+
+ return r;
}
/*===========================================================================*
- * req_mountpoint *
+ * req_readsuper *
*===========================================================================*/
-PUBLIC int req_mountpoint(req, res)
-mountpoint_req_t *req;
-node_details_t *res;
+PUBLIC int req_readsuper(fs_e, label, dev, readonly, isroot, res_nodep)
+endpoint_t fs_e;
+char *label;
+dev_t dev;
+int readonly;
+int isroot;
+struct node_details *res_nodep;
{
int r;
+ cp_grant_id_t gid;
+ size_t len;
message m;
+ len= strlen(label)+1;
+ gid= cpf_grant_direct(fs_e, (vir_bytes)label, len, CPF_READ);
+ if (gid == -1)
+ panic(__FILE__, "req_req_readsuper: cpf_grant_direct failed", NO_NUM);
+
/* Fill in request message */
- m.m_type = REQ_MOUNTPOINT;
- m.REQ_INODE_NR = req->inode_nr;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
+ m.m_type = REQ_READSUPER_S;
+ m.REQ_READONLY = readonly;
+ m.REQ_GRANT2 = gid;
+ m.REQ_DEV = dev;
+ m.REQ_ISROOT = isroot;
+ m.REQ_PATH_LEN = len;
/* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+ if ((r = fs_sendrec(fs_e, &m)) != OK) return r;
/* Fill in response structure */
- res->fs_e = m.m_source;
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
+ res_nodep->fs_e = m.m_source;
+ res_nodep->inode_nr = m.RES_INODE_NR;
+ res_nodep->fmode = m.RES_MODE;
+ res_nodep->fsize = m.RES_FILE_SIZE;
+ res_nodep->uid = m.RES_UID;
+ res_nodep->gid = m.RES_GID;
return OK;
}
+/* Structure for REQ_READ and REQ_WRITE request */
+typedef struct readwrite_req {
+ int rw_flag;
+ endpoint_t fs_e;
+ endpoint_t user_e;
+ ino_t inode_nr;
+ unsigned short inode_index;
+ int seg;
+ u64_t pos;
+ unsigned int num_of_bytes;
+ char *user_addr;
+} readwrite_req_t;
+
/*===========================================================================*
- * req_readsuper *
+ * req_readwrite *
*===========================================================================*/
-PUBLIC int req_readsuper(req, res)
-readsuper_req_t *req;
-readsuper_res_t *res;
+PUBLIC int req_readwrite(fs_e, inode_nr, inode_index, pos, rw_flag, user_e,
+ user_addr, num_of_bytes, new_posp, cum_iop)
+endpoint_t fs_e;
+ino_t inode_nr;
+unsigned short inode_index;
+u64_t pos;
+int rw_flag;
+endpoint_t user_e;
+char *user_addr;
+unsigned int num_of_bytes;
+u64_t *new_posp;
+unsigned int *cum_iop;
{
int r;
+ cp_grant_id_t gid;
message m;
- /* Fill in request message */
- m.m_type = REQ_READSUPER;
- m.REQ_READONLY = req->readonly;
- m.REQ_BOOTTIME = req->boottime;
- m.REQ_DRIVER_E = req->driver_e;
- m.REQ_DEV = req->dev;
- m.REQ_SLINK_STORAGE = req->slink_storage;
- m.REQ_ISROOT = req->isroot;
+ if (ex64hi(pos) != 0)
+ panic(__FILE__, "req_readwrite: pos too large", NO_NUM);
+
+ gid= cpf_grant_magic(fs_e, user_e, (vir_bytes)user_addr,
+ num_of_bytes, (rw_flag == READING ? CPF_WRITE : CPF_READ));
+ if (gid == -1)
+ panic(__FILE__, "req_readwrite: cpf_grant_magic failed", NO_NUM);
+ /* Fill in request message */
+ m.m_type = rw_flag == READING ? REQ_READ_S : REQ_WRITE_S;
+ m.REQ_FD_INODE_NR = inode_nr;
+ m.REQ_FD_GID = gid;
+ m.REQ_FD_POS = ex64lo(pos);
+ m.REQ_FD_NBYTES = num_of_bytes;
+ m.REQ_FD_INODE_INDEX = inode_index;
+
/* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+ r = fs_sendrec(fs_e, &m);
+
+ cpf_revoke(gid);
+
+ if (r != OK) return r;
/* Fill in response structure */
- res->fs_e = m.m_source;
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
- res->blocksize = m.RES_BLOCKSIZE;
- res->maxsize = m.RES_MAXSIZE;
+ *new_posp = cvul64(m.RES_FD_POS);
+ *cum_iop = m.RES_FD_CUM_IO;
return OK;
}
/*===========================================================================*
- * req_unmount *
+ * req_rename *
*===========================================================================*/
-PUBLIC int req_unmount(fs_e)
-endpoint_t fs_e;
+PUBLIC int req_rename(fs_e, old_dir, old_name, new_dir, new_name)
+endpoint_t fs_e;
+ino_t old_dir;
+char *old_name;
+ino_t new_dir;
+char *new_name;
{
+ int r;
+ cp_grant_id_t gid_old, gid_new;
+ size_t len_old, len_new;
message m;
+ len_old= strlen(old_name) + 1;
+ gid_old= cpf_grant_direct(fs_e, (vir_bytes)old_name, len_old,
+ CPF_READ);
+ if (gid_old == -1)
+ panic(__FILE__, "req_rename: cpf_grant_direct failed", NO_NUM);
+ len_new= strlen(new_name) + 1;
+ gid_new= cpf_grant_direct(fs_e, (vir_bytes)new_name, len_new,
+ CPF_READ);
+ if (gid_new == -1)
+ panic(__FILE__, "req_rename: cpf_grant_direct failed", NO_NUM);
+
/* Fill in request message */
- m.m_type = REQ_UNMOUNT;
-
+ m.m_type = REQ_RENAME_S;
+ m.REQ_REN_OLD_DIR = old_dir;
+ m.REQ_REN_NEW_DIR = new_dir;
+ m.REQ_REN_GRANT_OLD = gid_old;
+ m.REQ_REN_LEN_OLD = len_old;
+ m.REQ_REN_GRANT_NEW = gid_new;
+ m.REQ_REN_LEN_NEW = len_new;
+
/* Send/rec request */
- return fs_sendrec(fs_e, &m);
+ r = fs_sendrec(fs_e, &m);
+
+ cpf_revoke(gid_old);
+ cpf_revoke(gid_new);
+
+ return r;
}
/*===========================================================================*
- * req_trunc *
+ * req_rmdir *
*===========================================================================*/
-PUBLIC int req_trunc(req)
-trunc_req_t *req;
+PUBLIC int req_rmdir(fs_e, inode_nr, lastc)
+endpoint_t fs_e;
+ino_t inode_nr;
+char *lastc;
{
+ int r;
+ cp_grant_id_t gid;
+ size_t len;
message m;
+ len= strlen(lastc) + 1;
+ gid= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
+ if (gid == -1)
+ panic(__FILE__, "req_rmdir: cpf_grant_direct failed", NO_NUM);
+
/* Fill in request message */
- m.m_type = REQ_TRUNC;
- m.REQ_FD_INODE_NR = req->inode_nr;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_LENGTH = req->length;
+ m.m_type = REQ_RMDIR_S;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_GRANT = gid;
+ m.REQ_PATH_LEN = len;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
-}
+ r = fs_sendrec(fs_e, &m);
+ cpf_revoke(gid);
+
+ return r;
+}
/*===========================================================================*
- * req_newdriver *
+ * req_slink *
*===========================================================================*/
-PUBLIC int req_newdriver(fs_e, dev, driver_e)
+PUBLIC int req_slink(fs_e, inode_nr, lastc, who_e, path_addr, path_length,
+ uid, gid)
endpoint_t fs_e;
-Dev_t dev;
-endpoint_t driver_e;
+ino_t inode_nr;
+char *lastc;
+endpoint_t who_e;
+char *path_addr;
+unsigned short path_length;
+uid_t uid;
+gid_t gid;
{
-/* Note: this is the only request function that doesn't use the
- * fs_sendrec internal routine, since we want to avoid the dead
- * driver recovery mechanism here. This function is actually called
- * during the recovery.
- */
- message m;
int r;
+ size_t len;
+ cp_grant_id_t gid_name, gid_buf;
+ message m;
+
+ len= strlen(lastc) + 1;
+ gid_name= cpf_grant_direct(fs_e, (vir_bytes)lastc, len,
+ CPF_READ);
+ if (gid_name == -1)
+ panic(__FILE__, "req_slink: cpf_grant_direct failed", NO_NUM);
+
+ gid_buf= cpf_grant_magic(fs_e, who_e, (vir_bytes)path_addr,
+ path_length, CPF_READ);
+ if (gid_buf == -1)
+ {
+ cpf_revoke(gid_buf);
+ panic(__FILE__, "req_slink: cpf_grant_magic failed", NO_NUM);
+ }
/* Fill in request message */
- m.m_type = REQ_NEW_DRIVER;
- m.REQ_DEV = dev;
- m.REQ_DRIVER_E = driver_e;
+ m.m_type = REQ_SLINK_S;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_UID = uid;
+ m.REQ_GID = gid;
+ m.REQ_GRANT = gid_name;
+ m.REQ_PATH_LEN = len;
+ m.REQ_GRANT2 = gid_buf;
+ m.REQ_SLENGTH = path_length;
- /* Issue request */
- if ((r = sendrec(fs_e, &m)) != OK) {
- printf("VFSreq_newdriver: error sending message to %d: %d\n", fs_e, r);
- return r;
- }
+ /* Send/rec request */
+ r = fs_sendrec(fs_e, &m);
- return OK;
+ cpf_revoke(gid_name);
+ cpf_revoke(gid_buf);
+
+ return r;
}
/*===========================================================================*
- * req_lookup *
+ * req_stat *
*===========================================================================*/
-PUBLIC int req_lookup(req, res)
-lookup_req_t *req;
-lookup_res_t *res;
+PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos)
+int fs_e;
+ino_t inode_nr;
+int who_e;
+char *buf;
+int pos;
{
- int r;
- message m;
+ cp_grant_id_t gid;
+ int r;
+ message m;
+ struct stat sb;
- /* Fill in request message */
- m.m_type = REQ_LOOKUP;
- m.REQ_PATH = req->path;
- m.REQ_PATH_LEN = strlen(req->path) + 1;
- m.REQ_USER_ADDR = req->lastc;
- m.REQ_FLAGS = req->flags;
-
- m.REQ_INODE_NR = req->start_dir;
- m.REQ_CHROOT_NR = req->root_dir;
- m.REQ_UID = req->uid;
- m.REQ_GID = req->gid;
- m.REQ_SYMLOOP = req->symloop;
+ if (pos != 0)
+ {
+ gid= cpf_grant_direct(fs_e, (vir_bytes)&sb, sizeof(struct stat),
+ CPF_WRITE);
+ }
+ else
+ {
+ gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct stat),
+ CPF_WRITE);
+ }
+ if (gid < 0)
+ return gid;
- /* Send/rec request */
- r = fs_sendrec(req->fs_e, &m);
+ /* Fill in request message */
+ m.m_type = REQ_STAT;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_GRANT = gid;
- /* Fill in response according to the return value */
- res->fs_e = m.m_source;
- switch (r) {
- case OK:
- default:
- res->inode_nr = m.RES_INODE_NR;
- res->fmode = m.RES_MODE;
- res->fsize = m.RES_FILE_SIZE;
- res->dev = m.RES_DEV;
- res->uid= m.RES_UID;
- res->gid= m.RES_GID;
- res->char_processed = m.RES_OFFSET; /* For ENOENT */
- break;
- case EENTERMOUNT:
- res->inode_nr = m.RES_INODE_NR;
- case ELEAVEMOUNT:
- case ESYMLINK:
- res->char_processed = m.RES_OFFSET;
- res->symloop = m.RES_SYMLOOP;
- break;
- }
+ /* Send/rec request */
+ r= fs_sendrec(fs_e, &m);
- return r;
+ cpf_revoke(gid);
+
+ if (r == OK && pos != 0)
+ {
+ sb.st_size -= pos;
+ r= sys_vircopy(SELF, D, (vir_bytes)&sb, who_e, D, (vir_bytes)buf,
+ sizeof(struct stat));
+ }
+
+ return r;
}
/*===========================================================================*
- * req_breadwrite *
+ * req_sync *
*===========================================================================*/
-int req_breadwrite(req, res)
-breadwrite_req_t *req;
-readwrite_res_t *res;
+PUBLIC int req_sync(fs_e)
+endpoint_t fs_e;
{
- int r;
message m;
/* Fill in request message */
- m.m_type = req->rw_flag == READING ? REQ_BREAD : REQ_BWRITE;
- m.REQ_XFD_BDEV = req->dev;
- m.REQ_XFD_BLOCK_SIZE = req->blocksize;
- m.REQ_XFD_WHO_E = req->user_e;
- m.REQ_XFD_POS_LO = ex64lo(req->pos);
- m.REQ_XFD_POS_HI = ex64hi(req->pos);
- m.REQ_XFD_NBYTES = req->num_of_bytes;
- m.REQ_XFD_USER_ADDR = req->user_addr;
+ m.m_type = REQ_SYNC;
/* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+ return fs_sendrec(fs_e, &m);
+}
- /* Fill in response structure */
- res->new_pos = make64(m.RES_XFD_POS_LO, m.RES_XFD_POS_HI);
- res->cum_io = m.RES_XFD_CUM_IO;
+/* Structure for REQ_UNLINK request */
+typedef struct unlink_req {
+ int fs_e;
+ ino_t d_inode_nr;
+ uid_t uid;
+ gid_t gid;
+ char *lastc;
+} unlink_req_t;
- return OK;
-}
-PUBLIC int req_getdents(fs_e, inode_nr, pos, gid, size, pos_change)
+/*===========================================================================*
+ * req_unlink *
+ *===========================================================================*/
+PUBLIC int req_unlink(fs_e, inode_nr, lastc)
endpoint_t fs_e;
ino_t inode_nr;
-off_t pos;
-cp_grant_id_t gid;
-size_t size;
-off_t *pos_change;
+char *lastc;
{
- int r;
- message m;
+ cp_grant_id_t gid;
+ size_t len;
+ int r;
+ message m;
- m.m_type= REQ_GETDENTS;
- m.REQ_GDE_INODE= inode_nr;
- m.REQ_GDE_GRANT= gid;
- m.REQ_GDE_SIZE= size;
- m.REQ_GDE_POS= pos;
+ len= strlen(lastc) + 1;
+ gid= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
+ if (gid == -1)
+ panic(__FILE__, "req_unlink: cpf_grant_direct failed", NO_NUM);
- r = fs_sendrec(fs_e, &m);
- *pos_change= m.RES_GDE_POS_CHANGE;
- return r;
+ /* Fill in request message */
+ m.m_type = REQ_UNLINK_S;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_GRANT = gid;
+ m.REQ_PATH_LEN = len;
+
+ /* Send/rec request */
+ r = fs_sendrec(fs_e, &m);
+
+ cpf_revoke(gid);
+
+ return r;
}
/*===========================================================================*
- * req_flush *
+ * req_unmount *
*===========================================================================*/
-PUBLIC int req_flush(fs_e, dev)
+PUBLIC int req_unmount(fs_e)
endpoint_t fs_e;
-dev_t dev;
{
message m;
/* Fill in request message */
- m.m_type = REQ_FLUSH;
- m.REQ_DEV = dev;
+ m.m_type = REQ_UNMOUNT;
/* Send/rec request */
return fs_sendrec(fs_e, &m);
}
-#if 0
-/* Wrapper pattern: */
/*===========================================================================*
- * req_ *
+ * req_utime *
*===========================================================================*/
-PUBLIC int req_(req, res)
-_req_t *req;
-_t *res;
+PUBLIC int req_utime(fs_e, inode_nr, actime, modtime)
+endpoint_t fs_e;
+ino_t inode_nr;
+time_t actime;
+time_t modtime;
{
- int r;
message m;
/* Fill in request message */
-
+ m.m_type = REQ_UTIME;
+ m.REQ_INODE_NR = inode_nr;
+ m.REQ_ACTIME = actime;
+ m.REQ_MODTIME = modtime;
/* Send/rec request */
- if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
-
- /* Fill in response structure */
+ return fs_sendrec(fs_e, &m);
+}
+
+
+/*===========================================================================*
+ * req_newdriver *
+ *===========================================================================*/
+PUBLIC int req_newdriver(fs_e, dev, driver_e)
+endpoint_t fs_e;
+Dev_t dev;
+endpoint_t driver_e;
+{
+/* Note: this is the only request function that doesn't use the
+ * fs_sendrec internal routine, since we want to avoid the dead
+ * driver recovery mechanism here. This function is actually called
+ * during the recovery.
+ */
+ message m;
+ int r;
+
+ /* Fill in request message */
+ m.m_type = REQ_NEW_DRIVER;
+ m.REQ_DEV = dev;
+ m.REQ_DRIVER_E = driver_e;
+ /* Issue request */
+ if ((r = sendrec(fs_e, &m)) != OK) {
+ printf("VFSreq_newdriver: error sending message to %d: %d\n", fs_e, r);
+ return r;
+ }
return OK;
}
-#endif
+
message origm, m;
struct vmnt *vmp;
+ if (fs_e == PM_PROC_NR)
+ {
+ printf("from %s, %d\n", file, line);
+ panic(__FILE__, "talking to PM", NO_NUM);
+ }
+
/* Make a copy of the request so that we can load it back in
* case of a dead driver */
origm = *reqm;
#include <sys/types.h>
-/* Structure for REQ_GETNODE and REQ_PUTNODE requests */
-typedef struct node_req {
- endpoint_t fs_e;
- ino_t inode_nr;
-} node_req_t;
-
-
/* Structure for response that contains inode details */
typedef struct node_details {
endpoint_t fs_e;
ino_t inode_nr;
mode_t fmode;
off_t fsize;
+ uid_t uid;
+ gid_t gid;
+
+ /* For faster access */
unsigned short inode_index;
+
/* For char/block special files */
dev_t dev;
-
- /* Fields used by the exec() syscall */
- uid_t uid;
- gid_t gid;
- time_t ctime;
} node_details_t;
} open_req_t;
-/* Structure for REQ_READ and REQ_WRITE request */
-typedef struct readwrite_req {
- int rw_flag;
- endpoint_t fs_e;
- endpoint_t user_e;
- ino_t inode_nr;
- unsigned short inode_index;
- int seg;
- u64_t pos;
- unsigned int num_of_bytes;
- char *user_addr;
-} readwrite_req_t;
-
-
-/* Structure for response of REQ_READ and REQ_WRITE */
-typedef struct readwrite_res {
- u64_t new_pos;
- unsigned int cum_io;
-} readwrite_res_t;
-
-
-/* Structure for REQ_PIPE request */
-typedef struct pipe_req {
- int fs_e;
- uid_t uid;
- gid_t gid;
-} pipe_req_t;
-
-
/* Structure for REQ_CLONE_OPCL request */
typedef struct clone_opcl_req {
int fs_e;
} clone_opcl_req_t;
-/* Structure for REQ_FTRUNC request */
-typedef struct ftrunc_req {
- int fs_e;
- ino_t inode_nr;
- off_t start;
- off_t end;
-} ftrunc_req_t;
-
-
-/* Structure for REQ_CHOWN request */
-typedef struct chown_req {
- int fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
- uid_t newuid;
- gid_t newgid;
-} chown_req_t;
-
-
-/* Structure for REQ_CHMOD request */
-typedef struct chmod_req {
- int fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
- mode_t rmode;
-} chmod_req_t;
-
-
-/* Structure for REQ_ACCESS request */
-typedef struct access_req {
- int fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
- mode_t amode;
-} access_req_t;
-
-
-/* Structure for REQ_MKNOD request */
-typedef struct mknod_req {
- int fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
- mode_t rmode;
- dev_t dev;
- char *lastc;
-} mknod_req_t;
-
-
-/* Structure for REQ_MKDIR request */
-typedef struct mkdir_req {
- int fs_e;
- ino_t d_inode_nr;
- uid_t uid;
- gid_t gid;
- mode_t rmode;
- char *lastc;
-} mkdir_req_t;
-
-
-/* Structure for REQ_UNLINK request */
-typedef struct unlink_req {
- int fs_e;
- ino_t d_inode_nr;
- uid_t uid;
- gid_t gid;
- char *lastc;
-} unlink_req_t;
-
-
-/* Structure for REQ_UTIME request */
-typedef struct utime_req {
- int fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
- time_t actime;
- time_t modtime;
-} utime_req_t;
-
-
-/* Structure for REQ_LINK request */
-typedef struct link_req {
- endpoint_t fs_e;
- ino_t linked_file;
- ino_t link_parent;
- uid_t uid;
- gid_t gid;
- char *lastc;
-} link_req_t;
-
-
-/* Structure for REQ_SLINK request */
-typedef struct slink_req {
- endpoint_t fs_e;
- ino_t parent_dir;
- uid_t uid;
- gid_t gid;
- char *lastc;
- endpoint_t who_e;
- char *path_addr;
- unsigned short path_length;
-} slink_req_t;
-
-
-/* Structure for REQ_RDLINK request */
-typedef struct rdlink_req {
- endpoint_t fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
- endpoint_t who_e;
- char *path_buffer;
- unsigned short max_length;
-} rdlink_req_t;
-
-
-/* Structure for REQ_RENAME request */
-typedef struct rename_req {
- endpoint_t fs_e;
- ino_t old_dir;
- ino_t new_dir;
- uid_t uid;
- gid_t gid;
- char *old_name;
- char *new_name;
-} rename_req_t;
-
-
-/* Structure for REQ_MOUNTPOINT request */
-typedef struct mountpoint_req {
- endpoint_t fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
-} mountpoint_req_t;
-
-
/* Structure for REQ_READSUPER request */
typedef struct readsuper_req {
endpoint_t fs_e;
} readsuper_res_t;
-/* Structure for REQ_TRUNC request */
-typedef struct trunc_req {
- endpoint_t fs_e;
- ino_t inode_nr;
- uid_t uid;
- gid_t gid;
- off_t length;
-} trunc_req_t;
-
-
/* Structure for REQ_LOOKUP request */
typedef struct lookup_req {
/* Fields filled in by the caller */
} lookup_res_t;
-/* Structure for REQ_BREAD and REQ_BWRITE request (block spec files) */
-typedef struct breadwrite_req {
- int rw_flag;
- short blocksize;
- endpoint_t fs_e;
- endpoint_t user_e;
- endpoint_t driver_e;
- dev_t dev;
- u64_t pos;
- unsigned int num_of_bytes;
- char *user_addr;
-} breadwrite_req_t;
-
-
-
/* Structure for REQ_ request */
return ENOTDIR;
/* Issue request and handle error */
- r = forbidden(rfilp->filp_vno, X_BIT);
+ r = forbidden(rfilp->filp_vno, X_BIT, 0 /*!use_realuid*/);
if (r != OK) return r;
rfilp->filp_vno->v_ref_count++; /* change_into expects a reference */
{
/* Do the actual work for chdir() and chroot(). */
struct vnode *vp;
- struct lookup_req lookup_req;
int r;
if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup_vp(&lookup_req, &vp)) != OK) return r;
+ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* Is it a dir? */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
}
/* Access check */
- r = forbidden(vp, X_BIT);
+ r = forbidden(vp, X_BIT, 0 /*!use_realuid*/);
if (r != OK) {
put_vnode(vp);
return r;
PUBLIC int do_stat()
{
/* Perform the stat(name, buf) system call. */
- struct node_details res;
- struct lookup_req lookup_req;
int r;
-
+ struct vnode *vp;
+
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK)
+ return r;
/* Issue request */
- return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0);
+ r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
+ put_vnode(vp);
+ return r;
}
/*===========================================================================*
- * do_lstat *
+ * do_lstat *
*===========================================================================*/
PUBLIC int do_lstat()
{
/* Perform the lstat(name, buf) system call. */
- struct node_details res;
struct lookup_req lookup_req;
+ struct vnode *vp;
int r;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
lookup_req.flags = EAT_PATH_OPAQUE;
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp)) != OK)
+ return r;
/* Issue request */
- return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0);
+ r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
+
+ put_vnode(vp);
+
+ return r;
}
* A super_block slot is free if s_dev == NO_DEV.
*/
+#if 0
EXTERN struct super_block {
ino_t s_ninodes; /* # usable inodes on the minor device */
zone1_t s_nzones; /* total device size, including bit maps etc */
bit_t s_isearch; /* inodes below this bit number are in use */
bit_t s_zsearch; /* all zones below this bit number are in use*/
} super_block[NR_SUPERS];
+#endif
#define NIL_SUPER (struct super_block *) 0
#define IMAP 0 /* operating on the inode bit map */
do_umount, /* 22 = umount */
no_sys, /* 23 = (setuid) */
no_sys, /* 24 = getuid */
- do_stime, /* 25 = stime */
+ no_sys, /* 25 = (stime) */
no_sys, /* 26 = ptrace */
no_sys, /* 27 = alarm */
do_fstat, /* 28 = fstat */
#include "file.h"
#include "fproc.h"
#include "param.h"
+#include "vnode.h"
#include <minix/vfsif.h>
#include "vmnt.h"
{
/* Perform the utime(name, timep) system call. */
register int len;
- struct utime_req req;
- struct lookup_req lookup_req;
- struct node_details res;
int r;
+ uid_t uid;
+ time_t actime, modtime;
+ struct vnode *vp;
/* Adjust for case of 'timep' being NULL;
* utime_strlen then holds the actual size: strlen(name)+1.
if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
- /* Fill in lookup request fields */
- lookup_req.path = user_fullpath;
- lookup_req.lastc = NULL;
- lookup_req.flags = EAT_PATH;
-
/* Request lookup */
- if ((r = lookup(&lookup_req, &res)) != OK) return r;
+ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* Fill in request fields.*/
if (m_in.utime_length == 0) {
- req.actime = 0;
- req.modtime = clock_time();
+ actime = modtime = clock_time();
} else {
- req.actime = m_in.utime_actime;
- req.modtime = m_in.utime_modtime;
+ actime = m_in.utime_actime;
+ modtime = m_in.utime_modtime;
}
- req.fs_e = res.fs_e;
- req.inode_nr = res.inode_nr;
- req.uid = fp->fp_effuid;
- req.gid = fp->fp_effgid;
-
- /* Issue request */
- return req_utime(&req);
-}
+ uid= fp->fp_effuid;
-/*===========================================================================*
- * do_stime *
- *===========================================================================*/
-PUBLIC int do_stime()
-{
- struct vmnt *vmp;
- /* Perform the stime(tp) system call. */
- boottime = (long) m_in.pm_stime;
-
- /* Send new time for all FS processes */
- for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
- if (vmp->m_fs_e) req_stime(vmp->m_fs_e, boottime);
+ r= OK;
+ if (vp->v_uid != uid && uid != SU_UID) r = EPERM;
+ if (m_in.utime_length == 0 && r != OK)
+ {
+ /* With a null times pointer, updating the times (to the current time)
+ * is allow if the object is writable.
+ */
+ r = forbidden(vp, W_BIT, 0 /*!use_realuid*/);
}
- return OK;
+ if (r != OK)
+ {
+ put_vnode(vp);
+ return r;
+ }
+
+ /* Issue request */
+ r= req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
+ put_vnode(vp);
+ return r;
}
time_t d2_ctime; /* when was inode data last changed */
zone_t d2_zone[V2_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
} d2_inode;
+
+#if 1
+extern struct dmap {
+ int _PROTOTYPE ((*dmap_opcl), (int, Dev_t, int, int) );
+ int _PROTOTYPE ((*dmap_io), (int, message *) );
+ int dmap_driver;
+ int dmap_flags;
+} dmap[];
+#endif
+
* rate and that such things as leap seconds do not exist.
*/
- register int k;
+ register int r;
clock_t uptime;
+ time_t boottime;
+
+ r= getuptime2(&uptime, &boottime);
+ if (r != OK)
+ panic(__FILE__,"clock_time err", r);
- if ( (k=getuptime(&uptime)) != OK) panic(__FILE__,"clock_time err", k);
return( (time_t) (boottime + (uptime/HZ)));
}
dev_t m_dev; /* device number */
int m_driver_e; /* device driver process' kernel endpoint */
int m_flags; /* mount flags */
- int m_max_file_size; /* maximum file size on partition */
- unsigned short m_block_size; /* block size */
struct vnode *m_mounted_on; /* the vnode on which the partition is mounted */
struct vnode *m_root_node; /* root vnode */
} vmnt[NR_MNTS];
#include <minix/vfsif.h>
-/*===========================================================================*
- * get_vnode *
- *===========================================================================*/
-PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr)
-{
-/* get_vnode() is called to get the details of the specified inode.
- * Note that inode's usage counter in the FS is supposed to be incremented.
- */
- struct vnode *vp, *vp2;
- struct vmnt *vmp;
-
- /* Request & response structures */
- struct node_req req;
- struct node_details res;
-
- /* XXX remove this when debugging is complete */
- if (find_vnode(fs_e, inode_nr) != NULL)
- panic(__FILE__, "get_vnode: vnode already present", NO_NUM);
-
- /* Check whether a free vnode is avaliable */
- if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
- printf("VFSget_vnode: no vnode available\n");
- return NIL_VNODE;
- }
-
- /* Fill req struct */
- req.inode_nr = inode_nr;
- req.fs_e = fs_e;
-
- /* Send request to FS */
- if (req_getnode(&req, &res) != OK) {
- printf("VFSget_vnode: couldn't find vnode\n");
- return NIL_VNODE;
- }
-
- /* Fill in the free vnode's fields and return it */
- vp->v_fs_e = res.fs_e;
- vp->v_inode_nr = res.inode_nr;
- vp->v_mode = res.fmode;
- vp->v_size = res.fsize;
- vp->v_sdev = res.dev;
-
- /* Find corresponding virtual mount object */
- if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
- printf("VFS: vmnt not found by get_vnode()\n");
-
- vp->v_vmnt = vmp;
- vp->v_dev = vmp->m_dev;
- vp->v_fs_count = 1;
- vp->v_ref_count = 1;
-
- return vp;
-}
-
-
-/*===========================================================================*
- * get_vnode *
- *===========================================================================*/
-PUBLIC struct vnode *get_vnode_x(int fs_e, int inode_nr)
-{
-/* get_vnode() is called to get the details of the specified inode.
- * Note that inode's usage counter in the FS is supposed to be incremented.
- */
- struct vnode *vp, *vp2;
- struct vmnt *vmp;
-
- /* Request & response structures */
- struct node_req req;
- struct node_details res;
-
- vp= find_vnode(fs_e, inode_nr);
- if (vp)
- {
- vp->v_ref_count++;
- return vp;
- }
-
- return get_vnode(fs_e, inode_nr);
-}
-
/*===========================================================================*
* get_free_vnode *
if (vp->v_ref_count == 0)
{
vp->v_pipe= NO_PIPE;
+ vp->v_w_pipe_busy= FALSE;
vp->v_uid= -1;
vp->v_gid= -1;
vp->v_sdev= -1;
int v_fs_count; /* # reference at the underlying FS */
int v_ref_check; /* for consistency checks */
char v_pipe; /* set to I_PIPE if pipe */
+ char v_w_pipe_busy; /* true iff writer suspended */
off_t v_pipe_rd_pos;
off_t v_pipe_wr_pos;
endpoint_t v_bfs_e; /* endpoint number for the FS proces in case
inode resides */
Dev_t v_sdev; /* device number for special files */
- int v_blocksize; /* block size of the filesys */
unsigned short v_index; /* inode's index in the FS inode table */
struct vmnt *v_vmnt; /* vmnt object of the partition */