New VFS interface

This commit is contained in:
Philip Homburg 2007-08-07 12:52:47 +00:00
parent 2ca2b86a3a
commit f46319037b
29 changed files with 2737 additions and 2614 deletions

View file

@ -87,7 +87,6 @@
#define DIR_ENTRY_SIZE usizeof (struct direct) /* # bytes/dir entry */ #define DIR_ENTRY_SIZE usizeof (struct direct) /* # bytes/dir entry */
#define NR_DIR_ENTRIES(b) ((b)/DIR_ENTRY_SIZE) /* # dir entries/blk */ #define NR_DIR_ENTRIES(b) ((b)/DIR_ENTRY_SIZE) /* # dir entries/blk */
#define SUPER_SIZE usizeof (struct super_block) /* super_block size */ #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_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk */
#define FS_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT) #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_INDIRECTS(b) ((b)/V2_ZONE_NUM_SIZE) /* # zones/indir block */
#define V2_INODES_PER_BLOCK(b) ((b)/V2_INODE_SIZE)/* # V2 dsk inodes/blk */ #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_READ 2001
#define VFS_DEV_WRITE 2002 #define VFS_DEV_WRITE 2002
#define VFS_DEV_SCATTER 2003 #define VFS_DEV_SCATTER 2003

View file

@ -303,125 +303,6 @@ int gids_size;
return; 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 * * dev_io *
@ -803,12 +684,12 @@ int flags; /* mode bits and flags */
if (dp->dmap_driver == NONE) { 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; return ENXIO;
} }
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { 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); dev, dp->dmap_driver);
return ENXIO; return ENXIO;
} }
@ -822,22 +703,21 @@ int flags; /* mode bits and flags */
if (dev_mess.REP_STATUS != minor) { if (dev_mess.REP_STATUS != minor) {
struct vnode *vp; struct vnode *vp;
struct vmnt *vmp; struct vmnt *vmp;
struct clone_opcl_req req;
struct node_details res; struct node_details res;
/* A new minor device number has been returned. /* 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. */ /* Device number of the new device. */
dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR); dev = (dev & ~(BYTE << MINOR)) |
(dev_mess.REP_STATUS << MINOR);
/* Fill in request */
req.fs_e = ROOT_FS_E;
req.dev = dev;
/* Issue request */ /* 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); (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
return r; return r;
} }
@ -847,17 +727,19 @@ int flags; /* mode bits and flags */
put_vnode(vp); put_vnode(vp);
if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { 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 = fp->fp_filp[m_in.fd]->filp_vno;
} }
vp->v_fs_e = res.fs_e; vp->v_fs_e = res.fs_e;
if ((vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) 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_vmnt = vmp;
vp->v_dev = vmp->m_dev; vp->v_dev = vmp->m_dev;
vp->v_fs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr; vp->v_inode_nr = res.inode_nr;
vp->v_mode = res.fmode; vp->v_mode = res.fmode;
vp->v_sdev = dev; vp->v_sdev = dev;
@ -870,6 +752,7 @@ int flags; /* mode bits and flags */
return(dev_mess.REP_STATUS); return(dev_mess.REP_STATUS);
} }
/*===========================================================================* /*===========================================================================*
* dev_up * * dev_up *
*===========================================================================*/ *===========================================================================*/

View file

@ -10,12 +10,13 @@
#include <ctype.h> #include <ctype.h>
#include <unistd.h> #include <unistd.h>
#include <minix/com.h> #include <minix/com.h>
#include <minix/ds.h>
#include "param.h" #include "param.h"
/* Some devices may or may not be there in the next table. */ /* 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?(opcl):no_dev), (enable?(io):0), \
(enable?(driver):0), (flags) }, (enable?(driver):0), (flags), label },
#define NC(x) (NR_CTRLRS >= (x)) #define NC(x) (NR_CTRLRS >= (x))
/* The order of the entries here determines the mapping between major device /* The order of the entries here determines the mapping between major device
@ -32,29 +33,32 @@
*/ */
struct dmap dmap[NR_DEVICES]; /* actual map */ struct dmap dmap[NR_DEVICES]; /* actual map */
PRIVATE struct dmap init_dmap[] = { PRIVATE struct dmap init_dmap[] = {
DT(1, no_dev, 0, 0, 0) /* 0 = not used */ DT(1, no_dev, 0, 0, 0, "") /* 0 = not used */
DT(1, gen_opcl, gen_io, MEM_PROC_NR, 0) /* 1 = /dev/mem */ 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, "") /* 2 = /dev/fd0 */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /* 3 = /dev/c0 */ 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, 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(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0, "") /* 5 = /dev/tty */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 6 = /dev/lp */ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 6 = /dev/lp */
#if (MACHINE == IBM_PC) #if (MACHINE == IBM_PC)
DT(1, no_dev, 0, 0, DMAP_MUTABLE) /* 7 = /dev/ip */ DT(1, no_dev, 0, 0, DMAP_MUTABLE, "") /* 7 = /dev/ip */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 8 = /dev/c1 */ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 8 = /dev/c1 */
DT(0, 0, 0, 0, DMAP_MUTABLE) /* 9 = not used */ DT(0, 0, 0, 0, DMAP_MUTABLE, "") /* 9 = not used */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /*10 = /dev/c2 */ DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /*10 = /dev/c2 */
DT(0, 0, 0, 0, DMAP_MUTABLE) /*11 = not used */ 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, "") /*12 = /dev/c3 */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*13 = /dev/audio */ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*13 = /dev/audio */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*14 = /dev/mixer */ 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(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, "") /*16 = /dev/random*/
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*17 = /dev/cmos */ DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*17 = /dev/cmos */
#endif /* IBM_PC */ #endif /* IBM_PC */
}; };
FORWARD _PROTOTYPE( int map_driverX, (char *label, int major,
endpoint_t proc_nr_e, int style, int force) );
/*===========================================================================* /*===========================================================================*
* do_devctl * * do_devctl *
*===========================================================================*/ *===========================================================================*/
@ -116,6 +120,77 @@ int force;
return(result); 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 * * map_driver *
*===========================================================================*/ *===========================================================================*/
@ -176,6 +251,74 @@ int force;
return(OK); 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 * * dmap_unmap_by_endpt *
*===========================================================================*/ *===========================================================================*/
@ -213,6 +356,7 @@ PUBLIC void build_dmap()
dp->dmap_io = init_dmap[i].dmap_io; dp->dmap_io = init_dmap[i].dmap_io;
dp->dmap_driver = init_dmap[i].dmap_driver; dp->dmap_driver = init_dmap[i].dmap_driver;
dp->dmap_flags = init_dmap[i].dmap_flags; dp->dmap_flags = init_dmap[i].dmap_flags;
strcpy(dp->dmap_label, init_dmap[i].dmap_label);
} else { /* no default */ } else { /* no default */
dp->dmap_opcl = no_dev; dp->dmap_opcl = no_dev;
dp->dmap_io = no_dev_io; dp->dmap_io = no_dev_io;

24
servers/vfs/dmap.h Normal file
View file

@ -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[];

View file

@ -86,10 +86,6 @@ vir_bytes frame_len;
char progname[PROC_NAME_LEN]; char progname[PROC_NAME_LEN];
static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ 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); okendpt(proc_e, &proc_s);
rfp= fp= &fproc[proc_s]; rfp= fp= &fproc[proc_s];
who_e= proc_e; who_e= proc_e;
@ -129,23 +125,19 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
for (round= 0; round < 2; round++) for (round= 0; round < 2; round++)
/* round = 0 (first attempt), or 1 (interpreted script) */ /* 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 */ /* Save the name of the program */
(cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath); (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);
strncpy(progname, cp, PROC_NAME_LEN-1); strncpy(progname, cp, PROC_NAME_LEN-1);
progname[PROC_NAME_LEN-1] = '\0'; 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 */ /* Request lookup */
if ((r = lookup_vp(&lookup_req, &vp)) != OK) if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK)
{
put_vnode(vp);
return r; return r;
}
if ((vp->v_mode & I_TYPE) != I_REGULAR) { if ((vp->v_mode & I_TYPE) != I_REGULAR) {
put_vnode(vp); put_vnode(vp);
@ -153,7 +145,7 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
} }
/* Check access. */ /* Check access. */
if ((r = forbidden(vp, X_BIT)) != OK) if ((r = forbidden(vp, X_BIT, 0 /*!use_realuid*/)) != OK)
{ {
put_vnode(vp); put_vnode(vp);
return r; return r;
@ -168,6 +160,10 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
} }
v_ctime = sb.st_ctime; 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) if (round == 0)
{ {
/* Deal with setuid/setgid executables */ /* 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. */ /* Read the header and extract the text, data, bss and total sizes from it. */
off_t pos; off_t pos;
int r;
u64_t new_pos;
unsigned int cum_io_incr;
struct exec hdr; /* a.out header is read in here */ struct exec hdr; /* a.out header is read in here */
/* Read the header and check the magic number. The standard MINIX header /* 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 * used here only. The symbol table is for the benefit of a debugger and
* is ignored here. * is ignored here.
*/ */
struct readwrite_req req;
struct readwrite_res res;
int r;
pos= 0; /* Read from the start of the file */ 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 */ /* 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? */ /* Interpreted script? */
if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2) 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; int n, r;
off_t pos; off_t pos;
char *sp, *interp = NULL; char *sp, *interp = NULL;
u64_t new_pos;
unsigned int cum_io_incr;
char buf[_MAX_BLOCK_SIZE]; char buf[_MAX_BLOCK_SIZE];
struct readwrite_req req;
struct readwrite_res res;
/* Make user_path the new argv[0]. */ /* Make user_path the new argv[0]. */
if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) return(ENOMEM); if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) return(ENOMEM);
pos = 0; /* Read from the start of the file */ 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 */ /* 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; n = vp->v_size;
if (n > vp->v_vmnt->m_block_size) if (n > _MAX_BLOCK_SIZE)
n = vp->v_vmnt->m_block_size; n = _MAX_BLOCK_SIZE;
if (n < 2) return ENOEXEC; if (n < 2) return ENOEXEC;
sp = &(buf[2]); /* just behind the #! */ 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 * a segment is padded out to a click multiple, and the data segment is only
* partially initialized. * partially initialized.
*/ */
struct readwrite_req req;
struct readwrite_res res;
int r; 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 */ /* Make sure that the file is big enough */
if (vp->v_size < off+seg_bytes) return EIO; 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 */ #if 0
req.fs_e = vp->v_fs_e; printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n",
req.rw_flag = READING; proc_e, seg, 0, seg_bytes, off);
req.inode_nr = vp->v_inode_nr; #endif
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;
/* Issue request */ /* 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"); printf("VFSread_seg segment has not been read properly by exec() \n");
return r; return r;

View file

@ -22,5 +22,6 @@
#include <minix/sysutil.h> #include <minix/sysutil.h>
#include "const.h" #include "const.h"
#include "dmap.h"
#include "proto.h" #include "proto.h"
#include "glo.h" #include "glo.h"

View file

@ -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 ROOT_FS_E; /* kernel endpoint of the root FS proc */
EXTERN int last_login_fs_e; /* endpoint of the FS proc that logged in EXTERN int last_login_fs_e; /* endpoint of the FS proc that logged in
before the corresponding mount request */ before the corresponding mount request */
EXTERN time_t boottime; /* time in seconds at system boot */
/* The parameters of the call are kept here. */ /* The parameters of the call are kept here. */
EXTERN message m_in; /* the input message itself */ EXTERN message m_in; /* the input message itself */

View file

@ -33,59 +33,54 @@
PUBLIC int do_link() PUBLIC int do_link()
{ {
/* Perform the link(name1, name2) system call. */ /* 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; 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) if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK)
return(err_code); return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */ /* 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; linked_fs_e = vp_o->v_fs_e;
req.linked_file = res.inode_nr;
/* Does the final directory of 'name2' exist? */ /* Does the final directory of 'name2' exist? */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
put_vnode(vp_o);
return(err_code); return(err_code);
} }
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = string;
lookup_req.flags = LAST_DIR;
/* Request lookup */ /* 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. */ /* Check for links across devices. */
if (linked_fs_e != link_lastdir_fs_e) if (linked_fs_e != link_lastdir_fs_e)
{
put_vnode(vp_o);
put_vnode(vp_d);
return EXDEV; return EXDEV;
}
/* Send link request. */ r= forbidden(vp_d, W_BIT|X_BIT, 0 /*!use_realuid*/);
req.fs_e = linked_fs_e; if (r != OK)
/* Send the last component of the link name */ {
req.uid = fp->fp_effuid; put_vnode(vp_o);
req.gid = fp->fp_effgid; put_vnode(vp_d);
req.lastc = string; return r;
}
/* Issue request */ /* 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. * may be used by the superuser to do dangerous things; rmdir() may not.
*/ */
register struct fproc *rfp; register struct fproc *rfp;
char string[NAME_MAX];
struct vnode *vp; struct vnode *vp;
struct unlink_req req;
struct lookup_req lookup_req;
struct node_details res;
int r; int r;
string[0] = '\0';
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
/* Fill in lookup request fields */ r= lookup_lastdir(0 /*!use_realuid*/, &vp);
lookup_req.path = user_fullpath; if (r != OK)
lookup_req.lastc = NULL; return r;
lookup_req.flags = EAT_PATH_OPAQUE;
/* The caller must have both search and execute permission */
/* Request lookup */ r= forbidden(vp, X_BIT|W_BIT, 0 /*!use_realuid*/);
if ((r = lookup(&lookup_req, &res)) != OK) return r; if (r != OK)
{
put_vnode(vp);
return r;
}
/* If a directory file has to be removed the following conditions have to met: /* 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 the root of a mounted file system
* - The directory must not be anybody's root/working directory * - 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 */ /* 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() PUBLIC int do_rename()
{ {
/* Perform the rename(name1, name2) system call. */ /* Perform the rename(name1, name2) system call. */
int r;
int old_dir_inode; int old_dir_inode;
int old_fs_e; int old_fs_e;
int new_dir_inode; int new_dir_inode;
int new_fs_e; int new_fs_e;
char old_name[NAME_MAX]; size_t len;
char new_name[NAME_MAX]; struct vnode *vp_od, *vp_nd;
struct vnode *vp; char old_name[PATH_MAX+1];
struct fproc *rfp;
struct rename_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
/* See if 'name1' (existing file) exists. Get dir and file inodes. */ /* See if 'name1' (existing file) exists. Get dir and file inodes. */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); if (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 */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_od)) != OK) return r;
/* Remeber inode number and FS endpoint */
old_fs_e = res.fs_e;
req.old_dir = res.inode_nr;
/* See if 'name2' (new name) exists. Get dir inode */ r= forbidden(vp_od, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) r = err_code; if (r != OK)
{
/* Fill in lookup request fields */ put_vnode(vp_od);
lookup_req.path = user_fullpath; return r;
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);
}
}
} }
/* Fill in lookup request fields */ /* Remeber FS endpoint */
lookup_req.path = user_fullpath; old_fs_e = vp_od->v_fs_e;
lookup_req.lastc = new_name;
lookup_req.flags = LAST_DIR; /* Save the last component of the old name */
len= strlen(user_fullpath);
/* Request lookup */ if (len >= sizeof(old_name))
if ((r = lookup(&lookup_req, &res)) != OK) return r; {
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)
{
put_vnode(vp_od);
return err_code;
}
/* Remeber inode number and FS endpoint */ /* Request lookup */
new_fs_e = res.fs_e; r = lookup_lastdir(0 /*!use_realuid*/, &vp_nd);
req.new_dir = res.inode_nr; 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;
}
/* Remeber FS endpoint */
new_fs_e = vp_nd->v_fs_e;
/* Both parent directories must be on the same device. */ /* Both parent directories must be on the same device. */
if (old_fs_e != new_fs_e) return EXDEV; if (old_fs_e != new_fs_e)
{
put_vnode(vp_od);
put_vnode(vp_nd);
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];
/* Issue request */ /* 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. * work.
*/ */
struct vnode *vp; struct vnode *vp;
struct trunc_req req;
struct lookup_req lookup_req;
struct node_details res;
int r; int r;
printf("in do_truncate\n"); printf("in do_truncate\n");
if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code; 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 */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* Check whether the file is in use or not */ r= truncate_vn(vp, m_in.m2_l1);
vp = find_vnode(res.fs_e, res.inode_nr);
/* Fill in request message fields.*/ put_vnode(vp);
req.fs_e = res.fs_e;
req.length = m_in.m2_l1; return r;
req.inode_nr = res.inode_nr;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
/* 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;
} }
@ -327,21 +262,14 @@ struct vnode *vp;
off_t newsize; off_t newsize;
{ {
int r; int r;
struct ftrunc_req req;
if ( (vp->v_mode & I_TYPE) != I_REGULAR && if ( (vp->v_mode & I_TYPE) != I_REGULAR &&
(vp->v_mode & I_TYPE) != I_NAMED_PIPE) { (vp->v_mode & I_TYPE) != I_NAMED_PIPE) {
return EINVAL; 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 */ /* 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; vp->v_size = newsize;
return OK; return OK;
@ -353,38 +281,40 @@ off_t newsize;
PUBLIC int do_slink() PUBLIC int do_slink()
{ {
/* Perform the symlink(name1, name2) system call. */ /* 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; 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) if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
return(err_code); return(err_code);
if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE) if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE)
return(ENAMETOOLONG); 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 */ /* Request lookup */
req.fs_e = res.fs_e; if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK)
req.parent_dir = res.inode_nr; {
req.uid = fp->fp_effuid; printf("vfs:do_slink: lookup_lastdir failed with %d\n", r);
req.gid = fp->fp_effgid; return r;
req.lastc = string; }
req.who_e = who_e;
req.path_addr = m_in.name1; printf("vfs:do_slink: got dir inode %d on dev 0x%x, fs %d\n",
req.path_length = m_in.name1_length - 1; 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 */ /* 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() PUBLIC int do_rdlink()
{ {
/* Perform the readlink(name, buf) system call. */ /* Perform the readlink(name, buf) system call. */
int copylen; int r, copylen;
struct rdlink_req req; struct vnode *vp;
struct lookup_req lookup_req;
struct node_details res;
int r;
copylen = m_in.m1_i2; copylen = m_in.m1_i2;
if(copylen < 0) return EINVAL; if(copylen < 0) return EINVAL;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); 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 */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp);
if (r != 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;
/* Issue request */ /* 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;
} }

View file

@ -66,6 +66,10 @@ PUBLIC int main()
if (who_e == PM_PROC_NR && call_nr != PROC_EVENT) if (who_e == PM_PROC_NR && call_nr != PROC_EVENT)
printf("FS: strange, got message %d from PM\n", call_nr); 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. */ /* Check for special control messages first. */
if ((call_nr & NOTIFY_MESSAGE)) { if ((call_nr & NOTIFY_MESSAGE)) {
if (call_nr == PROC_EVENT) if (call_nr == PROC_EVENT)
@ -103,6 +107,11 @@ PUBLIC int main()
if (error != SUSPEND) reply(who_e, error); if (error != SUSPEND) reply(who_e, error);
break; break;
case MAPDRIVER:
error= do_mapdriver();
if (error != SUSPEND) reply(who_e, error);
break;
default: default:
/* Call the internal function that does the work. */ /* Call the internal function that does the work. */
if (call_nr < 0 || call_nr >= NCALLS) { if (call_nr < 0 || call_nr >= NCALLS) {
@ -147,15 +156,21 @@ PRIVATE void get_work()
/* Normally wait for new input. However, if 'reviving' is /* Normally wait for new input. However, if 'reviving' is
* nonzero, a suspended process must be awakened. * nonzero, a suspended process must be awakened.
*/ */
int r, found_one, fd_nr;
struct filp *f;
register struct fproc *rp; register struct fproc *rp;
if (reviving != 0) { while (reviving != 0) {
found_one= FALSE;
/* Revive a suspended process. */ /* Revive a suspended process. */
for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++)
if (rp->fp_pid != PID_FREE && rp->fp_revived == REVIVING) { if (rp->fp_pid != PID_FREE && rp->fp_revived == REVIVING) {
found_one= TRUE;
who_p = (int)(rp - fproc); who_p = (int)(rp - fproc);
who_e = rp->fp_endpoint; who_e = rp->fp_endpoint;
call_nr = rp->fp_fd & BYTE; call_nr = rp->fp_fd & BYTE;
m_in.fd = (rp->fp_fd >>8) & BYTE; m_in.fd = (rp->fp_fd >>8) & BYTE;
m_in.buffer = rp->fp_buffer; m_in.buffer = rp->fp_buffer;
m_in.nbytes = rp->fp_nbytes; m_in.nbytes = rp->fp_nbytes;
@ -166,9 +181,25 @@ PRIVATE void get_work()
* If it is, it'll 'leak' grants. * If it is, it'll 'leak' grants.
*/ */
assert(!GRANT_VALID(rp->fp_grant)); 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; 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(;;) { 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. */ /* Send a reply to a user process. If the send fails, just ignore it. */
int s; int s;
if (call_nr == SYMLINK)
printf("vfs:reply: replying %d for call %d\n", result, call_nr);
m_out.reply_type = result; m_out.reply_type = result;
s = send(whom, &m_out); s = send(whom, &m_out);
if (s != OK) printf("VFS: couldn't send reply %d to %d: %d\n", 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() PRIVATE void fs_init()
{ {
/* Initialize global variables, tables, etc. */ /* Initialize global variables, tables, etc. */
register struct inode *rip;
register struct fproc *rfp;
message mess;
int s; int s;
register struct fproc *rfp;
struct vmnt *vmp;
struct vnode *root_vp;
message mess;
/* Clear endpoint field */ /* Clear endpoint field */
last_login_fs_e = NONE; last_login_fs_e = NONE;
@ -273,13 +309,21 @@ PRIVATE void fs_init()
init_root(); /* init root device and load super block */ init_root(); /* init root device and load super block */
init_select(); /* init select() structures */ 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. */ /* The root device can now be accessed; set process directories. */
for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
FD_ZERO(&(rfp->fp_filp_inuse)); FD_ZERO(&(rfp->fp_filp_inuse));
if (rfp->fp_pid != PID_FREE) { if (rfp->fp_pid != PID_FREE) {
rfp->fp_rd = get_vnode_x(ROOT_FS_E, ROOT_INODE); dup_vnode(root_vp);
rfp->fp_wd = get_vnode_x(ROOT_FS_E, ROOT_INODE); rfp->fp_rd = root_vp;
dup_vnode(root_vp);
rfp->fp_wd = root_vp;
} else rfp->fp_endpoint = NONE; } else rfp->fp_endpoint = NONE;
} }
@ -290,13 +334,13 @@ PRIVATE void fs_init()
*===========================================================================*/ *===========================================================================*/
PRIVATE void init_root() PRIVATE void init_root()
{ {
int r = OK;
struct vmnt *vmp; struct vmnt *vmp;
struct vnode *root_node; struct vnode *root_node;
struct dmap *dp; struct dmap *dp;
char *label;
message m; message m;
int r = OK; struct node_details resX;
struct readsuper_req sreq;
struct readsuper_res sres;
/* Open the root device. */ /* Open the root device. */
root_dev = DEV_IMGRD; root_dev = DEV_IMGRD;
@ -335,40 +379,31 @@ PRIVATE void init_root()
panic(__FILE__,"No driver for root device", r); panic(__FILE__,"No driver for root device", r);
} }
/* Open the device the file system lives on. */ label= dp->dmap_label;
if ((r = dev_open(root_dev, ROOT_FS_E, (R_BIT|W_BIT))) != OK) if (strlen(label) == 0)
panic(__FILE__,"Cannot open root device", r); {
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 */ /* Issue request */
if ((r = req_readsuper(&sreq, &sres)) != OK) { r = req_readsuper(ROOT_FS_E, label, root_dev, 0 /*!readonly*/,
dev_close(root_dev); 1 /*isroot*/, &resX);
if (r != OK) {
panic(__FILE__,"Cannot read superblock from root", r); panic(__FILE__,"Cannot read superblock from root", r);
} }
/* Fill in root node's fields */ /* Fill in root node's fields */
root_node->v_fs_e = sres.fs_e; root_node->v_fs_e = resX.fs_e;
root_node->v_inode_nr = sres.inode_nr; root_node->v_inode_nr = resX.inode_nr;
root_node->v_mode = sres.fmode; root_node->v_mode = resX.fmode;
root_node->v_size = sres.fsize; root_node->v_size = resX.fsize;
root_node->v_sdev = NO_DEV; 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; root_node->v_ref_count = 1;
/* Fill in max file size and blocksize for the vmnt */ /* 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_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_driver_e = dp->dmap_driver;
vmp->m_flags = 0; vmp->m_flags = 0;
@ -406,16 +441,6 @@ PRIVATE void service_pm()
call= m.m_type; call= m.m_type;
switch(call) 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: case PM_SETSID:
pm_setsid(m.PM_SETSID_PROC); pm_setsid(m.PM_SETSID_PROC);

View file

@ -159,7 +159,6 @@ PUBLIC int do_fcntl()
long cloexec_mask; /* bit map for the FD_CLOEXEC flag */ long cloexec_mask; /* bit map for the FD_CLOEXEC flag */
long clo_value; /* FD_CLOEXEC flag in proper position */ long clo_value; /* FD_CLOEXEC flag in proper position */
struct filp *dummy; struct filp *dummy;
struct ftrunc_req req;
/* Is the file descriptor valid? */ /* Is the file descriptor valid? */
if ((f = get_filp(m_in.fd)) == NIL_FILP) { if ((f = get_filp(m_in.fd)) == NIL_FILP) {
@ -258,14 +257,9 @@ PUBLIC int do_fcntl()
end = 0; 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 */ /* Issue request */
return req_ftrunc(&req); return req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,
start, end);
} }
default: default:

View file

@ -95,19 +95,15 @@ PRIVATE int mount_fs(endpoint_t fs_e)
{ {
/* Perform the mount(name, mfile, rd_only) system call. */ /* Perform the mount(name, mfile, rd_only) system call. */
int rdir, mdir; /* TRUE iff {root|mount} file is dir */ 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 fproc *tfp;
struct dmap *dp; struct dmap *dp;
dev_t dev; dev_t dev;
message m; message m;
struct vnode *vp, *root_node, *mounted_on, *bspec; struct vnode *vp, *root_node, *Xmounted_on, *bspec;
struct vmnt *vmp, *vmp2; struct vmnt *vmp, *vmp2;
struct mountpoint_req mreq; char *label;
struct node_details res; struct node_details resX;
struct readsuper_req sreq;
struct readsuper_res sres;
struct lookup_req lookup_req;
node_req_t node_req;
/* Only the super-user may do MOUNT. */ /* Only the super-user may do MOUNT. */
if (!super_user) return(EPERM); 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 '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); 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 */ /* Convert name to device number */
if ((dev = name_to_dev()) == NO_DEV) return(err_code); 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 */ /* Partition was/is already mounted */
if (found) { if (found) {
/* It is possible that we have an old root lying around that /* It is possible that we have an old root lying around that
* needs to be remounted. */ * needs to be remounted. */
if (vmp->m_mounted_on != vmp->m_root_node || if (vmp->m_mounted_on != vmp->m_root_node ||
vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) { vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) {
/* Normally, m_mounted_on refers to the mount point. For a root /* Normally, m_mounted_on refers to the mount point. For a
* filesystem, m_mounted_on is equal to the root vnode. We assume * root filesystem, m_mounted_on is equal to the root vnode.
* that the root of FS is always the real root. If the two * We assume that the root of FS is always the real root. If
* vnodes are different or if the root of FS is equal two the * the two vnodes are different or if the root of FS is equal
* root of the filesystem we found, we found a filesystem that * to the root of the filesystem we found, we found a
* is in use. */ * filesystem that is in use.
mounted_on->v_ref_count = 0; */
return EBUSY; /* already mounted */ return EBUSY; /* already mounted */
} }
if (root_dev == vmp->m_dev) if (root_dev == vmp->m_dev)
panic("fs", "inconsistency remounting old root", NO_NUM); panic("fs", "inconsistency remounting old root", NO_NUM);
/* Now get the inode of the file to be mounted on. */ /* Now get the inode of the file to be mounted on. */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
return(err_code); return(err_code);
} }
/* Fill in lookup request fields */ /* Request lookup */
lookup_req.path = user_fullpath; r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &Xmounted_on);
lookup_req.lastc = NULL; if (r != OK) return r;
lookup_req.flags = EAT_PATH;
/* Request lookup */ if (vp->v_ref_count != 1)
if ((r = lookup(&lookup_req, &res)) != OK) return r; {
put_vnode(vp);
printf("vfs:mount_fs: mount point is busy\n");
return EBUSY;
}
/* Fill in request message fields.*/ /* Issue mountpoint request */
mreq.fs_e = res.fs_e; r = req_mountpoint(Xmounted_on->v_fs_e, Xmounted_on->v_inode_nr);
mreq.inode_nr = res.inode_nr; if (r != OK)
mreq.uid = fp->fp_effuid; {
mreq.gid = fp->fp_effgid; put_vnode(Xmounted_on);
printf("vfs:mount_fs: req_mountpoint_s failed with %d\n", r);
return r;
}
/* Issue request */ /* Get the root inode of the mounted file system. */
if ((r = req_mountpoint(&mreq, &res)) != OK) return r; root_node = vmp->m_root_node;
mounted_on->v_fs_e = res.fs_e; /* File types may not conflict. */
mounted_on->v_inode_nr = res.inode_nr; if (r == OK) {
mounted_on->v_mode = res.fmode; mdir = ((Xmounted_on->v_mode & I_TYPE) == I_DIRECTORY);
mounted_on->v_size = res.fsize; /* TRUE iff dir */
mounted_on->v_sdev = NO_DEV; rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
mounted_on->v_fs_count = 1; if (!mdir && rdir) r = EISDIR;
mounted_on->v_ref_count = 1; }
/* Find the vmnt for the vnode */ /* If error, return the mount point. */
if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT) if (r != OK) {
printf("VFS: vmnt not found by mount()\n"); put_vnode(Xmounted_on);
mounted_on->v_vmnt = vmp2;
mounted_on->v_dev = vmp2->m_dev;
/* Get the root inode of the mounted file system. */ return(r);
root_node = vmp->m_root_node; }
/* File types may not conflict. */ /* Nothing else can go wrong. Perform the mount. */
if (r == OK) { put_vnode(vmp->m_mounted_on);
mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY); vmp->m_mounted_on = Xmounted_on;
/* TRUE iff dir */ vmp->m_flags = m_in.rd_only;
rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY); allow_newroot = 0; /* The root is now fixed */
if (!mdir && rdir) r = EISDIR;
}
/* If error, return the mount point. */ return(OK);
if (r != OK) { }
put_vnode(mounted_on);
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. */ isroot= (strcmp(user_fullpath, "/") == 0);
put_vnode(vmp->m_mounted_on); replace_root= (isroot && allow_newroot);
vmp->m_mounted_on = mounted_on;
vmp->m_flags = m_in.rd_only;
allow_newroot = 0; /* The root is now fixed */
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 */ /* 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; 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 */ /* Get driver process' endpoint */
dp = &dmap[(dev >> MAJOR) & BYTE]; 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); printf("VFSmount: no driver for dev %x\n", dev);
return(EINVAL); return(EINVAL);
} }
label= dp->dmap_label;
/* Open the device the file system lives on. */ if (strlen(label) == 0)
if (dev_open(dev, fs_e, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK) { {
return(EINVAL); 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 */ /* Issue request */
if ((r = req_readsuper(&sreq, &sres)) != OK) { r = req_readsuper(fs_e, label, dev, m_in.rd_only, isroot, &resX);
dev_close(dev); if (r != OK) {
return r; 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 */ /* Fill in root node's fields */
root_node->v_fs_e = res.fs_e; root_node->v_fs_e = resX.fs_e;
root_node->v_inode_nr = res.inode_nr; root_node->v_inode_nr = resX.inode_nr;
root_node->v_mode = res.fmode; root_node->v_mode = resX.fmode;
root_node->v_uid = res.uid; root_node->v_uid = resX.uid;
root_node->v_gid = res.gid; root_node->v_gid = resX.gid;
root_node->v_size = res.fsize; root_node->v_size = resX.fsize;
root_node->v_sdev = NO_DEV; root_node->v_sdev = NO_DEV;
root_node->v_fs_count = 2; root_node->v_fs_count = 1;
root_node->v_ref_count = 1; root_node->v_ref_count = 1;
/* Fill in max file size and blocksize for the vmnt */ /* 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_dev = dev;
vmp->m_block_size = sres.blocksize;
vmp->m_max_file_size = sres.maxsize;
vmp->m_flags = m_in.rd_only; vmp->m_flags = m_in.rd_only;
vmp->m_driver_e = dp->dmap_driver; 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_vmnt = vmp;
root_node->v_dev = vmp->m_dev; root_node->v_dev = vmp->m_dev;
if (strcmp(user_fullpath, "/") == 0 && allow_newroot) { if (replace_root) {
printf("Replacing root\n"); printf("Replacing root\n");
/* Superblock and root node already read. /* Superblock and root node already read.
@ -365,63 +340,24 @@ PRIVATE int mount_fs(endpoint_t fs_e)
return(OK); 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. */ /* File types may not conflict. */
if (r == OK) { 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); rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
if (!mdir && rdir) r = EISDIR; if (!mdir && rdir) r = EISDIR;
} }
/* If error, return the super block and both inodes; release the vmnt. */ /* If error, return the super block and both inodes; release the vmnt. */
if (r != OK) { if (r != OK) {
put_vnode(mounted_on); put_vnode(Xmounted_on);
put_vnode(root_node); put_vnode(root_node);
vmp->m_dev = NO_DEV; vmp->m_dev = NO_DEV;
dev_close(dev);
return(r); return(r);
} }
/* Nothing else can go wrong. Perform the mount. */ /* 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; vmp->m_root_node = root_node;
/* The root is now fixed */ /* The root is now fixed */
@ -500,9 +436,6 @@ Dev_t dev;
panic(__FILE__, "unmount: strange fs endpoint", vmp->m_fs_e); panic(__FILE__, "unmount: strange fs endpoint", vmp->m_fs_e);
if ((r = req_unmount(vmp->m_fs_e)) != OK) return r; 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? */ /* Is there a block special file that was handled by that partition? */
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL && 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); printf("VFSunmount: moving block spec %d to root FS\n", dev);
vp->v_bfs_e = ROOT_FS_E; vp->v_bfs_e = ROOT_FS_E;
vp->v_blocksize = _MIN_BLOCK_SIZE;
/* Send the driver endpoint (even if it is known already...) */ /* Send the driver endpoint (even if it is known already...) */
if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver)) 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' /* Convert the block special file 'path' to a device number. If 'path'
* is not a block special file, return error code in 'err_code'. */ * is not a block special file, return error code in 'err_code'. */
struct lookup_req lookup_req;
struct node_details res;
int r; 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 */ /* 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; err_code = ENOTBLK;
return NO_DEV; dev= NO_DEV;
} }
else
dev= vp->v_sdev;
put_vnode(vp);
return res.dev; return dev;
} }

View file

@ -38,6 +38,10 @@
FORWARD _PROTOTYPE( int x_open, (int bits, int oflags, int omode, FORWARD _PROTOTYPE( int x_open, (int bits, int oflags, int omode,
char *lastc, struct vnode **vpp) ); char *lastc, struct vnode **vpp) );
FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) ); 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)); 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) PRIVATE int common_open(register int oflags, mode_t omode)
{ {
/* Common code from do_creat and do_open. */ /* Common code from do_creat and do_open. */
int r, b, found; int b, m, r, created, found;
dev_t dev;
mode_t bits; mode_t bits;
off_t pos;
struct dmap *dp;
struct filp *fil_ptr, *filp2; struct filp *fil_ptr, *filp2;
struct vnode *vp, *vp2; struct vnode *vp;
struct vmnt *vmp; struct vmnt *vmp;
char Xlastc[NAME_MAX]; struct dmap *dp;
char *pathrem;
int m;
/* Request and response structures */
struct lookup_req Xlookup_req;
struct open_req Xreq;
/* Remap the bottom two bits of oflags. */ /* Remap the bottom two bits of oflags. */
m = oflags & O_ACCMODE; 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); omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
} }
vp= NULL; if (oflags & O_CREAT)
r= create_open(omode, &vp, &created);
/* Fill in lookup request fields */ else
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 (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 #if 0
else printf("vfs:common_open: path '%s'\n", user_fullpath);
{
printf("common_open: / in pathrem\n");
}
#endif #endif
} created= FALSE;
r= lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
} }
if (r != OK) if (r != OK)
return r;
if (!created)
{ {
if (vp) r= y_open(vp, bits, oflags);
if (r != OK)
{ {
put_vnode(vp); put_vnode(vp);
vp= NULL; return r;
} }
return r;
} }
if (!vp) panic(__FILE__, "common_open: no vp", NO_NUM);
r= x_open(bits, oflags, omode, Xlastc, &vp);
if (r != OK)
{
if (vp)
{
put_vnode(vp);
vp= NULL;
}
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. */ /* Claim the file descriptor and filp slot and fill them in. */
fp->fp_filp[m_in.fd] = fil_ptr; fp->fp_filp[m_in.fd] = fil_ptr;
FD_SET(m_in.fd, &fp->fp_filp_inuse); 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? */ /* Who is going to be responsible for this device? */
if (found) { if (found) {
vp->v_bfs_e = vmp->m_fs_e; 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 */ else { /* To be handled in the root FS proc if not mounted */
vp->v_bfs_e = ROOT_FS_E; vp->v_bfs_e = ROOT_FS_E;
vp->v_blocksize = _MIN_BLOCK_SIZE;
} }
/* Get the driver endpoint of the block spec device */ /* 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); return(m_in.fd);
} }
/*===========================================================================*
* create_open *
*===========================================================================*/
PRIVATE int create_open(omode, vpp, created)
mode_t omode;
struct vnode **vpp;
int *created;
{
int i, r, r1;
size_t len;
struct vnode *vp, *dir_vp, *new_vp, *start_vp;
struct node_details res;
char lastc[PATH_MAX+1];
start_vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
dup_vnode(start_vp);
for (i= 0; i<SYMLOOP_MAX; i++)
{
#if 0
printf("vfs:create_open: path #%d '%s'\n", i+1, user_fullpath);
#endif
r= lookup_lastdir_rel(start_vp, 0 /*!use_realuid*/, &dir_vp);
put_vnode(start_vp);
if (r != OK)
return r;
/* Save the last component of the path */
len= strlen(user_fullpath)+1;
if (len > sizeof(lastc))
{
put_vnode(dir_vp);
return ENAMETOOLONG;
}
memcpy(lastc, user_fullpath, len);
/* Get a free vnode */
new_vp = get_free_vnode(__FILE__, __LINE__);
if (new_vp == NIL_VNODE) {
put_vnode(dir_vp);
printf("vfs:create_open: no free vnode available\n");
return EINVAL;
}
r= forbidden(dir_vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (r == OK)
{
/* Try to create the file */
r= req_create(dir_vp->v_fs_e, dir_vp->v_inode_nr,
omode, fp->fp_effuid, fp->fp_effgid, lastc,
&res);
}
if (r != EEXIST && r != EACCES)
{
put_vnode(dir_vp);
if (r != OK)
return r;
/* Check whether vnode is already in use or not */
vp = find_vnode(res.fs_e, res.inode_nr);
if (vp != NIL_VNODE) {
vp->v_ref_count++;
vp->v_fs_count++;
}
else
{
vp= new_vp;
/* Fill in the free vnode's fields */
vp->v_fs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr;
vp->v_mode = res.fmode;
vp->v_size = res.fsize;
vp->v_uid = res.uid;
vp->v_gid = res.gid;
vp->v_sdev = res.dev;
vp->v_vmnt = dir_vp->v_vmnt;
vp->v_dev = vp->v_vmnt->m_dev;
vp->v_fs_count = 1;
vp->v_ref_count = 1;
}
*vpp= vp;
*created= TRUE;
return OK;
}
/* Try a regular lookup */
memcpy(user_fullpath, lastc, len);
r1= lookup_rel_vp(dir_vp, 0 /*flags*/, 0 /*!use_realuid*/, &vp);
if (r1 != ENOENT)
{
put_vnode(dir_vp);
if (r1 == OK)
{
*vpp= vp;
*created= FALSE;
}
return r1;
}
if (r == EACCES)
{
/* We cannot create a new file and the file does not
* already exist.
*/
put_vnode(dir_vp);
return r;
}
/* The create failed with EEXIST and the regular lookup
* failed with ENOENT. We have to see whether the object
* we try to access actually exists, but is a symlink that
* cannot be resolved. If the symlink exists, we start
* with the contents of the symlink.
*/
memcpy(user_fullpath, lastc, len);
r= lookup_rel_vp(dir_vp, PATH_RET_SYMLINK, 0 /*!use_realuid*/,
&vp);
if (r != OK)
{
put_vnode(dir_vp);
return r;
}
if (!S_ISLNK(vp->v_mode))
{
/* Strange, we got an object, but it is not a symlink.
* Well, just return the object.
*/
put_vnode(dir_vp);
*vpp= vp;
*created= FALSE;
return OK;
}
/* Get the contents of the link */
len= sizeof(user_fullpath);
r= req_rdlink(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR,
(vir_bytes)user_fullpath, len-1);
put_vnode(vp);
if (r < 0)
{
printf("vfs:create_open: req_rdlink failed with %d\n",
r);
put_vnode(dir_vp);
return r;
}
if (r >= len)
{
printf(
"vfs:create_open: got bad length %d from req_rdlink\n",
r);
r= len-1;
}
user_fullpath[r]= '\0';
printf("got link target '%s'\n", user_fullpath);
if (user_fullpath[0] == '/')
{
put_vnode(dir_vp);
start_vp= fp->fp_rd;
dup_vnode(start_vp);
}
else
start_vp= dir_vp;
}
put_vnode(start_vp);
return ELOOP;
}
/*===========================================================================* /*===========================================================================*
* x_open * * x_open *
*===========================================================================*/ *===========================================================================*/
@ -381,7 +469,7 @@ struct vnode **vpp;
vp->v_sdev = res.dev; vp->v_sdev = res.dev;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) 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_vmnt = vmp;
vp->v_dev = vmp->m_dev; vp->v_dev = vmp->m_dev;
@ -404,7 +492,7 @@ struct vnode **vpp;
return OK; return OK;
/* Check protections. */ /* Check protections. */
if ((r = forbidden(vp, bits)) != OK) if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK)
return r; return r;
/* Opening reg. files directories and special files differ. */ /* Opening reg. files directories and special files differ. */
@ -412,7 +500,7 @@ struct vnode **vpp;
case I_REGULAR: case I_REGULAR:
/* Truncate regular file if O_TRUNC. */ /* Truncate regular file if O_TRUNC. */
if (oflags & 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); truncate_vn(vp, 0);
} }
break; 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 * * pipe_open *
*===========================================================================*/ *===========================================================================*/
@ -492,11 +648,8 @@ PUBLIC int do_mknod()
{ {
/* Perform the mknod(name, mode, addr) system call. */ /* Perform the mknod(name, mode, addr) system call. */
register mode_t bits, mode_bits; 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; int r;
struct vnode *vp;
/* Only the super_user may make nodes other than fifos. */ /* Only the super_user may make nodes other than fifos. */
mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */ 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); 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); 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 */ /* 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 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;
/* Issue request */ /* 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. */ /* Perform the mkdir(name, mode) system call. */
mode_t bits; /* mode bits for the new inode */ 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; int r;
struct vnode *vp;
/*printf("VFS: mkdir() START:");*/ /*printf("VFS: mkdir() START:");*/
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); 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); 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 */ /* 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 */ /* 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; int r;
long offset; long offset;
u64_t pos, newpos; u64_t pos, newpos;
struct node_req req;
/* Check to see if the file descriptor is valid. */ /* Check to see if the file descriptor is valid. */
if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code); if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
@ -606,12 +746,8 @@ PUBLIC int do_lseek()
return EINVAL; return EINVAL;
if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
/* Fill in request message */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
req.fs_e = rfilp->filp_vno->v_fs_e; if (r != OK) return r;
req.inode_nr = rfilp->filp_vno->v_inode_nr;
/* Issue request */
if ((r = req_inhibread(&req)) != OK) return r;
} }
rfilp->filp_pos = newpos; rfilp->filp_pos = newpos;
@ -631,7 +767,6 @@ PUBLIC int do_llseek()
/* Perform the llseek(ls_fd, offset, whence) system call. */ /* Perform the llseek(ls_fd, offset, whence) system call. */
register struct filp *rfilp; register struct filp *rfilp;
u64_t pos, newpos; u64_t pos, newpos;
struct node_req req;
int r; int r;
/* Check to see if the file descriptor is valid. */ /* Check to see if the file descriptor is valid. */
@ -657,12 +792,8 @@ PUBLIC int do_llseek()
return(EINVAL); return(EINVAL);
if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
/* Fill in request message */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
req.fs_e = rfilp->filp_vno->v_fs_e; if (r != OK) return r;
req.inode_nr = rfilp->filp_vno->v_inode_nr;
/* Issue request */
if ((r = req_inhibread(&req)) != OK) return r;
} }
rfilp->filp_pos = newpos; rfilp->filp_pos = newpos;

View file

@ -52,6 +52,11 @@
#define pm_stime m1_i1 #define pm_stime m1_i1
#define info_what m1_i1 #define info_what m1_i1
#define info_where m1_p1 #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. */ /* The following names are synonyms for the variables in the output message. */
#define reply_type m_type #define reply_type m_type

View file

@ -21,126 +21,306 @@
#include "vnode.h" #include "vnode.h"
#include "param.h" #include "param.h"
FORWARD _PROTOTYPE( int Xlookup, (lookup_req_t *lookup_req, FORWARD _PROTOTYPE( int lookup_rel, (struct vnode *start_node,
node_details_t *node, char **pathrem) ); int flags, int use_realuid, node_details_t *node) );
/*===========================================================================* /*===========================================================================*
* lookup * * lookup_rel_vp *
*===========================================================================*/ *===========================================================================*/
PUBLIC int lookup(lookup_req, node) PUBLIC int lookup_rel_vp(start_node, flags, use_realuid, vpp)
lookup_req_t *lookup_req; struct vnode *start_node;
node_details_t *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 vmnt *vmp;
struct vnode *start_node; struct node_details res;
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;
/* Empty (start) path? */ /* See if free vnode is available */
if (fullpath[0] == '\0') { if ((new_vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
node->inode_nr = 0; printf("vfs:lookup_rel_vp: no free vnode available\n");
return ENOENT; *vpp= NULL;
return EINVAL;
} }
/* Set user and group ids according to the system call */ lookup_res = lookup_rel(start_node, flags, use_realuid, &res);
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 */ if (lookup_res != OK)
start_node = (fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); {
req.start_dir = start_node->v_inode_nr; #if 0
req.fs_e = start_node->v_fs_e; printf("vfs:lookup_rel_vp: lookup_rel failed with %d\n", lookup_res);
#endif
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++;
vp->v_fs_count++; /* We got a reference from the FS */
*vpp= vp;
return OK;
}
/* 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;
}
/*===========================================================================*
* 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;
vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
return lookup_rel_vp(vp, flags, use_realuid, vpp);
}
/*===========================================================================*
* lookup_lastdir_rel *
*===========================================================================*/
PUBLIC int lookup_lastdir_rel(start_node, use_realuid, vpp)
struct vnode *start_node;
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.
* 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;
}
/*===========================================================================*
* 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);
}
/*===========================================================================*
* 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 (user_fullpath[0] == '\0') {
node->inode_nr = 0;
printf("vfs:lookup_rel: returning ENOENT\n");
return ENOENT;
}
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?, /* Is the process' root directory on the same partition?,
* if so, set the chroot directory too. */ * if so, set the chroot directory too. */
if (fp->fp_rd->v_dev == fp->fp_wd->v_dev) 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 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 */ /* 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 /* While the response is related to mount control set the
* new requests respectively */ * new requests respectively */
while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) { while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
/* Save the place in the (possibly updated) path where we have to
/* If a symlink was encountered during the lookup the * continue witht henext lookup request.
* new path has been copied back and the number of characters */
* processed has been started over. */ path_off= res.char_processed;
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 */ /* Update the current value of the symloop counter */
symloop = res.symloop; symloop += res.symloop;
if (symloop > SYMLOOP_MAX)
{
printf("vfs:lookup_rel: returning ELOOP\n");
return ELOOP;
}
/* Symlink encountered with absolute path */ /* Symlink encountered with absolute path */
if (r == ESYMLINK) { if (r == ESYMLINK) {
start_node = fp->fp_rd; dir_vp = fp->fp_rd;
} }
/* Entering a new partition */ else if (r == EENTERMOUNT) {
else if (r == EENTERMOUNT) { /* Entering a new partition */
start_node = 0; dir_vp = 0;
/* Start node is now the mounted partition's root node */ /* Start node is now the mounted partition's root node */
for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) { for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
if (vmp->m_mounted_on->v_inode_nr == res.inode_nr if (vmp->m_mounted_on->v_inode_nr == res.inode_nr &&
&& vmp->m_mounted_on->v_fs_e == res.fs_e) { vmp->m_mounted_on->v_fs_e == res.fs_e) {
start_node = vmp->m_root_node; dir_vp = vmp->m_root_node;
break; break;
} }
} }
if (!start_node) { if (!dir_vp) {
printf("VFSlookup: mounted partition couldn't be found\n"); printf(
printf("VFSlookup: res.inode_nr = %d, res.fs_e = %d\n", "vfs:lookup_rel: res.inode_nr = %d, res.fs_e = %d\n",
res.inode_nr, res.fs_e); res.inode_nr, res.fs_e);
return ENOENT; panic(__FILE__,
} "vfs:lookup_s: mounted partition couldn't be found",
NO_NUM);
}
} }
/* Climbing up mount */ else {
else { /* Climbing up mount */
/* Find the vmnt that represents the partition on /* Find the vmnt that represents the partition on
* which we "climb up". */ * which we "climb up". */
if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) { if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
printf("VFS: couldn't find vmnt during the climbup!\n"); panic(__FILE__,
return ENOENT; "vfs:lookup_s: couldn't find vmnt during the climbup",
} NO_NUM);
/* Start node is the vnode on which the partition is }
* mounted */ /* Start node is the vnode on which the partition is
start_node = vmp->m_mounted_on; * mounted */
} dir_vp = 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?*/ /* Set the starting directories inode number and FS endpoint */
if (start_node->v_dev == fp->fp_rd->v_dev) fs_e = dir_vp->v_fs_e;
req.root_dir = fp->fp_rd->v_inode_nr; dir_ino = dir_vp->v_inode_nr;
else /* Is the process' root directory on the same partition?,
req.root_dir = 0; * 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;
/* Fill in the current path name */ /* Issue the request */
req.path = &fullpath[cum_path_processed]; r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags,
req.symloop = symloop; &res);
/* Issue the request */ if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
r = req_lookup(&req, &res); {
#if 0
printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r);
#endif
return r;
}
} }
/* Fill in response fields */ /* Fill in response fields */
@ -154,295 +334,3 @@ node_details_t *node;
return r; return r;
} }
/*===========================================================================*
* Xlookup *
*===========================================================================*/
PRIVATE int Xlookup(lookup_req, node, pathrem)
lookup_req_t *lookup_req;
node_details_t *node;
char **pathrem;
{
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;
/* Clear pathrem */
*pathrem= NULL;
/* Empty (start) path? */
if (fullpath[0] == '\0') {
node->inode_nr = 0;
*pathrem = fullpath;
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;
/* 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;
req.symloop = symloop;
/* 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);
}
if (r == ENOENT)
{
cum_path_processed += res.char_processed;
*pathrem= &fullpath[cum_path_processed];
}
/* 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;
}
/*===========================================================================*
* 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;
}

View file

@ -51,11 +51,8 @@ PUBLIC int do_pipe()
int r; int r;
struct filp *fil_ptr0, *fil_ptr1; struct filp *fil_ptr0, *fil_ptr1;
int fil_des[2]; /* reply goes here */ int fil_des[2]; /* reply goes here */
struct vnode *vp; struct vnode *vp;
struct vmnt *vmp; struct vmnt *vmp;
struct pipe_req req;
struct node_details res; struct node_details res;
/* See if a free vnode is available */ /* See if a free vnode is available */
@ -80,13 +77,9 @@ PUBLIC int do_pipe()
FD_SET(fil_des[1], &rfp->fp_filp_inuse); FD_SET(fil_des[1], &rfp->fp_filp_inuse);
fil_ptr1->filp_count = 1; 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 */ /* 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 */ /* Handle error */
if (r != OK) { if (r != OK) {
@ -105,8 +98,8 @@ PUBLIC int do_pipe()
vp->v_mode = res.fmode; vp->v_mode = res.fmode;
vp->v_index = res.inode_index; vp->v_index = res.inode_index;
vp->v_pipe = I_PIPE; vp->v_pipe = I_PIPE;
vp->v_fs_count = 2; /* Double usage */ vp->v_fs_count = 1;
vp->v_ref_count = 2; /* Double usage */ vp->v_ref_count = 1;
vp->v_size = 0; vp->v_size = 0;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) { if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) {
@ -120,6 +113,7 @@ PUBLIC int do_pipe()
/* Fill in filp objects */ /* Fill in filp objects */
fil_ptr0->filp_vno = vp; fil_ptr0->filp_vno = vp;
dup_vnode(vp);
fil_ptr1->filp_vno = vp; fil_ptr1->filp_vno = vp;
fil_ptr0->filp_flags = O_RDONLY; fil_ptr0->filp_flags = O_RDONLY;
fil_ptr1->filp_flags = O_WRONLY; fil_ptr1->filp_flags = O_WRONLY;
@ -133,13 +127,12 @@ PUBLIC int do_pipe()
/*===========================================================================* /*===========================================================================*
* pipe_check * * 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 */ register struct vnode *vp; /* the inode of the pipe */
int rw_flag; /* READING or WRITING */ int rw_flag; /* READING or WRITING */
int oflags; /* flags set by open or fcntl */ int oflags; /* flags set by open or fcntl */
register int bytes; /* bytes to be read or written (all chunks) */ register int bytes; /* bytes to be read or written (all chunks) */
u64_t position; /* current file position */ u64_t position; /* current file position */
int *canwrite; /* return: number of bytes we can write */
int notouch; /* check only */ int notouch; /* check only */
{ {
/* Pipes are a little different. If a process reads from an empty pipe for /* 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) { if (oflags & O_NONBLOCK) {
r = EAGAIN; r = EAGAIN;
} else { } else {
if (!notouch)
suspend(XPIPE); /* block reader */
r = SUSPEND; r = SUSPEND;
} }
/* If need be, activate sleeping writers. */ /* If need be, activate sleeping writers. */
@ -173,56 +164,65 @@ int notouch; /* check only */
} }
return(r); 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);
}
if (pos + bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) { return bytes;
if ((oflags & O_NONBLOCK)
&& bytes <= PIPE_SIZE(vp->v_vmnt->m_block_size)) {
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);
}
}
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);
} }
*canwrite = 0; /* Process is writing to a pipe. */
return(1); 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_BUF) {
if (oflags & O_NONBLOCK)
{
if (bytes <= PIPE_BUF) {
/* Write has to be atomic */
return(EAGAIN);
}
/* 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);
}
}
/* Pipe is full, or we need an atomic write */
return(SUSPEND);
}
/* 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(). * 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; fp->fp_suspended = SUSPENDED;
assert(!GRANT_VALID(fp->fp_grant)); assert(!GRANT_VALID(fp->fp_grant));
fp->fp_fd = m_in.fd << 8 | call_nr; 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 * * unsuspend_by_endpt *
*===========================================================================*/ *===========================================================================*/
@ -296,6 +324,10 @@ int count; /* max number of processes to release */
register struct fproc *rp; register struct fproc *rp;
struct filp *f; 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 /* Trying to perform the call also includes SELECTing on it with that
* operation. * operation.
*/ */
@ -481,15 +513,15 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
int orig_ops, r = 0, err, canwrite; int orig_ops, r = 0, err, canwrite;
orig_ops = *ops; orig_ops = *ops;
if ((*ops & (SEL_RD|SEL_ERR))) { if ((*ops & (SEL_RD|SEL_ERR))) {
if ((err = pipe_check(f->filp_vno, READING, 0, if ((err = Xpipe_check(f->filp_vno, READING, 0,
1, f->filp_pos, &canwrite, 1)) != SUSPEND) 1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_RD; r |= SEL_RD;
if (err < 0 && err != SUSPEND) if (err < 0 && err != SUSPEND)
r |= SEL_ERR; r |= SEL_ERR;
} }
if ((*ops & (SEL_WR|SEL_ERR))) { if ((*ops & (SEL_WR|SEL_ERR))) {
if ((err = pipe_check(f->filp_vno, WRITING, 0, if ((err = Xpipe_check(f->filp_vno, WRITING, 0,
1, f->filp_pos, &canwrite, 1)) != SUSPEND) 1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_WR; r |= SEL_WR;
if (err < 0 && err != SUSPEND) if (err < 0 && err != SUSPEND)
r |= SEL_ERR; r |= SEL_ERR;

View file

@ -31,47 +31,54 @@
PUBLIC int do_chmod() PUBLIC int do_chmod()
{ {
struct filp *flp; struct filp *flp;
struct chmod_req req;
struct lookup_req lookup_req;
struct node_details res;
struct vnode *vp; struct vnode *vp;
int r, ch_mode; int r;
uid_t uid;
gid_t gid;
mode_t new_mode;
if (call_nr == CHMOD) { if (call_nr == CHMOD) {
/* Perform the chmod(name, mode) system call. */ /* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); 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 */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
req.inode_nr = res.inode_nr;
req.fs_e = res.fs_e;
} }
else if (call_nr == FCHMOD) { else if (call_nr == FCHMOD) {
if (!(flp = get_filp(m_in.m3_i1))) return err_code; if (!(flp = get_filp(m_in.m3_i1))) return err_code;
req.inode_nr = flp->filp_vno->v_inode_nr; vp= flp->filp_vno;
req.fs_e = flp->filp_vno->v_fs_e; dup_vnode(vp);
} }
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
/* Find vnode, if it's in use. */ uid= fp->fp_effuid;
vp = find_vnode(req.fs_e, req.inode_nr); 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 */ /* 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) if (r == OK)
vp->v_mode = ch_mode; vp->v_mode = new_mode;
put_vnode(vp);
return OK; return OK;
} }
@ -84,52 +91,58 @@ PUBLIC int do_chown()
int inode_nr; int inode_nr;
int fs_e; int fs_e;
struct filp *flp; struct filp *flp;
struct chown_req req;
struct lookup_req lookup_req;
struct node_details res;
struct vnode *vp; struct vnode *vp;
int r, ch_mode; int r;
uid_t uid;
gid_t gid;
mode_t new_mode;
if (call_nr == CHOWN) { if (call_nr == CHOWN) {
/* Perform the chmod(name, mode) system call. */ /* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); 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 */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
req.inode_nr = res.inode_nr;
req.fs_e = res.fs_e;
} }
else if (call_nr == FCHOWN) { else if (call_nr == FCHOWN) {
if (!(flp = get_filp(m_in.m1_i1))) return err_code; if (!(flp = get_filp(m_in.m1_i1))) return err_code;
req.inode_nr = flp->filp_vno->v_inode_nr; vp= flp->filp_vno;
req.fs_e = flp->filp_vno->v_fs_e; dup_vnode(vp);
} }
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
/* Find vnode, if it's in use. */ uid= fp->fp_effuid;
vp = find_vnode(req.fs_e, req.inode_nr); 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 */ /* 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_uid = m_in.owner;
vp->v_gid = m_in.group; vp->v_gid = m_in.group;
vp->v_mode = ch_mode; vp->v_mode = new_mode;
} }
put_vnode(vp);
return r; return r;
} }
@ -154,10 +167,8 @@ PUBLIC int do_umask()
PUBLIC int do_access() PUBLIC int do_access()
{ {
/* Perform the access(name, mode) system call. */ /* Perform the access(name, mode) system call. */
struct access_req req;
struct lookup_req lookup_req;
struct node_details res;
int r; int r;
struct vnode *vp;
/* First check to see if the mode is correct. */ /* First check to see if the mode is correct. */
if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK) if ( (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); 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 */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; r = lookup_vp(0 /*flags*/, TRUE /*use_realuid*/, &vp);
if (r != OK) return r;
/* Fill in request fields */ r= forbidden(vp, m_in.mode, 1 /*use_realuid*/);
req.fs_e = res.fs_e; put_vnode(vp);
req.amode = m_in.mode; return r;
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);
} }
/*===========================================================================* /*===========================================================================*
* forbidden * * 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 /* 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 * 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 struct super_block *sp;
register mode_t bits, perm_bits; register mode_t bits, perm_bits;
uid_t uid;
gid_t gid;
int r, shift, type; int r, shift, type;
if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1) 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); printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line);
return EACCES; return EACCES;
} }
/* Isolate the relevant rwx bits from the mode. */ /* Isolate the relevant rwx bits from the mode. */
bits = vp->v_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 /* Grant read and write permission. Grant search permission for
* directories. Grant execute permission (for non-directories) if * directories. Grant execute permission (for non-directories) if
* and only if one of the 'X' bits is set. * 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 else
perm_bits = R_BIT | W_BIT; perm_bits = R_BIT | W_BIT;
} else { } else {
if (fp->fp_effuid == vp->v_uid) shift = 6; /* owner */ if (uid == vp->v_uid) shift = 6; /* owner */
else if (fp->fp_effgid == vp->v_gid ) shift = 3; /* group */ else if (gid == vp->v_gid ) shift = 3; /* group */
else shift = 0; /* other */ else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT); perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
} }

View file

@ -12,8 +12,6 @@ struct vnode;
/* device.c */ /* device.c */
_PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags) ); _PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags) );
_PROTOTYPE( void dev_close, (Dev_t dev) ); _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, _PROTOTYPE( int dev_io, (int op, Dev_t dev, int proc, void *buf,
u64_t pos, int bytes, int flags) ); u64_t pos, int bytes, int flags) );
_PROTOTYPE( int gen_opcl, (int op, Dev_t dev, int proc, 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 do_devctl, (void) );
_PROTOTYPE( int fs_devctl, (int req, int dev, int proc_nr_e, int style, _PROTOTYPE( int fs_devctl, (int req, int dev, int proc_nr_e, int style,
int force) ); int force) );
_PROTOTYPE( int do_mapdriver, (void) );
_PROTOTYPE( void build_dmap, (void) ); _PROTOTYPE( void build_dmap, (void) );
_PROTOTYPE( int map_driver, (int major, int proc_nr, int dev_style, _PROTOTYPE( int map_driver, (int major, int proc_nr, int dev_style,
int force) ); int force) );
@ -100,20 +99,25 @@ _PROTOTYPE( int do_open, (void) );
_PROTOTYPE( int do_slink, (void) ); _PROTOTYPE( int do_slink, (void) );
/* path.c */ /* path.c */
_PROTOTYPE( int lookup, (lookup_req_t *request, node_details_t *node) ); _PROTOTYPE( int lookup_rel_vp, (struct vnode *start_node, int flags,
_PROTOTYPE( int lookup_vp, (lookup_req_t *request, struct vnode **vpp) ); int use_realuid, struct vnode **vpp) );
_PROTOTYPE( int Xlookup_vp, (lookup_req_t *request, struct vnode **vpp, _PROTOTYPE( int lookup_vp, (int flags, int use_realuid,
char **pathrem) ); 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 */ /* pipe.c */
_PROTOTYPE( int do_pipe, (void) ); _PROTOTYPE( int do_pipe, (void) );
_PROTOTYPE( int do_unpause, (void) ); _PROTOTYPE( int do_unpause, (void) );
_PROTOTYPE( int unpause, (int proc_nr_e) ); _PROTOTYPE( int unpause, (int proc_nr_e) );
_PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag, _PROTOTYPE( int Xpipe_check, (struct vnode *vp, int rw_flag,
int oflags, int bytes, u64_t position, int *canwrite, int notouch)); int oflags, int bytes, u64_t position, int notouch) );
_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) ); _PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) );
_PROTOTYPE( void revive, (int proc_nr, int bytes) ); _PROTOTYPE( void revive, (int proc_nr, int bytes) );
_PROTOTYPE( void suspend, (int task) ); _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_request_pipe, (struct filp *f, int *ops, int bl) );
_PROTOTYPE( int select_cancel_pipe, (struct filp *f) ); _PROTOTYPE( int select_cancel_pipe, (struct filp *f) );
_PROTOTYPE( int select_match_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_chmod, (void) );
_PROTOTYPE( int do_chown, (void) ); _PROTOTYPE( int do_chown, (void) );
_PROTOTYPE( int do_umask, (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) ); _PROTOTYPE( int read_only, (struct vnode *vp) );
/* read.c */ /* read.c */
_PROTOTYPE( int do_read, (void) ); _PROTOTYPE( int do_read, (void) );
_PROTOTYPE( int do_getdents, (void) ); _PROTOTYPE( int do_getdents, (void) );
_PROTOTYPE( int read_write, (int rw_flag) ); _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 */ /* request.c */
#define req_getnode(req, res) req_getnode_f(__FILE__, __LINE__, (req), (res)) _PROTOTYPE( int req_breadwrite, (endpoint_t fs_e, endpoint_t user_e,
_PROTOTYPE( int req_getnode_f, (char *file, int line, node_req_t *req, node_details_t *res) ); Dev_t dev, u64_t pos, unsigned int num_of_bytes,
_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) ); char *user_addr, int rw_flag,
_PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res) ); 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, _PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode,
int uid, int gid, char *path, node_details_t *res) ); int uid, int gid, char *path, node_details_t *res) );
_PROTOTYPE( int req_readwrite, (readwrite_req_t *req, _PROTOTYPE( int req_flush, (endpoint_t fs_e, Dev_t dev) );
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_fstatfs, (int fs_e, ino_t inode_nr, int who_e, _PROTOTYPE( int req_fstatfs, (int fs_e, ino_t inode_nr, int who_e,
char *buf) ); char *buf) );
_PROTOTYPE( int req_unlink, (unlink_req_t *req) ); _PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr,
_PROTOTYPE( int req_rmdir, (unlink_req_t *req) ); off_t start, off_t end) );
_PROTOTYPE( int req_utime, (utime_req_t *req) );
_PROTOTYPE( int req_stime, (endpoint_t fs_e, time_t boottime) );
_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_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_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, _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) ); 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) ); _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_unlink, (endpoint_t fs_e, ino_t inode_nr,
char *lastc) );
_PROTOTYPE( int req_unmount, (endpoint_t fs_e) );
_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) );
/* stadir.c */ /* stadir.c */
_PROTOTYPE( int do_chdir, (void) ); _PROTOTYPE( int do_chdir, (void) );
@ -190,7 +212,6 @@ _PROTOTYPE( int do_rdlink, (void) );
_PROTOTYPE( int do_lstat, (void) ); _PROTOTYPE( int do_lstat, (void) );
/* time.c */ /* time.c */
_PROTOTYPE( int do_stime, (void) );
_PROTOTYPE( int do_utime, (void) ); _PROTOTYPE( int do_utime, (void) );
/* utility.c */ /* 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 dup_vnode, (struct vnode *vp) );
_PROTOTYPE( void put_vnode, (struct vnode *vp) ); _PROTOTYPE( void put_vnode, (struct vnode *vp) );
_PROTOTYPE( void vnode_clean_refs, (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, (int fs_e, int inode_nr) );
_PROTOTYPE( struct vnode *get_vnode_x, (int fs_e, int inode_nr) ); _PROTOTYPE( struct vnode *get_vnode_x, (int fs_e, int inode_nr) );
#endif
#if 0 #if 0
_PROTOTYPE( void mark_vn, (struct vnode *vp, char *file, int line) ); _PROTOTYPE( void mark_vn, (struct vnode *vp, char *file, int line) );
_PROTOTYPE( int check_vrefs, (void) ); _PROTOTYPE( int check_vrefs, (void) );

View file

@ -27,7 +27,6 @@
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
/*===========================================================================* /*===========================================================================*
* do_read * * do_read *
*===========================================================================*/ *===========================================================================*/
@ -47,70 +46,74 @@ int rw_flag; /* READING or WRITING */
register struct filp *f; register struct filp *f;
register struct vnode *vp; register struct vnode *vp;
off_t bytes_left; off_t bytes_left;
u64_t position; u64_t position, res_pos, new_pos;
unsigned int off, cum_io; unsigned int off, cum_io, cum_io_incr, res_cum_io, num_of_bytes;
int op, oflags, r, chunk, usr, seg, block_spec, char_spec; int op, oflags, r, chunk, usr, block_spec, char_spec;
int regular, partial_pipe = 0, partial_cnt = 0; int regular;
mode_t mode_word; mode_t mode_word;
struct filp *wf;
phys_bytes p; phys_bytes p;
struct dmap *dp; 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 /* PM loads segments by putting funny things in other bits of the
* message, indicated by a high bit in fd. */ * message, indicated by a high bit in fd. */
if (who_e == PM_PROC_NR && (m_in.fd & _PM_SEG_FLAG)) { if (who_e == PM_PROC_NR && (m_in.fd & _PM_SEG_FLAG)) {
seg = (int) m_in.m1_p2; panic(__FILE__,
usr = (int) m_in.m1_p3; "read_write: special read/write calls by PM no longer supported",
m_in.fd &= ~(_PM_SEG_FLAG); /* get rid of flag bit */ NO_NUM);
} }
else { else {
usr = who_e; /* normal case */ usr = who_e; /* normal case */
seg = D;
} }
/* If the file descriptor is valid, get the vnode, size and mode. */ /* If the file descriptor is valid, get the vnode, size and mode. */
if (m_in.nbytes < 0) return(EINVAL); if (m_in.nbytes < 0)
if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code); 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) { 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); return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
} }
if (m_in.nbytes == 0) if (m_in.nbytes == 0)
return(0); /* so char special files need not check for 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; position = f->filp_pos;
oflags = f->filp_flags; oflags = f->filp_flags;
vp = f->filp_vno; vp = f->filp_vno;
r = OK; if (vp->v_pipe)
if (vp->v_pipe == I_PIPE) { {
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */ if (rw_flag == WRITING)
cum_io = fp->fp_cum_io_partial; {
} if (vp->v_w_pipe_busy)
else { {
cum_io = 0; 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); op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
mode_word = vp->v_mode & I_TYPE; 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 ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
if (vp->v_sdev == NO_DEV) if (vp->v_sdev == NO_DEV)
@ -138,83 +141,49 @@ int rw_flag; /* READING or WRITING */
} }
/* Block special files. */ /* Block special files. */
else if (block_spec) { 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 */ /* 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; position = res_pos;
cum_io += res.cum_io; cum_io += res_cum_io;
} }
/* Regular files (and pipes) */ /* Regular files */
else { else {
if (rw_flag == WRITING && block_spec == 0) { if (rw_flag == WRITING && block_spec == 0) {
/* Check for O_APPEND flag. */ /* Check for O_APPEND flag. */
if (oflags & O_APPEND) position = cvul64(vp->v_size); 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 */ /* Fill in request structure */
req.fs_e = vp->v_fs_e; num_of_bytes = m_in.nbytes;
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;
/* Truncate read request at size (mustn't do this for special files). */ /* Truncate read request at size (mustn't do this for special files). */
if((rw_flag == READING) && if((rw_flag == READING) &&
cmp64ul(add64ul(position, req.num_of_bytes), vp->v_size) > 0) { cmp64ul(add64ul(position, num_of_bytes), vp->v_size) > 0) {
/* Position always should fit in an off_t (LONG_MAX). */ /* Position always should fit in an off_t (LONG_MAX). */
off_t pos32; off_t pos32;
assert(cmp64ul(position, LONG_MAX) <= 0); assert(cmp64ul(position, LONG_MAX) <= 0);
pos32 = cv64ul(position); pos32 = cv64ul(position);
assert(pos32 >= 0); assert(pos32 >= 0);
assert(pos32 <= LONG_MAX); assert(pos32 <= LONG_MAX);
req.num_of_bytes = vp->v_size - pos32; num_of_bytes = vp->v_size - pos32;
assert(req.num_of_bytes >= 0); assert(num_of_bytes >= 0);
} }
/* Issue request */ /* 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 (r >= 0)
{ {
if (ex64hi(res.new_pos)) if (ex64hi(new_pos))
panic(__FILE__, "read_write: bad new pos", NO_NUM); panic(__FILE__, "read_write: bad new pos", NO_NUM);
position = res.new_pos; position = new_pos;
cum_io += res.cum_io; 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; f->filp_pos = position;
if (r == OK) { 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; 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 * * 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;
}

File diff suppressed because it is too large Load diff

View file

@ -7,27 +7,20 @@
#include <sys/types.h> #include <sys/types.h>
/* Structure for REQ_GETNODE and REQ_PUTNODE requests */
typedef struct node_req {
endpoint_t fs_e;
ino_t inode_nr;
} node_req_t;
/* Structure for response that contains inode details */ /* Structure for response that contains inode details */
typedef struct node_details { typedef struct node_details {
endpoint_t fs_e; endpoint_t fs_e;
ino_t inode_nr; ino_t inode_nr;
mode_t fmode; mode_t fmode;
off_t fsize; off_t fsize;
unsigned short inode_index;
/* For char/block special files */
dev_t dev;
/* Fields used by the exec() syscall */
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
time_t ctime;
/* For faster access */
unsigned short inode_index;
/* For char/block special files */
dev_t dev;
} node_details_t; } node_details_t;
@ -43,35 +36,6 @@ typedef struct open_req {
} open_req_t; } open_req_t;
/* Structure for REQ_READ and REQ_WRITE request */
typedef struct readwrite_req {
int rw_flag;
endpoint_t fs_e;
endpoint_t user_e;
ino_t inode_nr;
unsigned short inode_index;
int seg;
u64_t pos;
unsigned int num_of_bytes;
char *user_addr;
} readwrite_req_t;
/* Structure for response of REQ_READ and REQ_WRITE */
typedef struct readwrite_res {
u64_t new_pos;
unsigned int cum_io;
} readwrite_res_t;
/* Structure for REQ_PIPE request */
typedef struct pipe_req {
int fs_e;
uid_t uid;
gid_t gid;
} pipe_req_t;
/* Structure for REQ_CLONE_OPCL request */ /* Structure for REQ_CLONE_OPCL request */
typedef struct clone_opcl_req { typedef struct clone_opcl_req {
int fs_e; int fs_e;
@ -79,147 +43,6 @@ typedef struct clone_opcl_req {
} clone_opcl_req_t; } 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 */ /* Structure for REQ_READSUPER request */
typedef struct readsuper_req { typedef struct readsuper_req {
endpoint_t fs_e; endpoint_t fs_e;
@ -242,16 +65,6 @@ typedef struct readsuper_res {
} readsuper_res_t; } 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 */ /* Structure for REQ_LOOKUP request */
typedef struct lookup_req { typedef struct lookup_req {
/* Fields filled in by the caller */ /* Fields filled in by the caller */
@ -285,19 +98,4 @@ typedef struct lookup_res {
} lookup_res_t; } 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 */ /* Structure for REQ_ request */

View file

@ -47,7 +47,7 @@ PUBLIC int do_fchdir()
return ENOTDIR; return ENOTDIR;
/* Issue request and handle error */ /* 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; if (r != OK) return r;
rfilp->filp_vno->v_ref_count++; /* change_into expects a reference */ 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(). */ /* Do the actual work for chdir() and chroot(). */
struct vnode *vp; struct vnode *vp;
struct lookup_req lookup_req;
int r; int r;
if (fetch_name(name_ptr, len, M3) != OK) return(err_code); 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 */ /* 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? */ /* Is it a dir? */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY) if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
@ -143,7 +137,7 @@ int len; /* length of the directory name string */
} }
/* Access check */ /* Access check */
r = forbidden(vp, X_BIT); r = forbidden(vp, X_BIT, 0 /*!use_realuid*/);
if (r != OK) { if (r != OK) {
put_vnode(vp); put_vnode(vp);
return r; return r;
@ -174,22 +168,19 @@ struct vnode *vp; /* this is what the inode has to become */
PUBLIC int do_stat() PUBLIC int do_stat()
{ {
/* Perform the stat(name, buf) system call. */ /* Perform the stat(name, buf) system call. */
struct node_details res;
struct lookup_req lookup_req;
int r; int r;
struct vnode *vp;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); 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 */ /* 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 */ /* 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() PUBLIC int do_lstat()
{ {
/* Perform the lstat(name, buf) system call. */ /* Perform the lstat(name, buf) system call. */
struct node_details res;
struct lookup_req lookup_req; struct lookup_req lookup_req;
struct vnode *vp;
int r; int r;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); 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; lookup_req.flags = EAT_PATH_OPAQUE;
/* Request lookup */ /* 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 */ /* 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;
} }

View file

@ -18,6 +18,7 @@
* A super_block slot is free if s_dev == NO_DEV. * A super_block slot is free if s_dev == NO_DEV.
*/ */
#if 0
EXTERN struct super_block { EXTERN struct super_block {
ino_t s_ninodes; /* # usable inodes on the minor device */ ino_t s_ninodes; /* # usable inodes on the minor device */
zone1_t s_nzones; /* total device size, including bit maps etc */ 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_isearch; /* inodes below this bit number are in use */
bit_t s_zsearch; /* all zones below this bit number are in use*/ bit_t s_zsearch; /* all zones below this bit number are in use*/
} super_block[NR_SUPERS]; } super_block[NR_SUPERS];
#endif
#define NIL_SUPER (struct super_block *) 0 #define NIL_SUPER (struct super_block *) 0
#define IMAP 0 /* operating on the inode bit map */ #define IMAP 0 /* operating on the inode bit map */

View file

@ -41,7 +41,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
do_umount, /* 22 = umount */ do_umount, /* 22 = umount */
no_sys, /* 23 = (setuid) */ no_sys, /* 23 = (setuid) */
no_sys, /* 24 = getuid */ no_sys, /* 24 = getuid */
do_stime, /* 25 = stime */ no_sys, /* 25 = (stime) */
no_sys, /* 26 = ptrace */ no_sys, /* 26 = ptrace */
no_sys, /* 27 = alarm */ no_sys, /* 27 = alarm */
do_fstat, /* 28 = fstat */ do_fstat, /* 28 = fstat */

View file

@ -11,6 +11,7 @@
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include "vnode.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vmnt.h" #include "vmnt.h"
@ -22,10 +23,10 @@ PUBLIC int do_utime()
{ {
/* Perform the utime(name, timep) system call. */ /* Perform the utime(name, timep) system call. */
register int len; register int len;
struct utime_req req;
struct lookup_req lookup_req;
struct node_details res;
int r; int r;
uid_t uid;
time_t actime, modtime;
struct vnode *vp;
/* Adjust for case of 'timep' being NULL; /* Adjust for case of 'timep' being NULL;
* utime_strlen then holds the actual size: strlen(name)+1. * 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); 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 */ /* 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.*/ /* Fill in request fields.*/
if (m_in.utime_length == 0) { if (m_in.utime_length == 0) {
req.actime = 0; actime = modtime = clock_time();
req.modtime = clock_time();
} else { } else {
req.actime = m_in.utime_actime; actime = m_in.utime_actime;
req.modtime = m_in.utime_modtime; modtime = m_in.utime_modtime;
}
uid= fp->fp_effuid;
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*/);
}
if (r != OK)
{
put_vnode(vp);
return r;
} }
req.fs_e = res.fs_e;
req.inode_nr = res.inode_nr;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
/* Issue request */ /* Issue request */
return req_utime(&req); r= req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
} put_vnode(vp);
return r;
/*===========================================================================*
* 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);
}
return OK;
} }

View file

@ -21,3 +21,13 @@ typedef struct { /* V2.x disk inode */
time_t d2_ctime; /* when was inode data last changed */ 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 */ zone_t d2_zone[V2_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
} d2_inode; } 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

View file

@ -143,10 +143,14 @@ PUBLIC time_t clock_time()
* rate and that such things as leap seconds do not exist. * rate and that such things as leap seconds do not exist.
*/ */
register int k; register int r;
clock_t uptime; 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))); return( (time_t) (boottime + (uptime/HZ)));
} }

View file

@ -5,8 +5,6 @@ EXTERN struct vmnt {
dev_t m_dev; /* device number */ dev_t m_dev; /* device number */
int m_driver_e; /* device driver process' kernel endpoint */ int m_driver_e; /* device driver process' kernel endpoint */
int m_flags; /* mount flags */ 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_mounted_on; /* the vnode on which the partition is mounted */
struct vnode *m_root_node; /* root vnode */ struct vnode *m_root_node; /* root vnode */
} vmnt[NR_MNTS]; } vmnt[NR_MNTS];

View file

@ -19,86 +19,6 @@
#include <minix/vfsif.h> #include <minix/vfsif.h>
/*===========================================================================*
* get_vnode *
*===========================================================================*/
PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr)
{
/* get_vnode() is called to get the details of the specified inode.
* Note that inode's usage counter in the FS is supposed to be incremented.
*/
struct vnode *vp, *vp2;
struct vmnt *vmp;
/* Request & response structures */
struct node_req req;
struct node_details res;
/* XXX remove this when debugging is complete */
if (find_vnode(fs_e, inode_nr) != NULL)
panic(__FILE__, "get_vnode: vnode already present", NO_NUM);
/* Check whether a free vnode is avaliable */
if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
printf("VFSget_vnode: no vnode available\n");
return NIL_VNODE;
}
/* Fill req struct */
req.inode_nr = inode_nr;
req.fs_e = fs_e;
/* Send request to FS */
if (req_getnode(&req, &res) != OK) {
printf("VFSget_vnode: couldn't find vnode\n");
return NIL_VNODE;
}
/* Fill in the free vnode's fields and return it */
vp->v_fs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr;
vp->v_mode = res.fmode;
vp->v_size = res.fsize;
vp->v_sdev = res.dev;
/* Find corresponding virtual mount object */
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
printf("VFS: vmnt not found by get_vnode()\n");
vp->v_vmnt = vmp;
vp->v_dev = vmp->m_dev;
vp->v_fs_count = 1;
vp->v_ref_count = 1;
return vp;
}
/*===========================================================================*
* get_vnode *
*===========================================================================*/
PUBLIC struct vnode *get_vnode_x(int fs_e, int inode_nr)
{
/* get_vnode() is called to get the details of the specified inode.
* Note that inode's usage counter in the FS is supposed to be incremented.
*/
struct vnode *vp, *vp2;
struct vmnt *vmp;
/* Request & response structures */
struct node_req req;
struct node_details res;
vp= find_vnode(fs_e, inode_nr);
if (vp)
{
vp->v_ref_count++;
return vp;
}
return get_vnode(fs_e, inode_nr);
}
/*===========================================================================* /*===========================================================================*
* get_free_vnode * * get_free_vnode *
@ -114,6 +34,7 @@ int line;
if (vp->v_ref_count == 0) if (vp->v_ref_count == 0)
{ {
vp->v_pipe= NO_PIPE; vp->v_pipe= NO_PIPE;
vp->v_w_pipe_busy= FALSE;
vp->v_uid= -1; vp->v_uid= -1;
vp->v_gid= -1; vp->v_gid= -1;
vp->v_sdev= -1; vp->v_sdev= -1;

View file

@ -11,6 +11,7 @@ EXTERN struct vnode {
int v_fs_count; /* # reference at the underlying FS */ int v_fs_count; /* # reference at the underlying FS */
int v_ref_check; /* for consistency checks */ int v_ref_check; /* for consistency checks */
char v_pipe; /* set to I_PIPE if pipe */ 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_rd_pos;
off_t v_pipe_wr_pos; off_t v_pipe_wr_pos;
endpoint_t v_bfs_e; /* endpoint number for the FS proces in case endpoint_t v_bfs_e; /* endpoint number for the FS proces in case
@ -20,7 +21,6 @@ EXTERN struct vnode {
inode resides */ inode resides */
Dev_t v_sdev; /* device number for special files */ 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 */ unsigned short v_index; /* inode's index in the FS inode table */
struct vmnt *v_vmnt; /* vmnt object of the partition */ struct vmnt *v_vmnt; /* vmnt object of the partition */