From f46319037b7815a2fb821246841f187c69b59b20 Mon Sep 17 00:00:00 2001 From: Philip Homburg Date: Tue, 7 Aug 2007 12:52:47 +0000 Subject: [PATCH] New VFS interface --- servers/vfs/const.h | 3 +- servers/vfs/device.c | 147 +--- servers/vfs/dmap.c | 184 ++++- servers/vfs/dmap.h | 24 + servers/vfs/exec.c | 134 ++-- servers/vfs/fs.h | 1 + servers/vfs/glo.h | 1 - servers/vfs/link.c | 363 ++++------ servers/vfs/main.c | 109 +-- servers/vfs/misc.c | 10 +- servers/vfs/mount.c | 323 ++++----- servers/vfs/open.c | 467 ++++++++----- servers/vfs/param.h | 5 + servers/vfs/path.c | 638 +++++++---------- servers/vfs/pipe.c | 154 +++-- servers/vfs/protect.c | 164 +++-- servers/vfs/proto.h | 117 ++-- servers/vfs/read.c | 354 +++++----- servers/vfs/request.c | 1515 +++++++++++++++++++++++++---------------- servers/vfs/request.h | 212 +----- servers/vfs/stadir.c | 42 +- servers/vfs/super.h | 2 + servers/vfs/table.c | 2 +- servers/vfs/time.c | 61 +- servers/vfs/type.h | 10 + servers/vfs/utility.c | 8 +- servers/vfs/vmnt.h | 2 - servers/vfs/vnode.c | 81 +-- servers/vfs/vnode.h | 2 +- 29 files changed, 2629 insertions(+), 2506 deletions(-) create mode 100644 servers/vfs/dmap.h diff --git a/servers/vfs/const.h b/servers/vfs/const.h index 4894e234b..6c0ef4805 100644 --- a/servers/vfs/const.h +++ b/servers/vfs/const.h @@ -87,7 +87,6 @@ #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) @@ -109,7 +108,7 @@ #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 diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 37f68c91b..be6933a3b 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -303,125 +303,6 @@ int gids_size; 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 * @@ -803,12 +684,12 @@ int flags; /* mode bits and flags */ 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; } @@ -822,22 +703,21 @@ int flags; /* mode bits and flags */ 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; } @@ -847,17 +727,19 @@ int flags; /* mode bits and flags */ 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; @@ -870,6 +752,7 @@ int flags; /* mode bits and flags */ return(dev_mess.REP_STATUS); } + /*===========================================================================* * dev_up * *===========================================================================*/ diff --git a/servers/vfs/dmap.c b/servers/vfs/dmap.c index 8ab0d016b..6bc92bd1c 100644 --- a/servers/vfs/dmap.c +++ b/servers/vfs/dmap.c @@ -10,12 +10,13 @@ #include #include #include +#include #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 @@ -32,29 +33,32 @@ */ 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 * *===========================================================================*/ @@ -116,6 +120,77 @@ int force; 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 * *===========================================================================*/ @@ -176,6 +251,74 @@ int force; 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 * *===========================================================================*/ @@ -213,6 +356,7 @@ PUBLIC void build_dmap() 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; diff --git a/servers/vfs/dmap.h b/servers/vfs/dmap.h new file mode 100644 index 000000000..71c2d4856 --- /dev/null +++ b/servers/vfs/dmap.h @@ -0,0 +1,24 @@ +/* +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[]; diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index 44c077154..f86c10129 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -86,10 +86,6 @@ vir_bytes frame_len; 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; @@ -129,23 +125,19 @@ printf("return at %s, %d\n", __FILE__, __LINE__); 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); @@ -153,7 +145,7 @@ printf("return at %s, %d\n", __FILE__, __LINE__); } /* Check access. */ - if ((r = forbidden(vp, X_BIT)) != OK) + if ((r = forbidden(vp, X_BIT, 0 /*!use_realuid*/)) != OK) { put_vnode(vp); return r; @@ -168,6 +160,10 @@ printf("return at %s, %d\n", __FILE__, __LINE__); } 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 */ @@ -340,6 +336,9 @@ int *hdrlenp; { /* 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 @@ -368,26 +367,14 @@ int *hdrlenp; * 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) @@ -441,32 +428,23 @@ vir_bytes *stk_bytes; /* size of initial stack */ 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 #! */ @@ -604,28 +582,64 @@ phys_bytes seg_bytes; /* how much is to be transferred? */ * 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; diff --git a/servers/vfs/fs.h b/servers/vfs/fs.h index b9f16ff04..7d0328340 100644 --- a/servers/vfs/fs.h +++ b/servers/vfs/fs.h @@ -22,5 +22,6 @@ #include #include "const.h" +#include "dmap.h" #include "proto.h" #include "glo.h" diff --git a/servers/vfs/glo.h b/servers/vfs/glo.h index 829353b37..1c7fa6a17 100644 --- a/servers/vfs/glo.h +++ b/servers/vfs/glo.h @@ -15,7 +15,6 @@ EXTERN Dev_t root_dev; /* device number of the root device */ 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 */ diff --git a/servers/vfs/link.c b/servers/vfs/link.c index 69c471bdb..56e632c58 100644 --- a/servers/vfs/link.c +++ b/servers/vfs/link.c @@ -33,59 +33,54 @@ 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; } @@ -100,65 +95,35 @@ PUBLIC int do_unlink() * 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; } @@ -168,90 +133,81 @@ PUBLIC int do_unlink() 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; } @@ -266,41 +222,20 @@ PUBLIC int do_truncate() * 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; } @@ -327,21 +262,14 @@ struct vnode *vp; 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; @@ -353,38 +281,40 @@ off_t newsize; 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; } /*===========================================================================* @@ -393,36 +323,25 @@ PUBLIC int do_slink() 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; } diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 47018444c..2551472a7 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -66,6 +66,10 @@ PUBLIC int main() 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) @@ -103,6 +107,11 @@ PUBLIC int main() 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) { @@ -147,15 +156,21 @@ PRIVATE void get_work() /* 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; @@ -166,9 +181,25 @@ PRIVATE void get_work() * 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(;;) { @@ -207,6 +238,10 @@ int result; /* result of the call (usually OK or error #) */ { /* 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", @@ -219,10 +254,11 @@ int result; /* result of the call (usually OK or error #) */ 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; @@ -273,13 +309,21 @@ PRIVATE void fs_init() 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; } @@ -290,13 +334,13 @@ PRIVATE void fs_init() *===========================================================================*/ 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; @@ -335,40 +379,31 @@ PRIVATE void init_root() 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; @@ -406,16 +441,6 @@ PRIVATE void service_pm() 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); diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 4c586725d..240fd03fb 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -159,7 +159,6 @@ PUBLIC int do_fcntl() 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) { @@ -258,14 +257,9 @@ PUBLIC int do_fcntl() 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: diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index a7b0b983f..7a96ef1c9 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -95,19 +95,15 @@ PRIVATE int mount_fs(endpoint_t fs_e) { /* 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); @@ -128,15 +124,6 @@ PRIVATE int mount_fs(endpoint_t fs_e) /* 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); @@ -175,84 +162,101 @@ PRIVATE int mount_fs(endpoint_t fs_e) /* 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 */ @@ -261,13 +265,6 @@ PRIVATE int mount_fs(endpoint_t fs_e) 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]; @@ -275,57 +272,35 @@ PRIVATE int mount_fs(endpoint_t fs_e) 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; @@ -333,7 +308,7 @@ PRIVATE int mount_fs(endpoint_t fs_e) 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. @@ -365,63 +340,24 @@ PRIVATE int mount_fs(endpoint_t fs_e) 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 */ @@ -500,9 +436,6 @@ Dev_t dev; 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 && @@ -519,7 +452,6 @@ Dev_t dev; 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)) @@ -556,23 +488,22 @@ PRIVATE dev_t name_to_dev() { /* 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; } diff --git a/servers/vfs/open.c b/servers/vfs/open.c index a8c04b570..eb381976f 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -38,6 +38,10 @@ 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)); /*===========================================================================* @@ -83,21 +87,12 @@ PUBLIC int do_open() 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; @@ -116,114 +111,29 @@ PRIVATE int common_open(register int oflags, mode_t omode) 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); @@ -256,11 +166,9 @@ PRIVATE int common_open(register int oflags, mode_t omode) /* 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 */ @@ -332,6 +240,186 @@ PRIVATE int common_open(register int oflags, mode_t omode) 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 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 * *===========================================================================*/ @@ -381,7 +469,7 @@ struct vnode **vpp; 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; @@ -404,7 +492,7 @@ struct vnode **vpp; 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. */ @@ -412,7 +500,7 @@ struct vnode **vpp; 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; @@ -449,6 +537,74 @@ struct vnode **vpp; } +/*===========================================================================* + * 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 * *===========================================================================*/ @@ -492,11 +648,8 @@ PUBLIC int do_mknod() { /* 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 */ @@ -504,26 +657,21 @@ PUBLIC int do_mknod() 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; } @@ -534,36 +682,29 @@ PUBLIC int do_mkdir() { /* 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; } @@ -579,7 +720,6 @@ PUBLIC int do_lseek() 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); @@ -606,12 +746,8 @@ PUBLIC int do_lseek() 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; @@ -631,7 +767,6 @@ PUBLIC int do_llseek() /* 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. */ @@ -657,12 +792,8 @@ PUBLIC int do_llseek() 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; diff --git a/servers/vfs/param.h b/servers/vfs/param.h index a64ecab43..66461a98e 100644 --- a/servers/vfs/param.h +++ b/servers/vfs/param.h @@ -52,6 +52,11 @@ #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 diff --git a/servers/vfs/path.c b/servers/vfs/path.c index f9db5d5c8..521a29b5d 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -21,269 +21,306 @@ #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 */ @@ -297,152 +334,3 @@ char **pathrem; 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; -} - diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index 0dddab50b..a3f4ec3e4 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -51,11 +51,8 @@ PUBLIC int do_pipe() 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 */ @@ -80,13 +77,9 @@ PUBLIC int do_pipe() 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) { @@ -105,8 +98,8 @@ PUBLIC int do_pipe() 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) { @@ -120,6 +113,7 @@ PUBLIC int do_pipe() /* 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; @@ -133,13 +127,12 @@ PUBLIC int do_pipe() /*===========================================================================* * 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 @@ -163,8 +156,6 @@ int notouch; /* check only */ if (oflags & O_NONBLOCK) { r = EAGAIN; } else { - if (!notouch) - suspend(XPIPE); /* block reader */ r = SUSPEND; } /* If need be, activate sleeping writers. */ @@ -173,56 +164,65 @@ int notouch; /* check only */ } 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; } /*===========================================================================* @@ -238,7 +238,10 @@ int task; /* who is proc waiting for? (PIPE = pipe) */ * 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; @@ -254,6 +257,31 @@ int task; /* who is proc waiting for? (PIPE = pipe) */ } } +/*===========================================================================* + * 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 * *===========================================================================*/ @@ -296,6 +324,10 @@ int count; /* max number of processes to release */ 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. */ @@ -481,15 +513,15 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block) 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; diff --git a/servers/vfs/protect.c b/servers/vfs/protect.c index 3ac498b72..97082ce16 100644 --- a/servers/vfs/protect.c +++ b/servers/vfs/protect.c @@ -31,47 +31,54 @@ 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; } @@ -84,52 +91,58 @@ PUBLIC int do_chown() 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; } @@ -154,10 +167,8 @@ PUBLIC int do_umask() 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) @@ -165,30 +176,20 @@ PUBLIC int do_access() 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 @@ -198,18 +199,31 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired) 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. @@ -220,8 +234,8 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired) 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); } diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 1248f5f18..cba9fe87a 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -12,8 +12,6 @@ struct vnode; /* 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) ); @@ -33,6 +31,7 @@ _PROTOTYPE( void dev_up, (int major) ); _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) ); @@ -100,20 +99,25 @@ _PROTOTYPE( int do_open, (void) ); _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) ); @@ -124,60 +128,78 @@ _PROTOTYPE( int do_access, (void) ); _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) ); @@ -190,7 +212,6 @@ _PROTOTYPE( int do_rdlink, (void) ); _PROTOTYPE( int do_lstat, (void) ); /* time.c */ -_PROTOTYPE( int do_stime, (void) ); _PROTOTYPE( int do_utime, (void) ); /* utility.c */ @@ -215,8 +236,10 @@ _PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb) ); _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) ); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index 47e68155f..fa37d4d43 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -27,7 +27,6 @@ #include "vnode.h" #include "vmnt.h" - /*===========================================================================* * do_read * *===========================================================================*/ @@ -47,70 +46,74 @@ int rw_flag; /* READING or WRITING */ 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) @@ -138,83 +141,49 @@ int rw_flag; /* READING or WRITING */ } /* 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; } } @@ -233,32 +202,10 @@ int rw_flag; /* READING or WRITING */ } } } - 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; } @@ -266,65 +213,6 @@ int rw_flag; /* READING or WRITING */ } -/* 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 * *===========================================================================*/ @@ -366,4 +254,128 @@ PUBLIC int 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; +} + + diff --git a/servers/vfs/request.c b/servers/vfs/request.c index b4ca2810e..2ed24f955 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -1,452 +1,521 @@ -/* 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 -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include "file.h" +#include "fproc.h" +#include "param.h" #include -#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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; @@ -455,517 +524,805 @@ int pos; 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 + @@ -983,6 +1340,12 @@ PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm) 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; diff --git a/servers/vfs/request.h b/servers/vfs/request.h index ca65ac016..087b8032b 100644 --- a/servers/vfs/request.h +++ b/servers/vfs/request.h @@ -7,27 +7,20 @@ #include -/* 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; @@ -43,35 +36,6 @@ typedef struct open_req { } 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; @@ -79,147 +43,6 @@ typedef struct clone_opcl_req { } 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; @@ -242,16 +65,6 @@ typedef struct readsuper_res { } 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 */ @@ -285,19 +98,4 @@ typedef struct lookup_res { } 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 */ diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index 544a315c8..5d0954e58 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -47,7 +47,7 @@ PUBLIC int do_fchdir() 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 */ @@ -122,18 +122,12 @@ int len; /* length of the directory name string */ { /* 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) @@ -143,7 +137,7 @@ int len; /* length of the directory name string */ } /* Access check */ - r = forbidden(vp, X_BIT); + r = forbidden(vp, X_BIT, 0 /*!use_realuid*/); if (r != OK) { put_vnode(vp); return r; @@ -174,22 +168,19 @@ struct vnode *vp; /* this is what the inode has to become */ 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; } @@ -246,13 +237,13 @@ PUBLIC int do_fstatfs() /*===========================================================================* - * 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); @@ -263,10 +254,15 @@ PUBLIC int do_lstat() 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; } diff --git a/servers/vfs/super.h b/servers/vfs/super.h index 035c87b38..b784a272f 100644 --- a/servers/vfs/super.h +++ b/servers/vfs/super.h @@ -18,6 +18,7 @@ * 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 */ @@ -53,6 +54,7 @@ EXTERN struct super_block { 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 */ diff --git a/servers/vfs/table.c b/servers/vfs/table.c index 5b27eefc7..859eee3d8 100644 --- a/servers/vfs/table.c +++ b/servers/vfs/table.c @@ -41,7 +41,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = { 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 */ diff --git a/servers/vfs/time.c b/servers/vfs/time.c index 806fee9a2..5e34e395b 100644 --- a/servers/vfs/time.c +++ b/servers/vfs/time.c @@ -11,6 +11,7 @@ #include "file.h" #include "fproc.h" #include "param.h" +#include "vnode.h" #include #include "vmnt.h" @@ -22,10 +23,10 @@ PUBLIC int do_utime() { /* 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. @@ -35,46 +36,38 @@ PUBLIC int do_utime() 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; } diff --git a/servers/vfs/type.h b/servers/vfs/type.h index 19749fef0..5206d3e21 100644 --- a/servers/vfs/type.h +++ b/servers/vfs/type.h @@ -21,3 +21,13 @@ typedef struct { /* V2.x disk inode */ 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 + diff --git a/servers/vfs/utility.c b/servers/vfs/utility.c index 97f12a3d7..a3e893409 100644 --- a/servers/vfs/utility.c +++ b/servers/vfs/utility.c @@ -143,10 +143,14 @@ PUBLIC time_t clock_time() * 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))); } diff --git a/servers/vfs/vmnt.h b/servers/vfs/vmnt.h index f1916fcdb..266c54907 100644 --- a/servers/vfs/vmnt.h +++ b/servers/vfs/vmnt.h @@ -5,8 +5,6 @@ EXTERN struct vmnt { 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]; diff --git a/servers/vfs/vnode.c b/servers/vfs/vnode.c index b0d2bd4fa..6628a89cd 100644 --- a/servers/vfs/vnode.c +++ b/servers/vfs/vnode.c @@ -19,86 +19,6 @@ #include -/*===========================================================================* - * 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 * @@ -114,6 +34,7 @@ int line; 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; diff --git a/servers/vfs/vnode.h b/servers/vfs/vnode.h index 6cc1eec0c..ee7dc6c7a 100644 --- a/servers/vfs/vnode.h +++ b/servers/vfs/vnode.h @@ -11,6 +11,7 @@ EXTERN struct vnode { 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 @@ -20,7 +21,6 @@ EXTERN struct vnode { 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 */ -- 2.44.0