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 NR_DIR_ENTRIES(b) ((b)/DIR_ENTRY_SIZE) /* # dir entries/blk */
#define SUPER_SIZE usizeof (struct super_block) /* super_block size */
#define PIPE_SIZE(b) (V1_NR_DZONES*(b)) /* pipe size in bytes */
#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk */
#define FS_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT)
@ -109,7 +108,7 @@
#define V2_INDIRECTS(b) ((b)/V2_ZONE_NUM_SIZE) /* # zones/indir block */
#define V2_INODES_PER_BLOCK(b) ((b)/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
/* Args to dev_bio/dev_io */
/* Args to dev_io */
#define VFS_DEV_READ 2001
#define VFS_DEV_WRITE 2002
#define VFS_DEV_SCATTER 2003

View file

@ -303,125 +303,6 @@ int gids_size;
return;
}
#if 0
/*===========================================================================*
* dev_bio *
*===========================================================================*/
PUBLIC int dev_bio(op, dev, proc_e, buf, pos, bytes)
int op; /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
dev_t dev; /* major-minor device number */
int proc_e; /* in whose address space is buf? */
void *buf; /* virtual address of the buffer */
off_t pos; /* byte position */
int bytes; /* how many bytes to transfer */
{
/* Read or write from a device. The parameter 'dev' tells which one. */
struct dmap *dp;
int r, safe;
message m;
iovec_t *v;
cp_grant_id_t gid = GRANT_INVALID;
int vec_grants;
/* Determine task dmap. */
dp = &dmap[(dev >> MAJOR) & BYTE];
/* The io vector copying relies on this I/O being for FS itself. */
if(proc_e != FS_PROC_NR)
panic(__FILE__, "doing dev_bio for non-self", proc_e);
for (;;)
{
int op_used;
void *buf_used;
static cp_grant_id_t gids[NR_IOREQS];
cp_grant_id_t gid = GRANT_INVALID;
int vec_grants;
/* See if driver is roughly valid. */
if (dp->dmap_driver == NONE) {
printf("FS: dev_io: no driver for dev %x\n", dev);
return ENXIO;
}
/* By default, these are right. */
m.IO_ENDPT = proc_e;
m.ADDRESS = buf;
buf_used = buf;
/* Convert parameters to 'safe mode'. */
op_used = op;
safe = safe_io_conversion(dp->dmap_driver, &gid,
&op_used, gids, NR_IOREQS, &m.IO_ENDPT, &buf_used,
&vec_grants, bytes, &pos);
/* Set up rest of the message. */
if(safe) m.IO_GRANT = (char *) gid;
m.m_type = op_used;
m.DEVICE = (dev >> MINOR) & BYTE;
m.POSITION = pos;
m.COUNT = bytes;
m.HIGHPOS = 0;
/* Call the task. */
(*dp->dmap_io)(dp->dmap_driver, &m);
/* As block I/O never SUSPENDs, safe cleanup must be done whether
* the I/O succeeded or not.
*/
if(safe) safe_io_cleanup(gid, gids, vec_grants);
if(dp->dmap_driver == NONE) {
/* Driver has vanished. Wait for a new one. */
for (;;)
{
r= receive(RS_PROC_NR, &m);
if (r != OK)
{
panic(__FILE__,
"dev_bio: unable to receive from RS",
r);
}
if (m.m_type == DEVCTL)
{
r= fs_devctl(m.ctl_req, m.dev_nr, m.driver_nr,
m.dev_style, m.m_force);
}
else
{
panic(__FILE__,
"dev_bio: got message from RS, type",
m.m_type);
}
m.m_type= r;
r= send(RS_PROC_NR, &m);
if (r != OK)
{
panic(__FILE__,
"dev_bio: unable to send to RS",
r);
}
if (dp->dmap_driver != NONE)
break;
}
printf("dev_bio: trying new driver\n");
continue;
}
/* Task has completed. See if call completed. */
if (m.REP_STATUS == SUSPEND) {
panic(__FILE__, "dev_bio: driver returned SUSPEND", NO_NUM);
}
if(buf != buf_used) {
memcpy(buf, buf_used, bytes * sizeof(iovec_t));
}
return(m.REP_STATUS);
}
}
#endif
/*===========================================================================*
* dev_io *
@ -803,12 +684,12 @@ int flags; /* mode bits and flags */
if (dp->dmap_driver == NONE) {
printf("FS: clone_opcl: no driver for dev %x\n", dev);
printf("vfs:clone_opcl: no driver for dev %x\n", dev);
return ENXIO;
}
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
printf("FS: clone_opcl: old driver for dev %x (%d)\n",
printf("vfs:clone_opcl: bad driver endpoint for dev %x (%d)\n",
dev, dp->dmap_driver);
return ENXIO;
}
@ -822,22 +703,21 @@ int flags; /* mode bits and flags */
if (dev_mess.REP_STATUS != minor) {
struct vnode *vp;
struct vmnt *vmp;
struct clone_opcl_req req;
struct node_details res;
/* A new minor device number has been returned.
* Request root FS to create a temporary device file to hold it.
* Request the root FS to create a temporary device file to
* hold it.
*/
/* Device number of the new device. */
dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
/* Fill in request */
req.fs_e = ROOT_FS_E;
req.dev = dev;
dev = (dev & ~(BYTE << MINOR)) |
(dev_mess.REP_STATUS << MINOR);
/* Issue request */
if ((r = req_clone_opcl(&req, &res)) != OK) {
r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid,
ALL_MODES | I_CHAR_SPECIAL, dev, &res);
if (r != OK) {
(void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
return r;
}
@ -847,17 +727,19 @@ int flags; /* mode bits and flags */
put_vnode(vp);
if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
printf("VFSclone_opcl: failed to get a free vnode..\n");
printf(
"vfs:clone_opcl: failed to get a free vnode..\n");
vp = fp->fp_filp[m_in.fd]->filp_vno;
}
vp->v_fs_e = res.fs_e;
if ((vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
printf("VFSclone_opcl: no vmnt found\n");
printf("vfs:clone_opcl: no vmnt found\n");
vp->v_vmnt = vmp;
vp->v_dev = vmp->m_dev;
vp->v_fs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr;
vp->v_mode = res.fmode;
vp->v_sdev = dev;
@ -870,6 +752,7 @@ int flags; /* mode bits and flags */
return(dev_mess.REP_STATUS);
}
/*===========================================================================*
* dev_up *
*===========================================================================*/

View file

@ -10,12 +10,13 @@
#include <ctype.h>
#include <unistd.h>
#include <minix/com.h>
#include <minix/ds.h>
#include "param.h"
/* Some devices may or may not be there in the next table. */
#define DT(enable, opcl, io, driver, flags) \
#define DT(enable, opcl, io, driver, flags, label) \
{ (enable?(opcl):no_dev), (enable?(io):0), \
(enable?(driver):0), (flags) },
(enable?(driver):0), (flags), label },
#define NC(x) (NR_CTRLRS >= (x))
/* The order of the entries here determines the mapping between major device
@ -32,29 +33,32 @@
*/
struct dmap dmap[NR_DEVICES]; /* actual map */
PRIVATE struct dmap init_dmap[] = {
DT(1, no_dev, 0, 0, 0) /* 0 = not used */
DT(1, gen_opcl, gen_io, MEM_PROC_NR, 0) /* 1 = /dev/mem */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /* 2 = /dev/fd0 */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /* 3 = /dev/c0 */
DT(1, tty_opcl, gen_io, TTY_PROC_NR, 0) /* 4 = /dev/tty00 */
DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0) /* 5 = /dev/tty */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 6 = /dev/lp */
DT(1, no_dev, 0, 0, 0, "") /* 0 = not used */
DT(1, gen_opcl, gen_io, MEM_PROC_NR, 0, "memory") /* 1 = /dev/mem */
DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /* 2 = /dev/fd0 */
DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /* 3 = /dev/c0 */
DT(1, tty_opcl, gen_io, TTY_PROC_NR, 0, "") /* 4 = /dev/tty00 */
DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0, "") /* 5 = /dev/tty */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 6 = /dev/lp */
#if (MACHINE == IBM_PC)
DT(1, no_dev, 0, 0, DMAP_MUTABLE) /* 7 = /dev/ip */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 8 = /dev/c1 */
DT(0, 0, 0, 0, DMAP_MUTABLE) /* 9 = not used */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /*10 = /dev/c2 */
DT(0, 0, 0, 0, DMAP_MUTABLE) /*11 = not used */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*12 = /dev/c3 */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*13 = /dev/audio */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*14 = /dev/mixer */
DT(1, gen_opcl, gen_io, LOG_PROC_NR, 0) /*15 = /dev/klog */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*16 = /dev/random*/
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*17 = /dev/cmos */
DT(1, no_dev, 0, 0, DMAP_MUTABLE, "") /* 7 = /dev/ip */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 8 = /dev/c1 */
DT(0, 0, 0, 0, DMAP_MUTABLE, "") /* 9 = not used */
DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /*10 = /dev/c2 */
DT(0, 0, 0, 0, DMAP_MUTABLE, "") /*11 = not used */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*12 = /dev/c3 */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*13 = /dev/audio */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*14 = /dev/mixer */
DT(1, gen_opcl, gen_io, LOG_PROC_NR, 0, "") /*15 = /dev/klog */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*16 = /dev/random*/
DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*17 = /dev/cmos */
#endif /* IBM_PC */
};
FORWARD _PROTOTYPE( int map_driverX, (char *label, int major,
endpoint_t proc_nr_e, int style, int force) );
/*===========================================================================*
* do_devctl *
*===========================================================================*/
@ -116,6 +120,77 @@ int force;
return(result);
}
/*===========================================================================*
* do_mapdriver *
*===========================================================================*/
PUBLIC int do_mapdriver()
{
int r, force, major, proc_nr_n;
unsigned long tasknr;
vir_bytes label_vir;
size_t label_len;
char label[16];
if (!super_user)
{
printf("FS: unauthorized call of do_mapdriver by proc %d\n",
who_e);
return(EPERM); /* only su (should be only RS or some drivers)
* may call do_mapdriver.
*/
}
/* Get the label */
label_vir= (vir_bytes)m_in.md_label;
label_len= m_in.md_label_len;
if (label_len+1 > sizeof(label))
{
printf("vfs:do_mapdriver: label too long\n");
return EINVAL;
}
r= sys_vircopy(who_e, D, label_vir, SELF, D, (vir_bytes)label,
label_len);
if (r != OK)
{
printf("vfs:do_mapdriver: sys_vircopy failed: %d\n", r);
return EINVAL;
}
label[label_len]= '\0';
r= ds_retrieve_u32(label, &tasknr);
if (r != OK)
{
printf("vfs:do_mapdriver: ds doesn't know '%s'\n", label);
return EINVAL;
}
if (isokendpt(tasknr, &proc_nr_n) != OK)
return(EINVAL);
/* Try to update device mapping. */
major= m_in.md_major;
force= m_in.md_force;
r= map_driverX(label, major, tasknr, m_in.md_style, force);
if (r == OK)
{
/* If a driver has completed its exec(), it can be announced
* to be up.
*/
if(force || fproc[proc_nr_n].fp_execced) {
dev_up(major);
} else {
dmap[major].dmap_flags |= DMAP_BABY;
}
}
return(r);
}
/*===========================================================================*
* map_driver *
*===========================================================================*/
@ -176,6 +251,74 @@ int force;
return(OK);
}
/*===========================================================================*
* map_driverX *
*===========================================================================*/
PRIVATE int map_driverX(label, major, proc_nr_e, style, force)
char *label; /* name of the driver */
int major; /* major number of the device */
endpoint_t proc_nr_e; /* process number of the driver */
int style; /* style of the device */
int force;
{
/* Set a new device driver mapping in the dmap table. Given that correct
* arguments are given, this only works if the entry is mutable and the
* current driver is not busy. If the proc_nr is set to NONE, we're supposed
* to unmap it.
*
* Normal error codes are returned so that this function can be used from
* a system call that tries to dynamically install a new driver.
*/
int proc_nr_n;
size_t len;
struct dmap *dp;
/* Get pointer to device entry in the dmap table. */
if (major < 0 || major >= NR_DEVICES) return(ENODEV);
dp = &dmap[major];
/* Check if we're supposed to unmap it. If so, do it even
* if busy or unmutable, as unmap is called when driver has
* exited.
*/
if(proc_nr_e == NONE) {
dp->dmap_opcl = no_dev;
dp->dmap_io = no_dev_io;
dp->dmap_driver = NONE;
dp->dmap_flags = DMAP_MUTABLE; /* When gone, not busy or reserved. */
return(OK);
}
/* See if updating the entry is allowed. */
if (! (dp->dmap_flags & DMAP_MUTABLE)) return(EPERM);
if (dp->dmap_flags & DMAP_BUSY) return(EBUSY);
if (!force)
{
/* Check process number of new driver. */
if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
return(EINVAL);
}
len= strlen(label);
if (len+1 > sizeof(dp->dmap_label))
panic(__FILE__, "map_driver: label too long", len);
strcpy(dp->dmap_label, label);
/* Try to update the entry. */
switch (style) {
case STYLE_DEV: dp->dmap_opcl = gen_opcl; break;
case STYLE_TTY: dp->dmap_opcl = tty_opcl; break;
case STYLE_CLONE: dp->dmap_opcl = clone_opcl; break;
default: return(EINVAL);
}
dp->dmap_io = gen_io;
dp->dmap_driver = proc_nr_e;
return(OK);
}
/*===========================================================================*
* dmap_unmap_by_endpt *
*===========================================================================*/
@ -213,6 +356,7 @@ PUBLIC void build_dmap()
dp->dmap_io = init_dmap[i].dmap_io;
dp->dmap_driver = init_dmap[i].dmap_driver;
dp->dmap_flags = init_dmap[i].dmap_flags;
strcpy(dp->dmap_label, init_dmap[i].dmap_label);
} else { /* no default */
dp->dmap_opcl = no_dev;
dp->dmap_io = no_dev_io;

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];
static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
/* Request and response structures */
struct lookup_req lookup_req;
struct node_details Xres;
okendpt(proc_e, &proc_s);
rfp= fp= &fproc[proc_s];
who_e= proc_e;
@ -129,23 +125,19 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
for (round= 0; round < 2; round++)
/* round = 0 (first attempt), or 1 (interpreted script) */
{
#if 0
printf("vfs:pm_exec: round %d, name '%s'\n", round, user_fullpath);
#endif
/* Save the name of the program */
(cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);
strncpy(progname, cp, PROC_NAME_LEN-1);
progname[PROC_NAME_LEN-1] = '\0';
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup_vp(&lookup_req, &vp)) != OK)
{
put_vnode(vp);
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK)
return r;
}
if ((vp->v_mode & I_TYPE) != I_REGULAR) {
put_vnode(vp);
@ -153,7 +145,7 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
}
/* Check access. */
if ((r = forbidden(vp, X_BIT)) != OK)
if ((r = forbidden(vp, X_BIT, 0 /*!use_realuid*/)) != OK)
{
put_vnode(vp);
return r;
@ -168,6 +160,10 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
}
v_ctime = sb.st_ctime;
#if 0
printf("vfs:pm_exec: round %d, mode 0%o, uid %d, gid %d\n",
round, vp->v_mode, vp->v_uid, vp->v_gid);
#endif
if (round == 0)
{
/* Deal with setuid/setgid executables */
@ -340,6 +336,9 @@ int *hdrlenp;
{
/* Read the header and extract the text, data, bss and total sizes from it. */
off_t pos;
int r;
u64_t new_pos;
unsigned int cum_io_incr;
struct exec hdr; /* a.out header is read in here */
/* Read the header and check the magic number. The standard MINIX header
@ -368,26 +367,14 @@ int *hdrlenp;
* used here only. The symbol table is for the benefit of a debugger and
* is ignored here.
*/
struct readwrite_req req;
struct readwrite_res res;
int r;
pos= 0; /* Read from the start of the file */
/* Fill in request structure */
req.fs_e = vp->v_fs_e;
req.rw_flag = READING;
req.inode_nr = vp->v_inode_nr;
req.user_e = FS_PROC_NR;
req.seg = D;
req.pos = cvul64(pos);
req.num_of_bytes = sizeof(hdr);
req.user_addr = (char*)&hdr;
req.inode_index = vp->v_index;
/* Issue request */
if ((r = req_readwrite(&req, &res)) != OK) return r;
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index,
cvul64(pos), READING, FS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos,
&cum_io_incr);
if (r != OK) return r;
/* Interpreted script? */
if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2)
@ -441,32 +428,23 @@ vir_bytes *stk_bytes; /* size of initial stack */
int n, r;
off_t pos;
char *sp, *interp = NULL;
u64_t new_pos;
unsigned int cum_io_incr;
char buf[_MAX_BLOCK_SIZE];
struct readwrite_req req;
struct readwrite_res res;
/* Make user_path the new argv[0]. */
if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) return(ENOMEM);
pos = 0; /* Read from the start of the file */
/* Fill in request structure */
req.fs_e = vp->v_fs_e;
req.rw_flag = READING;
req.inode_nr = vp->v_inode_nr;
req.user_e = FS_PROC_NR;
req.seg = D;
req.pos = cvul64(pos);
req.num_of_bytes = _MAX_BLOCK_SIZE;
req.user_addr = buf;
req.inode_index = vp->v_index;
/* Issue request */
if ((r = req_readwrite(&req, &res)) != OK) return r;
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, cvul64(pos),
READING, FS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io_incr);
if (r != OK) return r;
n = vp->v_size;
if (n > vp->v_vmnt->m_block_size)
n = vp->v_vmnt->m_block_size;
if (n > _MAX_BLOCK_SIZE)
n = _MAX_BLOCK_SIZE;
if (n < 2) return ENOEXEC;
sp = &(buf[2]); /* just behind the #! */
@ -604,28 +582,64 @@ phys_bytes seg_bytes; /* how much is to be transferred? */
* a segment is padded out to a click multiple, and the data segment is only
* partially initialized.
*/
struct readwrite_req req;
struct readwrite_res res;
int r;
unsigned n, o;
u64_t new_pos;
unsigned int cum_io_incr;
char buf[1024];
/* Make sure that the file is big enough */
if (vp->v_size < off+seg_bytes) return EIO;
if (seg != D)
{
/* We have to use a copy loop until safecopies support segments */
o= 0;
while (o < seg_bytes)
{
n= seg_bytes-o;
if (n > sizeof(buf))
n= sizeof(buf);
#if 0
printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n",
proc_e, seg, buf, n, off+o);
#endif
/* Issue request */
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index,
cvul64(off+o), READING, FS_PROC_NR, buf, n, &new_pos,
&cum_io_incr);
if (r != OK) return r;
if (cum_io_incr != n)
{
printf(
"VFSread_seg segment has not been read properly by exec() \n");
return EIO;
}
r= sys_vircopy(FS_PROC_NR, D, (vir_bytes)buf, proc_e, seg, o,
n);
if (r != OK)
return r;
o += n;
}
return OK;
}
/* Fill in request structure */
req.fs_e = vp->v_fs_e;
req.rw_flag = READING;
req.inode_nr = vp->v_inode_nr;
req.user_e = proc_e;
req.seg = seg;
req.pos = cvul64(off);
req.num_of_bytes = seg_bytes;
req.user_addr = 0;
req.inode_index = vp->v_index;
#if 0
printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n",
proc_e, seg, 0, seg_bytes, off);
#endif
/* Issue request */
if ((r = req_readwrite(&req, &res)) != OK) return r;
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, cvul64(off),
READING, proc_e, 0, seg_bytes, &new_pos, &cum_io_incr);
if (r != OK) return r;
if (r == OK && res.cum_io != seg_bytes)
if (r == OK && cum_io_incr != seg_bytes)
printf("VFSread_seg segment has not been read properly by exec() \n");
return r;

View file

@ -22,5 +22,6 @@
#include <minix/sysutil.h>
#include "const.h"
#include "dmap.h"
#include "proto.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 last_login_fs_e; /* endpoint of the FS proc that logged in
before the corresponding mount request */
EXTERN time_t boottime; /* time in seconds at system boot */
/* The parameters of the call are kept here. */
EXTERN message m_in; /* the input message itself */

View file

@ -33,59 +33,54 @@
PUBLIC int do_link()
{
/* Perform the link(name1, name2) system call. */
int linked_fs_e;
int linked_inode_nr;
int link_lastdir_fs_e;
int link_lastdir_inode_nr;
char string[NAME_MAX];
struct link_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
endpoint_t linked_fs_e, link_lastdir_fs_e;
struct vnode *vp_o, *vp_d;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK)
return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp_o)) != OK) return r;
linked_fs_e = res.fs_e;
req.linked_file = res.inode_nr;
linked_fs_e = vp_o->v_fs_e;
/* Does the final directory of 'name2' exist? */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
put_vnode(vp_o);
return(err_code);
}
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = string;
lookup_req.flags = LAST_DIR;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_d)) != OK)
{
put_vnode(vp_o);
return r;
}
link_lastdir_fs_e = vp_d->v_fs_e;
link_lastdir_fs_e = res.fs_e;
req.link_parent = res.inode_nr;
/* Check for links across devices. */
if (linked_fs_e != link_lastdir_fs_e)
{
put_vnode(vp_o);
put_vnode(vp_d);
return EXDEV;
}
/* Send link request. */
req.fs_e = linked_fs_e;
/* Send the last component of the link name */
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.lastc = string;
r= forbidden(vp_d, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (r != OK)
{
put_vnode(vp_o);
put_vnode(vp_d);
return r;
}
/* Issue request */
return req_link(&req);
r= req_link(linked_fs_e, vp_d->v_inode_nr, user_fullpath, vp_o->v_inode_nr);
put_vnode(vp_o);
put_vnode(vp_d);
return r;
}
@ -100,65 +95,35 @@ PUBLIC int do_unlink()
* may be used by the superuser to do dangerous things; rmdir() may not.
*/
register struct fproc *rfp;
char string[NAME_MAX];
struct vnode *vp;
struct unlink_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
string[0] = '\0';
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH_OPAQUE;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
r= lookup_lastdir(0 /*!use_realuid*/, &vp);
if (r != OK)
return r;
/* The caller must have both search and execute permission */
r= forbidden(vp, X_BIT|W_BIT, 0 /*!use_realuid*/);
if (r != OK)
{
put_vnode(vp);
return r;
}
/* If a directory file has to be removed the following conditions have to met:
* - The directory must not be the root of a mounted file system
* - The directory must not be anybody's root/working directory
*/
if ((res.fmode & I_TYPE) == I_DIRECTORY) {
/* Only root can unlink a directory */
if (call_nr == UNLINK && !super_user) return EPERM;
/* Can't remove a root directory */
if (res.inode_nr == ROOT_INODE) return EBUSY;
/* Can't remove anybody's working directory */
if ((vp = find_vnode(res.fs_e, res.inode_nr)) !=
NIL_VNODE) {
/* Check directories */
for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS];
rfp++) {
if (rfp->fp_pid != PID_FREE &&
(rfp->fp_wd == vp || rfp->fp_rd == vp))
return(EBUSY);
}
}
}
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = string;
lookup_req.flags = LAST_DIR;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
/* Fill in request fields. */
req.fs_e = res.fs_e;
req.d_inode_nr = res.inode_nr;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.lastc = string;
/* Issue request */
return (call_nr == UNLINK) ? req_unlink(&req) : req_rmdir(&req);
r= ((call_nr == UNLINK) ? req_unlink : req_rmdir)(vp->v_fs_e,
vp->v_inode_nr, user_fullpath);
put_vnode(vp);
return r;
}
@ -168,90 +133,81 @@ PUBLIC int do_unlink()
PUBLIC int do_rename()
{
/* Perform the rename(name1, name2) system call. */
int r;
int old_dir_inode;
int old_fs_e;
int new_dir_inode;
int new_fs_e;
char old_name[NAME_MAX];
char new_name[NAME_MAX];
struct vnode *vp;
struct fproc *rfp;
struct rename_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
size_t len;
struct vnode *vp_od, *vp_nd;
char old_name[PATH_MAX+1];
/* See if 'name1' (existing file) exists. Get dir and file inodes. */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = old_name;
lookup_req.flags = LAST_DIR;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
/* Remeber inode number and FS endpoint */
old_fs_e = res.fs_e;
req.old_dir = res.inode_nr;
if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_od)) != OK) return r;
/* See if 'name2' (new name) exists. Get dir inode */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) r = err_code;
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH_OPAQUE;
/* Request lookup */
r = lookup(&lookup_req, &res);
/* If a directory file has to be removed the following conditions have to met:
* - The directory must not be the root of a mounted file system
* - The directory must not be anybody's root/working directory
*/
if (r == OK && ((res.fmode & I_TYPE) == I_DIRECTORY)) {
/* Can't remove a root directory */
if (res.inode_nr == ROOT_INODE) return EBUSY;
/* Can't remove anybody's working directory */
if ((vp = find_vnode(res.fs_e, res.inode_nr)) !=
NIL_VNODE) {
/* Check directories */
for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS];
rfp++) {
if (rfp->fp_pid != PID_FREE &&
(rfp->fp_wd == vp || rfp->fp_rd == vp))
return(EBUSY);
}
}
r= forbidden(vp_od, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (r != OK)
{
put_vnode(vp_od);
return r;
}
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = new_name;
lookup_req.flags = LAST_DIR;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
/* Remeber FS endpoint */
old_fs_e = vp_od->v_fs_e;
/* Save the last component of the old name */
len= strlen(user_fullpath);
if (len >= sizeof(old_name))
{
put_vnode(vp_od);
return ENAMETOOLONG;
}
memcpy(old_name, user_fullpath, len+1);
/* See if 'name2' (new name) exists. Get dir inode */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
{
put_vnode(vp_od);
return err_code;
}
/* Remeber inode number and FS endpoint */
new_fs_e = res.fs_e;
req.new_dir = res.inode_nr;
/* Request lookup */
r = lookup_lastdir(0 /*!use_realuid*/, &vp_nd);
if (r != OK)
{
put_vnode(vp_od);
return r;
}
r= forbidden(vp_nd, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (r != OK)
{
put_vnode(vp_od);
put_vnode(vp_nd);
return r;
}
/* Remeber FS endpoint */
new_fs_e = vp_nd->v_fs_e;
/* Both parent directories must be on the same device. */
if (old_fs_e != new_fs_e) return EXDEV;
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 */
return req_rename(&req);
r= req_rename(old_fs_e, vp_od->v_inode_nr, old_name, vp_nd->v_inode_nr,
user_fullpath);
put_vnode(vp_od);
put_vnode(vp_nd);
return r;
}
@ -266,41 +222,20 @@ PUBLIC int do_truncate()
* work.
*/
struct vnode *vp;
struct trunc_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
printf("in do_truncate\n");
if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code;
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* Check whether the file is in use or not */
vp = find_vnode(res.fs_e, res.inode_nr);
r= truncate_vn(vp, m_in.m2_l1);
/* Fill in request message fields.*/
req.fs_e = res.fs_e;
req.length = m_in.m2_l1;
req.inode_nr = res.inode_nr;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
/* 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;
put_vnode(vp);
return r;
}
@ -327,21 +262,14 @@ struct vnode *vp;
off_t newsize;
{
int r;
struct ftrunc_req req;
if ( (vp->v_mode & I_TYPE) != I_REGULAR &&
(vp->v_mode & I_TYPE) != I_NAMED_PIPE) {
return EINVAL;
}
/* Fill in FS request */
req.fs_e = vp->v_fs_e;
req.inode_nr = vp->v_inode_nr;
req.start = newsize;
req.end = 0; /* Indicate trunc in fs_freesp_trunc */
/* Issue request */
if ((r = req_ftrunc(&req)) != OK) return r;
if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) != OK) return r;
vp->v_size = newsize;
return OK;
@ -353,38 +281,40 @@ off_t newsize;
PUBLIC int do_slink()
{
/* Perform the symlink(name1, name2) system call. */
char string[NAME_MAX]; /* last component of the new dir's path name */
struct slink_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
struct vnode *vp;
char string[NAME_MAX]; /* last component of the new dir's path name */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
return(err_code);
if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE)
return(ENAMETOOLONG);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = string;
lookup_req.flags = LAST_DIR;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
/* Fill in request message */
req.fs_e = res.fs_e;
req.parent_dir = res.inode_nr;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.lastc = string;
req.who_e = who_e;
req.path_addr = m_in.name1;
req.path_length = m_in.name1_length - 1;
/* Request lookup */
if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK)
{
printf("vfs:do_slink: lookup_lastdir failed with %d\n", r);
return r;
}
printf("vfs:do_slink: got dir inode %d on dev 0x%x, fs %d\n",
vp->v_inode_nr, vp->v_dev, vp->v_fs_e);
r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (r != OK)
{
put_vnode(vp);
return r;
}
/* Issue request */
return req_slink(&req);
r= req_slink(vp->v_fs_e, vp->v_inode_nr, user_fullpath, who_e, m_in.name1,
m_in.name1_length - 1, fp->fp_effuid, fp->fp_effgid);
put_vnode(vp);
return r;
}
/*===========================================================================*
@ -393,36 +323,25 @@ PUBLIC int do_slink()
PUBLIC int do_rdlink()
{
/* Perform the readlink(name, buf) system call. */
int copylen;
struct rdlink_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
int r, copylen;
struct vnode *vp;
copylen = m_in.m1_i2;
if(copylen < 0) return EINVAL;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH_OPAQUE;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
/* Fill in request message */
req.fs_e = res.fs_e;
req.inode_nr = res.inode_nr;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.who_e = who_e;
req.path_buffer = m_in.name2;
req.max_length = copylen;
r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
/* Issue request */
return req_rdlink(&req);
r= req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, (vir_bytes)m_in.name2,
copylen);
put_vnode(vp);
return r;
}

View file

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

View file

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

View file

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

View file

@ -38,6 +38,10 @@
FORWARD _PROTOTYPE( int x_open, (int bits, int oflags, int omode,
char *lastc, struct vnode **vpp) );
FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) );
FORWARD _PROTOTYPE( int create_open, (_mnx_Mode_t omode,
struct vnode **vpp, int *created) );
FORWARD _PROTOTYPE( int y_open, (struct vnode *vp, _mnx_Mode_t bits,
int oflags));
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
/*===========================================================================*
@ -83,21 +87,12 @@ PUBLIC int do_open()
PRIVATE int common_open(register int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */
int r, b, found;
dev_t dev;
int b, m, r, created, found;
mode_t bits;
off_t pos;
struct dmap *dp;
struct filp *fil_ptr, *filp2;
struct vnode *vp, *vp2;
struct vnode *vp;
struct vmnt *vmp;
char Xlastc[NAME_MAX];
char *pathrem;
int m;
/* Request and response structures */
struct lookup_req Xlookup_req;
struct open_req Xreq;
struct dmap *dp;
/* Remap the bottom two bits of oflags. */
m = oflags & O_ACCMODE;
@ -116,114 +111,29 @@ PRIVATE int common_open(register int oflags, mode_t omode)
omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
}
vp= NULL;
/* Fill in lookup request fields */
Xlookup_req.path = user_fullpath;
Xlookup_req.lastc = Xlastc;
Xlookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR :
LAST_DIR_EATSYM) : EAT_PATH;
Xlookup_req.flags = ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) ?
LAST_DIR : EAT_PATH;
Xlastc[0]= '\0'; /* Clear lastc, it will be filled with the part of the
* path that cannot be resolved.
*/
/* Request lookup */
r = Xlookup_vp(&Xlookup_req, &vp, &pathrem);
if (r == OK && ((oflags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL)))
if (oflags & O_CREAT)
r= create_open(omode, &vp, &created);
else
{
/* 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
else
{
printf("common_open: / in pathrem\n");
}
printf("vfs:common_open: path '%s'\n", user_fullpath);
#endif
}
created= FALSE;
r= lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
}
if (r != OK)
return r;
if (!created)
{
if (vp)
r= y_open(vp, bits, oflags);
if (r != OK)
{
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. */
fp->fp_filp[m_in.fd] = fil_ptr;
FD_SET(m_in.fd, &fp->fp_filp_inuse);
@ -256,11 +166,9 @@ PRIVATE int common_open(register int oflags, mode_t omode)
/* Who is going to be responsible for this device? */
if (found) {
vp->v_bfs_e = vmp->m_fs_e;
vp->v_blocksize - vmp->m_block_size;
}
else { /* To be handled in the root FS proc if not mounted */
vp->v_bfs_e = ROOT_FS_E;
vp->v_blocksize = _MIN_BLOCK_SIZE;
}
/* Get the driver endpoint of the block spec device */
@ -332,6 +240,186 @@ PRIVATE int common_open(register int oflags, mode_t omode)
return(m_in.fd);
}
/*===========================================================================*
* create_open *
*===========================================================================*/
PRIVATE int create_open(omode, vpp, created)
mode_t omode;
struct vnode **vpp;
int *created;
{
int i, r, r1;
size_t len;
struct vnode *vp, *dir_vp, *new_vp, *start_vp;
struct node_details res;
char lastc[PATH_MAX+1];
start_vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
dup_vnode(start_vp);
for (i= 0; i<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 *
*===========================================================================*/
@ -381,7 +469,7 @@ struct vnode **vpp;
vp->v_sdev = res.dev;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM);
panic(__FILE__, "x_open: vmnt not found", NO_NUM);
vp->v_vmnt = vmp;
vp->v_dev = vmp->m_dev;
@ -404,7 +492,7 @@ struct vnode **vpp;
return OK;
/* Check protections. */
if ((r = forbidden(vp, bits)) != OK)
if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK)
return r;
/* Opening reg. files directories and special files differ. */
@ -412,7 +500,7 @@ struct vnode **vpp;
case I_REGULAR:
/* Truncate regular file if O_TRUNC. */
if (oflags & O_TRUNC) {
if ((r = forbidden(vp, W_BIT)) !=OK) break;
if ((r = forbidden(vp, W_BIT, 0 /*!use_realuid*/)) !=OK) break;
truncate_vn(vp, 0);
}
break;
@ -449,6 +537,74 @@ struct vnode **vpp;
}
/*===========================================================================*
* y_open *
*===========================================================================*/
PRIVATE int y_open(vp, bits, oflags /*, omode, lastc, vpp */)
struct vnode *vp;
mode_t bits;
int oflags;
#if 0
mode_t omode;
char *lastc;
struct vnode **vpp;
#endif
{
int r;
#if 0
int r, b, exist = TRUE;
struct vnode *vp, *dvp, *tmp_vp;
struct vmnt *vmp;
struct node_details res;
#endif
/* Check protections. */
if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK)
return r;
/* Opening reg. files directories and special files differ. */
switch (vp->v_mode & I_TYPE) {
case I_REGULAR:
/* Truncate regular file if O_TRUNC. */
if (oflags & O_TRUNC) {
if ((r = forbidden(vp, W_BIT, 0 /*!use_realuid*/)) !=OK) break;
truncate_vn(vp, 0);
}
break;
case I_DIRECTORY:
/* Directories may be read but not written. */
r = (bits & W_BIT ? EISDIR : OK);
break;
case I_CHAR_SPECIAL:
case I_BLOCK_SPECIAL:
if (vp->v_sdev == (dev_t)-1)
panic(__FILE__, "y_open: bad special", NO_NUM);
break;
case I_NAMED_PIPE:
if (vp->v_ref_count == 1)
{
if (vp->v_size != 0)
{
r= truncate_vn(vp, 0);
if (r != OK)
{
printf(
"x_open (fifo): truncate_vn failed: %d\n",
r);
}
}
}
break;
}
return(r);
}
/*===========================================================================*
* pipe_open *
*===========================================================================*/
@ -492,11 +648,8 @@ PUBLIC int do_mknod()
{
/* Perform the mknod(name, mode, addr) system call. */
register mode_t bits, mode_bits;
char lastc[NAME_MAX]; /* last component of the path */
struct mknod_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
struct vnode *vp;
/* Only the super_user may make nodes other than fifos. */
mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */
@ -504,26 +657,21 @@ PUBLIC int do_mknod()
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = lastc;
lookup_req.flags = LAST_DIR;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
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 */
return req_mknod(&req);
r= req_mknod(vp->v_fs_e, vp->v_inode_nr, user_fullpath,
fp->fp_effuid, fp->fp_effgid, bits, m_in.mk_z0);
put_vnode(vp);
return r;
}
@ -534,36 +682,29 @@ PUBLIC int do_mkdir()
{
/* Perform the mkdir(name, mode) system call. */
mode_t bits; /* mode bits for the new inode */
char lastc[NAME_MAX];
struct mkdir_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
struct vnode *vp;
/*printf("VFS: mkdir() START:");*/
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = lastc;
lookup_req.flags = LAST_DIR;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK) return r;
r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (r != OK)
{
put_vnode(vp);
return r;
}
/* Lookup was okay, fill in request message fields
* for the actual mknod request. */
req.fs_e = res.fs_e;
req.d_inode_nr = res.inode_nr;
req.rmode = bits;
req.lastc = lastc;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
/* Issue request */
return req_mkdir(&req);
r= req_mkdir(vp->v_fs_e, vp->v_inode_nr, user_fullpath,
fp->fp_effuid, fp->fp_effgid, bits);
put_vnode(vp);
return r;
}
@ -579,7 +720,6 @@ PUBLIC int do_lseek()
int r;
long offset;
u64_t pos, newpos;
struct node_req req;
/* Check to see if the file descriptor is valid. */
if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
@ -606,12 +746,8 @@ PUBLIC int do_lseek()
return EINVAL;
if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
/* Fill in request message */
req.fs_e = rfilp->filp_vno->v_fs_e;
req.inode_nr = rfilp->filp_vno->v_inode_nr;
/* Issue request */
if ((r = req_inhibread(&req)) != OK) return r;
r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
if (r != OK) return r;
}
rfilp->filp_pos = newpos;
@ -631,7 +767,6 @@ PUBLIC int do_llseek()
/* Perform the llseek(ls_fd, offset, whence) system call. */
register struct filp *rfilp;
u64_t pos, newpos;
struct node_req req;
int r;
/* Check to see if the file descriptor is valid. */
@ -657,12 +792,8 @@ PUBLIC int do_llseek()
return(EINVAL);
if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
/* Fill in request message */
req.fs_e = rfilp->filp_vno->v_fs_e;
req.inode_nr = rfilp->filp_vno->v_inode_nr;
/* Issue request */
if ((r = req_inhibread(&req)) != OK) return r;
r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
if (r != OK) return r;
}
rfilp->filp_pos = newpos;

View file

@ -52,6 +52,11 @@
#define pm_stime m1_i1
#define info_what m1_i1
#define info_where m1_p1
#define md_label m2_p1
#define md_label_len m2_l1
#define md_major m2_i1
#define md_style m2_i2
#define md_force m2_i3
/* The following names are synonyms for the variables in the output message. */
#define reply_type m_type

View file

@ -21,126 +21,306 @@
#include "vnode.h"
#include "param.h"
FORWARD _PROTOTYPE( int Xlookup, (lookup_req_t *lookup_req,
node_details_t *node, char **pathrem) );
FORWARD _PROTOTYPE( int lookup_rel, (struct vnode *start_node,
int flags, int use_realuid, node_details_t *node) );
/*===========================================================================*
* lookup *
* lookup_rel_vp *
*===========================================================================*/
PUBLIC int lookup(lookup_req, node)
lookup_req_t *lookup_req;
node_details_t *node;
PUBLIC int lookup_rel_vp(start_node, flags, use_realuid, vpp)
struct vnode *start_node;
int flags;
int use_realuid;
struct vnode **vpp;
{
/* Resolve a pathname (in user_fullpath) starting at start_node to a vnode. */
int r, lookup_res;
struct vnode *new_vp, *vp;
struct vmnt *vmp;
struct vnode *start_node;
struct lookup_res res;
int r, symloop = 0;
int cum_path_processed = 0;
/* Make a copy of the request so that the original values will be kept */
struct lookup_req req = *lookup_req;
char *fullpath = lookup_req->path;
struct node_details res;
/* Empty (start) path? */
if (fullpath[0] == '\0') {
node->inode_nr = 0;
return ENOENT;
/* See if free vnode is available */
if ((new_vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
printf("vfs:lookup_rel_vp: no free vnode available\n");
*vpp= NULL;
return EINVAL;
}
/* Set user and group ids according to the system call */
req.uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
req.gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
lookup_res = lookup_rel(start_node, flags, use_realuid, &res);
/* Set the starting directories inode number and FS endpoint */
start_node = (fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
req.start_dir = start_node->v_inode_nr;
req.fs_e = start_node->v_fs_e;
if (lookup_res != OK)
{
#if 0
printf("vfs:lookup_rel_vp: lookup_rel failed with %d\n", lookup_res);
#endif
return lookup_res;
}
/* 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?,
* if so, set the chroot directory too. */
if (fp->fp_rd->v_dev == fp->fp_wd->v_dev)
req.root_dir = fp->fp_rd->v_inode_nr;
root_ino = fp->fp_rd->v_inode_nr;
else
req.root_dir = 0;
root_ino = 0;
req.symloop = symloop;
/* Set user and group ids according to the system call */
uid = (use_realuid ? fp->fp_realuid : fp->fp_effuid);
gid = (use_realuid ? fp->fp_realgid : fp->fp_effgid);
symloop= 0; /* Number of symlinks seen so far */
/* Issue the request */
r = req_lookup(&req, &res);
r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags, &res);
if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
{
#if 0
printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r);
#endif
return r;
}
/* While the response is related to mount control set the
* new requests respectively */
while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
/* If a symlink was encountered during the lookup the
* new path has been copied back and the number of characters
* processed has been started over. */
if (r == ESYMLINK || res.symloop > symloop) {
/* The link's content is copied back to the user_fullpath
* array. Use it as the path argument from now on... */
fullpath = user_fullpath;
cum_path_processed = res.char_processed;
}
else {
/* Otherwise, cumulate the characters already processsed from
* the path */
cum_path_processed += res.char_processed;
}
/* Save the place in the (possibly updated) path where we have to
* continue witht henext lookup request.
*/
path_off= res.char_processed;
/* Remember the current value of the symloop counter */
symloop = res.symloop;
/* Update the current value of the symloop counter */
symloop += res.symloop;
if (symloop > SYMLOOP_MAX)
{
printf("vfs:lookup_rel: returning ELOOP\n");
return ELOOP;
}
/* Symlink encountered with absolute path */
if (r == ESYMLINK) {
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;
}
/* Symlink encountered with absolute path */
if (r == ESYMLINK) {
dir_vp = fp->fp_rd;
}
else if (r == EENTERMOUNT) {
/* Entering a new partition */
dir_vp = 0;
/* Start node is now the mounted partition's root node */
for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
if (vmp->m_mounted_on->v_inode_nr == res.inode_nr &&
vmp->m_mounted_on->v_fs_e == res.fs_e) {
dir_vp = vmp->m_root_node;
break;
}
}
if (!dir_vp) {
printf(
"vfs:lookup_rel: res.inode_nr = %d, res.fs_e = %d\n",
res.inode_nr, res.fs_e);
panic(__FILE__,
"vfs:lookup_s: mounted partition couldn't be found",
NO_NUM);
}
}
/* 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;
}
else {
/* Climbing up mount */
/* Find the vmnt that represents the partition on
* which we "climb up". */
if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
panic(__FILE__,
"vfs:lookup_s: couldn't find vmnt during the climbup",
NO_NUM);
}
/* Start node is the vnode on which the partition is
* mounted */
dir_vp = vmp->m_mounted_on;
}
/* 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;
/* Set the starting directories inode number and FS endpoint */
fs_e = dir_vp->v_fs_e;
dir_ino = dir_vp->v_inode_nr;
/* Is the process' root directory on the same partition?,
* if so, set the chroot directory too. */
if (fp->fp_rd->v_dev == fp->fp_wd->v_dev)
root_ino = fp->fp_rd->v_inode_nr;
else
root_ino = 0;
/* Fill in the current path name */
req.path = &fullpath[cum_path_processed];
req.symloop = symloop;
/* Issue the request */
r = req_lookup(&req, &res);
/* Issue the request */
r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags,
&res);
if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
{
#if 0
printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r);
#endif
return r;
}
}
/* Fill in response fields */
@ -154,295 +334,3 @@ node_details_t *node;
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;
struct filp *fil_ptr0, *fil_ptr1;
int fil_des[2]; /* reply goes here */
struct vnode *vp;
struct vmnt *vmp;
struct pipe_req req;
struct node_details res;
/* See if a free vnode is available */
@ -80,13 +77,9 @@ PUBLIC int do_pipe()
FD_SET(fil_des[1], &rfp->fp_filp_inuse);
fil_ptr1->filp_count = 1;
/* Fill in FS request */
req.fs_e = ROOT_FS_E;
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
/* Send request */
r = req_pipe(&req, &res);
r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE,
(dev_t)0, &res);
/* Handle error */
if (r != OK) {
@ -105,8 +98,8 @@ PUBLIC int do_pipe()
vp->v_mode = res.fmode;
vp->v_index = res.inode_index;
vp->v_pipe = I_PIPE;
vp->v_fs_count = 2; /* Double usage */
vp->v_ref_count = 2; /* Double usage */
vp->v_fs_count = 1;
vp->v_ref_count = 1;
vp->v_size = 0;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) {
@ -120,6 +113,7 @@ PUBLIC int do_pipe()
/* Fill in filp objects */
fil_ptr0->filp_vno = vp;
dup_vnode(vp);
fil_ptr1->filp_vno = vp;
fil_ptr0->filp_flags = O_RDONLY;
fil_ptr1->filp_flags = O_WRONLY;
@ -133,13 +127,12 @@ PUBLIC int do_pipe()
/*===========================================================================*
* pipe_check *
*===========================================================================*/
PUBLIC int pipe_check(vp, rw_flag, oflags, bytes, position, canwrite, notouch)
PUBLIC int Xpipe_check(vp, rw_flag, oflags, bytes, position, notouch)
register struct vnode *vp; /* the inode of the pipe */
int rw_flag; /* READING or WRITING */
int oflags; /* flags set by open or fcntl */
register int bytes; /* bytes to be read or written (all chunks) */
u64_t position; /* current file position */
int *canwrite; /* return: number of bytes we can write */
int notouch; /* check only */
{
/* Pipes are a little different. If a process reads from an empty pipe for
@ -163,8 +156,6 @@ int notouch; /* check only */
if (oflags & O_NONBLOCK) {
r = EAGAIN;
} else {
if (!notouch)
suspend(XPIPE); /* block reader */
r = SUSPEND;
}
/* If need be, activate sleeping writers. */
@ -173,56 +164,65 @@ int notouch; /* check only */
}
return(r);
}
} else {
/* Process is writing to a pipe. */
if (find_filp(vp, R_BIT) == NIL_FILP) {
/* Tell kernel to generate a SIGPIPE signal. */
if (!notouch) {
sys_kill(fp->fp_endpoint, SIGPIPE);
}
return(EPIPE);
}
if (pos + bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) {
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);
return bytes;
}
*canwrite = 0;
return(1);
/* 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_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().
*/
if (task == XPIPE || task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
if (task == XPIPE)
panic(__FILE__, "suspend: called for XPIPE", NO_NUM);
if (task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
fp->fp_suspended = SUSPENDED;
assert(!GRANT_VALID(fp->fp_grant));
fp->fp_fd = m_in.fd << 8 | call_nr;
@ -254,6 +257,31 @@ int task; /* who is proc waiting for? (PIPE = pipe) */
}
}
/*===========================================================================*
* pipe_suspend *
*===========================================================================*/
PUBLIC void pipe_suspend(rw_flag, fd_nr, buf, size)
int rw_flag;
int fd_nr;
char *buf;
size_t size;
{
/* Take measures to suspend the processing of the present system call.
* Store the parameters to be used upon resuming in the process table.
* (Actually they are not used when a process is waiting for an I/O device,
* but they are needed for pipes, and it is not worth making the distinction.)
* The SUSPEND pseudo error should be returned after calling suspend().
*/
susp_count++; /* #procs susp'ed on pipe*/
fp->fp_suspended = SUSPENDED;
assert(!GRANT_VALID(fp->fp_grant));
fp->fp_fd = (fd_nr << 8) | ((rw_flag == READING) ? READ : WRITE);
fp->fp_task = -XPIPE;
fp->fp_buffer = buf;
fp->fp_nbytes = size;
}
/*===========================================================================*
* unsuspend_by_endpt *
*===========================================================================*/
@ -296,6 +324,10 @@ int count; /* max number of processes to release */
register struct fproc *rp;
struct filp *f;
#if 0
printf("vfs:release: vp 0x%x, call %d, count %d\n", vp, call_nr, count);
#endif
/* Trying to perform the call also includes SELECTing on it with that
* operation.
*/
@ -481,15 +513,15 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
int orig_ops, r = 0, err, canwrite;
orig_ops = *ops;
if ((*ops & (SEL_RD|SEL_ERR))) {
if ((err = pipe_check(f->filp_vno, READING, 0,
1, f->filp_pos, &canwrite, 1)) != SUSPEND)
if ((err = Xpipe_check(f->filp_vno, READING, 0,
1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_RD;
if (err < 0 && err != SUSPEND)
r |= SEL_ERR;
}
if ((*ops & (SEL_WR|SEL_ERR))) {
if ((err = pipe_check(f->filp_vno, WRITING, 0,
1, f->filp_pos, &canwrite, 1)) != SUSPEND)
if ((err = Xpipe_check(f->filp_vno, WRITING, 0,
1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_WR;
if (err < 0 && err != SUSPEND)
r |= SEL_ERR;

View file

@ -31,47 +31,54 @@
PUBLIC int do_chmod()
{
struct filp *flp;
struct chmod_req req;
struct lookup_req lookup_req;
struct node_details res;
struct vnode *vp;
int r, ch_mode;
int r;
uid_t uid;
gid_t gid;
mode_t new_mode;
if (call_nr == CHMOD) {
/* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
req.inode_nr = res.inode_nr;
req.fs_e = res.fs_e;
r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
}
else if (call_nr == FCHMOD) {
if (!(flp = get_filp(m_in.m3_i1))) return err_code;
req.inode_nr = flp->filp_vno->v_inode_nr;
req.fs_e = flp->filp_vno->v_fs_e;
vp= flp->filp_vno;
dup_vnode(vp);
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
/* Find vnode, if it's in use. */
vp = find_vnode(req.fs_e, req.inode_nr);
uid= fp->fp_effuid;
gid= fp->fp_effgid;
/* Only the owner or the super_user may change the mode of a file.
* No one may change the mode of a file on a read-only file system.
*/
if (vp->v_uid != uid && uid != SU_UID)
r = EPERM;
else
r = read_only(vp);
/* If error, return inode. */
if (r != OK) {
put_vnode(vp);
return(r);
}
/* Now make the change. Clear setgid bit if file is not in caller's grp */
if (uid != SU_UID && vp->v_gid != gid)
m_in.mode &= ~I_SET_GID_BIT;
/* Fill in request message fields.*/
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.rmode = m_in.mode;
/* Issue request */
if((r = req_chmod(&req, &ch_mode)) != OK) return r;
r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode);
if(vp != NIL_VNODE)
vp->v_mode = ch_mode;
if (r == OK)
vp->v_mode = new_mode;
put_vnode(vp);
return OK;
}
@ -84,52 +91,58 @@ PUBLIC int do_chown()
int inode_nr;
int fs_e;
struct filp *flp;
struct chown_req req;
struct lookup_req lookup_req;
struct node_details res;
struct vnode *vp;
int r, ch_mode;
int r;
uid_t uid;
gid_t gid;
mode_t new_mode;
if (call_nr == CHOWN) {
/* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
req.inode_nr = res.inode_nr;
req.fs_e = res.fs_e;
r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
}
else if (call_nr == FCHOWN) {
if (!(flp = get_filp(m_in.m1_i1))) return err_code;
req.inode_nr = flp->filp_vno->v_inode_nr;
req.fs_e = flp->filp_vno->v_fs_e;
vp= flp->filp_vno;
dup_vnode(vp);
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
/* Find vnode, if it's in use. */
vp = find_vnode(req.fs_e, req.inode_nr);
uid= fp->fp_effuid;
gid= fp->fp_effgid;
r= OK;
if (uid == SU_UID) {
/* The super user can do anything. */
} else {
/* Regular users can only change groups of their own files. */
if (vp->v_uid != uid)
r = EPERM; /* File does not belong to the caller */
if (vp->v_uid != m_in.owner)
r = EPERM; /* no giving away */
if (gid != m_in.group)
r = EPERM; /* only change to the current gid */
}
if (r != OK) {
put_vnode(vp);
return r;
}
/* Fill in request message fields.*/
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.newuid = m_in.owner;
req.newgid = m_in.group;
/* Issue request */
r = req_chown(&req, &ch_mode);
r = req_chown(vp->v_fs_e, vp->v_inode_nr, m_in.owner, m_in.group, &new_mode);
if(r == OK && vp) {
if(r == OK) {
vp->v_uid = m_in.owner;
vp->v_gid = m_in.group;
vp->v_mode = ch_mode;
vp->v_mode = new_mode;
}
put_vnode(vp);
return r;
}
@ -154,10 +167,8 @@ PUBLIC int do_umask()
PUBLIC int do_access()
{
/* Perform the access(name, mode) system call. */
struct access_req req;
struct lookup_req lookup_req;
struct node_details res;
int r;
struct vnode *vp;
/* First check to see if the mode is correct. */
if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
@ -165,30 +176,20 @@ PUBLIC int do_access()
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
r = lookup_vp(0 /*flags*/, TRUE /*use_realuid*/, &vp);
if (r != OK) return r;
/* Fill in request fields */
req.fs_e = res.fs_e;
req.amode = m_in.mode;
req.inode_nr = res.inode_nr;
req.uid = fp->fp_realuid; /* real user and group id */
req.gid = fp->fp_realgid;
/* Issue request */
return req_access(&req);
r= forbidden(vp, m_in.mode, 1 /*use_realuid*/);
put_vnode(vp);
return r;
}
/*===========================================================================*
* forbidden *
*===========================================================================*/
PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid)
{
/* Given a pointer to an inode, 'rip', and the access desired, determine
* if the access is allowed, and if not why not. The routine looks up the
@ -198,18 +199,31 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
register struct super_block *sp;
register mode_t bits, perm_bits;
uid_t uid;
gid_t gid;
int r, shift, type;
if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1)
{
printf("forbidden: bad uid/gid in vnode\n");
printf("forbidden: bad uid/gid in vnode: inode %d on dev 0x%x\n",
vp->v_inode_nr, vp->v_dev);
printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line);
return EACCES;
}
/* Isolate the relevant rwx bits from the mode. */
bits = vp->v_mode;
if (fp->fp_effuid == SU_UID) {
if (use_realuid)
{
uid= fp->fp_realuid;
gid= fp->fp_realgid;
}
else
{
uid= fp->fp_effuid;
gid= fp->fp_effgid;
}
if (uid == SU_UID) {
/* Grant read and write permission. Grant search permission for
* directories. Grant execute permission (for non-directories) if
* and only if one of the 'X' bits is set.
@ -220,8 +234,8 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
else
perm_bits = R_BIT | W_BIT;
} else {
if (fp->fp_effuid == vp->v_uid) shift = 6; /* owner */
else if (fp->fp_effgid == vp->v_gid ) shift = 3; /* group */
if (uid == vp->v_uid) shift = 6; /* owner */
else if (gid == vp->v_gid ) shift = 3; /* group */
else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
}

View file

@ -12,8 +12,6 @@ struct vnode;
/* device.c */
_PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags) );
_PROTOTYPE( void dev_close, (Dev_t dev) );
_PROTOTYPE( int dev_bio, (int op, Dev_t dev, int proc, void *buf,
off_t pos, int bytes) );
_PROTOTYPE( int dev_io, (int op, Dev_t dev, int proc, void *buf,
u64_t pos, int bytes, int flags) );
_PROTOTYPE( int gen_opcl, (int op, Dev_t dev, int proc, int flags) );
@ -33,6 +31,7 @@ _PROTOTYPE( void dev_up, (int major) );
_PROTOTYPE( int do_devctl, (void) );
_PROTOTYPE( int fs_devctl, (int req, int dev, int proc_nr_e, int style,
int force) );
_PROTOTYPE( int do_mapdriver, (void) );
_PROTOTYPE( void build_dmap, (void) );
_PROTOTYPE( int map_driver, (int major, int proc_nr, int dev_style,
int force) );
@ -100,20 +99,25 @@ _PROTOTYPE( int do_open, (void) );
_PROTOTYPE( int do_slink, (void) );
/* path.c */
_PROTOTYPE( int lookup, (lookup_req_t *request, node_details_t *node) );
_PROTOTYPE( int lookup_vp, (lookup_req_t *request, struct vnode **vpp) );
_PROTOTYPE( int Xlookup_vp, (lookup_req_t *request, struct vnode **vpp,
char **pathrem) );
_PROTOTYPE( int lookup_rel_vp, (struct vnode *start_node, int flags,
int use_realuid, struct vnode **vpp) );
_PROTOTYPE( int lookup_vp, (int flags, int use_realuid,
struct vnode **vpp) );
_PROTOTYPE( int lookup_lastdir_rel, (struct vnode *start_node,
int use_realuid, struct vnode **vpp) );
_PROTOTYPE( int lookup_lastdir, (int use_realuid, struct vnode **vpp) );
/* pipe.c */
_PROTOTYPE( int do_pipe, (void) );
_PROTOTYPE( int do_unpause, (void) );
_PROTOTYPE( int unpause, (int proc_nr_e) );
_PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
int oflags, int bytes, u64_t position, int *canwrite, int notouch));
_PROTOTYPE( int Xpipe_check, (struct vnode *vp, int rw_flag,
int oflags, int bytes, u64_t position, int notouch) );
_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) );
_PROTOTYPE( void revive, (int proc_nr, int bytes) );
_PROTOTYPE( void suspend, (int task) );
_PROTOTYPE( void pipe_suspend, (int rw_flag, int fd_nr, char *buf,
size_t size) );
_PROTOTYPE( int select_request_pipe, (struct filp *f, int *ops, int bl) );
_PROTOTYPE( int select_cancel_pipe, (struct filp *f) );
_PROTOTYPE( int select_match_pipe, (struct filp *f) );
@ -124,60 +128,78 @@ _PROTOTYPE( int do_access, (void) );
_PROTOTYPE( int do_chmod, (void) );
_PROTOTYPE( int do_chown, (void) );
_PROTOTYPE( int do_umask, (void) );
_PROTOTYPE( int forbidden, (struct vnode *vp, mode_t access_desired) );
_PROTOTYPE( int forbidden, (struct vnode *vp,
mode_t access_desired, int use_realuid) );
_PROTOTYPE( int read_only, (struct vnode *vp) );
/* read.c */
_PROTOTYPE( int do_read, (void) );
_PROTOTYPE( int do_getdents, (void) );
_PROTOTYPE( int read_write, (int rw_flag) );
_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr,
int fd_nr, struct filp *f, char *buf, size_t req_size) );
/* request.c */
#define req_getnode(req, res) req_getnode_f(__FILE__, __LINE__, (req), (res))
_PROTOTYPE( int req_getnode_f, (char *file, int line, node_req_t *req, node_details_t *res) );
_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) );
_PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res) );
_PROTOTYPE( int req_breadwrite, (endpoint_t fs_e, endpoint_t user_e,
Dev_t dev, u64_t pos, unsigned int num_of_bytes,
char *user_addr, int rw_flag,
u64_t *new_posp, unsigned int *cum_iop) );
_PROTOTYPE( int req_chmod, (int fs_e, ino_t inode_nr, _mnx_Mode_t rmode,
mode_t *new_modep) );
_PROTOTYPE( int req_chown, (endpoint_t fs_e, ino_t inode_nr,
_mnx_Uid_t newuid, _mnx_Gid_t newgid, mode_t *new_modep) );
_PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode,
int uid, int gid, char *path, node_details_t *res) );
_PROTOTYPE( int req_readwrite, (readwrite_req_t *req,
readwrite_res_t *res) );
_PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_t *res) );
_PROTOTYPE( int req_clone_opcl, (clone_opcl_req_t *req,
node_details_t *res) );
_PROTOTYPE( int req_ftrunc, (ftrunc_req_t *req) );
_PROTOTYPE( int req_chown, (chown_req_t *req, int *mode) );
_PROTOTYPE( int req_chmod, (chmod_req_t *req, int *mode) );
_PROTOTYPE( int req_access, (access_req_t *req) );
_PROTOTYPE( int req_mknod, (mknod_req_t *req) );
_PROTOTYPE( int req_mkdir, (mkdir_req_t *req) );
_PROTOTYPE( int req_inhibread, (node_req_t *req) );
_PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e,
char *buf, int pos) );
_PROTOTYPE( int req_flush, (endpoint_t fs_e, Dev_t dev) );
_PROTOTYPE( int req_fstatfs, (int fs_e, ino_t inode_nr, int who_e,
char *buf) );
_PROTOTYPE( int req_unlink, (unlink_req_t *req) );
_PROTOTYPE( int req_rmdir, (unlink_req_t *req) );
_PROTOTYPE( int req_utime, (utime_req_t *req) );
_PROTOTYPE( int req_stime, (endpoint_t fs_e, time_t boottime) );
_PROTOTYPE( int req_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_ftrunc, (endpoint_t fs_e, ino_t inode_nr,
off_t start, off_t end) );
_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr,
off_t pos, cp_grant_id_t gid, size_t size, off_t *pos_change) );
_PROTOTYPE( int req_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 */
_PROTOTYPE( int do_chdir, (void) );
@ -190,7 +212,6 @@ _PROTOTYPE( int do_rdlink, (void) );
_PROTOTYPE( int do_lstat, (void) );
/* time.c */
_PROTOTYPE( int do_stime, (void) );
_PROTOTYPE( int do_utime, (void) );
/* utility.c */
@ -215,8 +236,10 @@ _PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb) );
_PROTOTYPE( void dup_vnode, (struct vnode *vp) );
_PROTOTYPE( void put_vnode, (struct vnode *vp) );
_PROTOTYPE( void vnode_clean_refs, (struct vnode *vp) );
#if 0
_PROTOTYPE( struct vnode *get_vnode, (int fs_e, int inode_nr) );
_PROTOTYPE( struct vnode *get_vnode_x, (int fs_e, int inode_nr) );
#endif
#if 0
_PROTOTYPE( void mark_vn, (struct vnode *vp, char *file, int line) );
_PROTOTYPE( int check_vrefs, (void) );

View file

@ -27,7 +27,6 @@
#include "vnode.h"
#include "vmnt.h"
/*===========================================================================*
* do_read *
*===========================================================================*/
@ -47,70 +46,74 @@ int rw_flag; /* READING or WRITING */
register struct filp *f;
register struct vnode *vp;
off_t bytes_left;
u64_t position;
unsigned int off, cum_io;
int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
int regular, partial_pipe = 0, partial_cnt = 0;
u64_t position, res_pos, new_pos;
unsigned int off, cum_io, cum_io_incr, res_cum_io, num_of_bytes;
int op, oflags, r, chunk, usr, block_spec, char_spec;
int regular;
mode_t mode_word;
struct filp *wf;
phys_bytes p;
struct dmap *dp;
/* Request and response structures */
struct readwrite_req req;
struct readwrite_res res;
/* For block spec files */
struct breadwrite_req breq;
/* PM loads segments by putting funny things in other bits of the
* message, indicated by a high bit in fd. */
if (who_e == PM_PROC_NR && (m_in.fd & _PM_SEG_FLAG)) {
seg = (int) m_in.m1_p2;
usr = (int) m_in.m1_p3;
m_in.fd &= ~(_PM_SEG_FLAG); /* get rid of flag bit */
panic(__FILE__,
"read_write: special read/write calls by PM no longer supported",
NO_NUM);
}
else {
usr = who_e; /* normal case */
seg = D;
}
/* If the file descriptor is valid, get the vnode, size and mode. */
if (m_in.nbytes < 0) return(EINVAL);
if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
if (m_in.nbytes < 0)
return(EINVAL);
if ((f = get_filp(m_in.fd)) == NIL_FILP)
{
printf("vfs:read_write: returning %d\n", err_code);
return(err_code);
}
if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
printf("vfs:read_write: returning error\n");
return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
}
if (m_in.nbytes == 0)
return(0); /* so char special files need not check for 0*/
/* check if user process has the memory it needs.
* if not, copying will fail later.
* do this after 0-check above because umap doesn't want to map 0 bytes. */
if ((r = sys_umap(usr, seg, (vir_bytes) m_in.buffer, m_in.nbytes, &p)) != OK)
{
printf("VFS: read_write: umap failed for process %d\n", usr);
return r;
}
position = f->filp_pos;
oflags = f->filp_flags;
vp = f->filp_vno;
r = OK;
if (vp->v_pipe == I_PIPE) {
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
cum_io = fp->fp_cum_io_partial;
}
else {
cum_io = 0;
if (vp->v_pipe)
{
if (rw_flag == WRITING)
{
if (vp->v_w_pipe_busy)
{
panic(__FILE__,
"read_write: pipe already has a writer",
NO_NUM);
}
if (fp->fp_cum_io_partial != 0)
{
panic(__FILE__,
"read_write: fp_cum_io_partial not clear for new pipe writer",
NO_NUM);
}
vp->v_w_pipe_busy= TRUE;
}
return rw_pipe(rw_flag, usr, m_in.fd, f, m_in.buffer, m_in.nbytes);
}
r = OK;
cum_io = 0;
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
mode_word = vp->v_mode & I_TYPE;
regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
regular = mode_word == I_REGULAR;
if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
if (vp->v_sdev == NO_DEV)
@ -138,83 +141,49 @@ int rw_flag; /* READING or WRITING */
}
/* Block special files. */
else if (block_spec) {
/* Fill in the fields of the request */
breq.rw_flag = rw_flag;
breq.fs_e = vp->v_bfs_e;
breq.blocksize = vp->v_blocksize;
breq.dev = vp->v_sdev;
breq.user_e = usr;
breq.pos = position;
breq.num_of_bytes = m_in.nbytes;
breq.user_addr = m_in.buffer;
/* Issue request */
r = req_breadwrite(&breq, &res);
r = req_breadwrite(vp->v_bfs_e, usr, vp->v_sdev, position,
m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io);
position = res.new_pos;
cum_io += res.cum_io;
position = res_pos;
cum_io += res_cum_io;
}
/* Regular files (and pipes) */
/* Regular files */
else {
if (rw_flag == WRITING && block_spec == 0) {
/* Check for O_APPEND flag. */
if (oflags & O_APPEND) position = cvul64(vp->v_size);
/* Check in advance to see if file will grow too big. */
if (cmp64ul(position, vp->v_vmnt->m_max_file_size - m_in.nbytes) > 0)
return(EFBIG);
}
/* Pipes are a little different. Check. */
if (vp->v_pipe == I_PIPE) {
r = pipe_check(vp, rw_flag, oflags,
m_in.nbytes, position, &partial_cnt, 0);
if (r <= 0) return(r);
}
if (partial_cnt > 0) {
/* So that we don't need to deal with partial count
* in the FS process.
*/
m_in.nbytes = MIN(m_in.nbytes, partial_cnt);
partial_pipe = 1;
}
/* Fill in request structure */
req.fs_e = vp->v_fs_e;
req.rw_flag = rw_flag;
req.inode_nr = vp->v_inode_nr;
req.user_e = usr;
req.seg = seg;
req.pos = position;
req.num_of_bytes = m_in.nbytes;
req.user_addr = m_in.buffer;
req.inode_index = vp->v_index;
num_of_bytes = m_in.nbytes;
/* Truncate read request at size (mustn't do this for special files). */
if((rw_flag == READING) &&
cmp64ul(add64ul(position, req.num_of_bytes), vp->v_size) > 0) {
/* Position always should fit in an off_t (LONG_MAX). */
off_t pos32;
assert(cmp64ul(position, LONG_MAX) <= 0);
pos32 = cv64ul(position);
assert(pos32 >= 0);
assert(pos32 <= LONG_MAX);
req.num_of_bytes = vp->v_size - pos32;
assert(req.num_of_bytes >= 0);
cmp64ul(add64ul(position, num_of_bytes), vp->v_size) > 0) {
/* Position always should fit in an off_t (LONG_MAX). */
off_t pos32;
assert(cmp64ul(position, LONG_MAX) <= 0);
pos32 = cv64ul(position);
assert(pos32 >= 0);
assert(pos32 <= LONG_MAX);
num_of_bytes = vp->v_size - pos32;
assert(num_of_bytes >= 0);
}
/* Issue request */
r = req_readwrite(&req, &res);
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, position,
rw_flag, usr, m_in.buffer, num_of_bytes, &new_pos, &cum_io_incr);
if (r >= 0)
{
if (ex64hi(res.new_pos))
if (ex64hi(new_pos))
panic(__FILE__, "read_write: bad new pos", NO_NUM);
position = res.new_pos;
cum_io += res.cum_io;
position = new_pos;
cum_io += cum_io_incr;
}
}
@ -233,32 +202,10 @@ int rw_flag; /* READING or WRITING */
}
}
}
else {
if (vp->v_pipe == I_PIPE) {
if (cmp64ul(position, vp->v_size) >= 0) {
/* Reset pipe pointers */
vp->v_size = 0;
position = cvu64(0);
wf = find_filp(vp, W_BIT);
if (wf != NIL_FILP) wf->filp_pos = cvu64(0);
}
}
}
f->filp_pos = position;
if (r == OK) {
if (partial_pipe) {
partial_pipe = 0;
/* partial write on pipe with */
/* O_NONBLOCK, return write count */
if (!(oflags & O_NONBLOCK)) {
fp->fp_cum_io_partial = cum_io;
suspend(XPIPE); /* partial write on pipe with */
return(SUSPEND); /* nbyte > PIPE_SIZE - non-atomic */
}
}
fp->fp_cum_io_partial = 0;
return cum_io;
}
@ -266,65 +213,6 @@ int rw_flag; /* READING or WRITING */
}
/* Original "uncached" code for block spec files */
#if 0
else if (block_spec) {
char buf[_MIN_BLOCK_SIZE];
block_t b;
int bleft = m_in.nbytes;
dev_t dev = vp->v_sdev;
b = position / _MIN_BLOCK_SIZE;
off = position % _MIN_BLOCK_SIZE;
while (bleft) {
/* First read the whole block */
r = dev_bio(VFS_DEV_READ, dev, FS_PROC_NR, buf,
b * _MIN_BLOCK_SIZE, _MIN_BLOCK_SIZE);
if (r != _MIN_BLOCK_SIZE)
break;
/* How many bytes to copy? */
chunk = MIN(bleft, _MIN_BLOCK_SIZE - off);
if (rw_flag == READING) {
/* Copy a chunk from the buffer to user space. */
r = sys_vircopy(FS_PROC_NR, D, (phys_bytes) (&buf[off]),
usr, seg, (phys_bytes) m_in.buffer,
(phys_bytes) chunk);
}
else {
/* Copy a chunk from user space to the buffer. */
r = sys_vircopy(usr, seg, (phys_bytes) m_in.buffer,
FS_PROC_NR, D, (phys_bytes) (&buf[off]),
(phys_bytes) chunk);
}
/* Write back if WRITE */
if (rw_flag == WRITING) {
r = dev_bio(DEV_WRITE, dev, FS_PROC_NR, buf,
b * _MIN_BLOCK_SIZE, _MIN_BLOCK_SIZE);
if (r != _MIN_BLOCK_SIZE)
break;
}
bleft -= chunk;
m_in.buffer += chunk;
/* 0 offset in the next block */
b++;
off = 0;
}
cum_io = m_in.nbytes - bleft;
position += cum_io;
r = OK;
}
#endif
/*===========================================================================*
* do_getdents *
*===========================================================================*/
@ -366,4 +254,128 @@ PUBLIC int do_getdents()
}
/*===========================================================================*
* rw_pipe *
*===========================================================================*/
PUBLIC int rw_pipe(rw_flag, usr, fd_nr, f, buf, req_size)
int rw_flag; /* READING or WRITING */
endpoint_t usr;
int fd_nr;
struct filp *f;
char *buf;
size_t req_size;
{
int r, oflags, op, partial_pipe;
size_t size, cum_io, cum_io_incr;
struct filp *wf;
struct vnode *vp;
u64_t position, new_pos;
position = f->filp_pos;
oflags = f->filp_flags;
vp = f->filp_vno;
#if 0
printf("vfs:rw_pipe: pipe %s, buf 0x%x, size %d\n",
rw_flag == READING ? "read" : "write", buf, req_size);
printf("vfs:rw_pipe: pipe vp 00x%x, dev/num 0x%x/%d size %d, pos 0x%x:%08x\n",
vp, vp->v_dev, vp->v_inode_nr,
vp->v_size, ex64hi(position), ex64lo(position));
#endif
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
cum_io = fp->fp_cum_io_partial;
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
r = Xpipe_check(vp, rw_flag, oflags, req_size, position, 0);
if (r <= 0)
{
if (r == SUSPEND)
pipe_suspend(rw_flag, fd_nr, buf, req_size);
return(r);
}
size = r;
if (r < req_size)
partial_pipe = 1;
else
partial_pipe = 0;
/* Truncate read request at size. */
if((rw_flag == READING) &&
cmp64ul(add64ul(position, size), vp->v_size) > 0) {
/* Position always should fit in an off_t (LONG_MAX). */
off_t pos32;
assert(cmp64ul(position, LONG_MAX) <= 0);
pos32 = cv64ul(position);
assert(pos32 >= 0);
assert(pos32 <= LONG_MAX);
size = vp->v_size - pos32;
}
/* Issue request */
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, position,
rw_flag, usr, buf, size, &new_pos, &cum_io_incr);
if (r >= 0)
{
if (ex64hi(new_pos))
panic(__FILE__, "read_write: bad new pos", NO_NUM);
position = new_pos;
cum_io += cum_io_incr;
buf += cum_io_incr;
req_size -= cum_io_incr;
}
/* On write, update file size and access time. */
if (rw_flag == WRITING) {
if (cmp64ul(position, vp->v_size) > 0)
{
if (ex64hi(position) != 0)
{
panic(__FILE__,
"read_write: file size too big for v_size",
NO_NUM);
}
vp->v_size = ex64lo(position);
}
}
else {
if (cmp64ul(position, vp->v_size) >= 0) {
/* Reset pipe pointers */
vp->v_size = 0;
position = cvu64(0);
wf = find_filp(vp, W_BIT);
if (wf != NIL_FILP) wf->filp_pos = cvu64(0);
}
}
f->filp_pos = position;
if (r == OK) {
if (partial_pipe) {
/* partial write on pipe with */
/* O_NONBLOCK, return write count */
if (!(oflags & O_NONBLOCK)) {
/* partial write on pipe with req_size > PIPE_SIZE,
* non-atomic
*/
fp->fp_cum_io_partial = cum_io;
pipe_suspend(rw_flag, fd_nr, buf, req_size);
return(SUSPEND);
}
}
fp->fp_cum_io_partial = 0;
if (rw_flag == WRITING)
vp->v_w_pipe_busy= FALSE;
return cum_io;
}
return r;
}

File diff suppressed because it is too large Load diff

View file

@ -7,27 +7,20 @@
#include <sys/types.h>
/* Structure for REQ_GETNODE and REQ_PUTNODE requests */
typedef struct node_req {
endpoint_t fs_e;
ino_t inode_nr;
} node_req_t;
/* Structure for response that contains inode details */
typedef struct node_details {
endpoint_t fs_e;
ino_t inode_nr;
mode_t fmode;
off_t fsize;
unsigned short inode_index;
/* For char/block special files */
dev_t dev;
/* Fields used by the exec() syscall */
uid_t uid;
gid_t gid;
time_t ctime;
/* For faster access */
unsigned short inode_index;
/* For char/block special files */
dev_t dev;
} node_details_t;
@ -43,35 +36,6 @@ typedef struct open_req {
} open_req_t;
/* Structure for REQ_READ and REQ_WRITE request */
typedef struct readwrite_req {
int rw_flag;
endpoint_t fs_e;
endpoint_t user_e;
ino_t inode_nr;
unsigned short inode_index;
int seg;
u64_t pos;
unsigned int num_of_bytes;
char *user_addr;
} readwrite_req_t;
/* Structure for response of REQ_READ and REQ_WRITE */
typedef struct readwrite_res {
u64_t new_pos;
unsigned int cum_io;
} readwrite_res_t;
/* Structure for REQ_PIPE request */
typedef struct pipe_req {
int fs_e;
uid_t uid;
gid_t gid;
} pipe_req_t;
/* Structure for REQ_CLONE_OPCL request */
typedef struct clone_opcl_req {
int fs_e;
@ -79,147 +43,6 @@ typedef struct clone_opcl_req {
} clone_opcl_req_t;
/* Structure for REQ_FTRUNC request */
typedef struct ftrunc_req {
int fs_e;
ino_t inode_nr;
off_t start;
off_t end;
} ftrunc_req_t;
/* Structure for REQ_CHOWN request */
typedef struct chown_req {
int fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
uid_t newuid;
gid_t newgid;
} chown_req_t;
/* Structure for REQ_CHMOD request */
typedef struct chmod_req {
int fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
mode_t rmode;
} chmod_req_t;
/* Structure for REQ_ACCESS request */
typedef struct access_req {
int fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
mode_t amode;
} access_req_t;
/* Structure for REQ_MKNOD request */
typedef struct mknod_req {
int fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
mode_t rmode;
dev_t dev;
char *lastc;
} mknod_req_t;
/* Structure for REQ_MKDIR request */
typedef struct mkdir_req {
int fs_e;
ino_t d_inode_nr;
uid_t uid;
gid_t gid;
mode_t rmode;
char *lastc;
} mkdir_req_t;
/* Structure for REQ_UNLINK request */
typedef struct unlink_req {
int fs_e;
ino_t d_inode_nr;
uid_t uid;
gid_t gid;
char *lastc;
} unlink_req_t;
/* Structure for REQ_UTIME request */
typedef struct utime_req {
int fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
time_t actime;
time_t modtime;
} utime_req_t;
/* Structure for REQ_LINK request */
typedef struct link_req {
endpoint_t fs_e;
ino_t linked_file;
ino_t link_parent;
uid_t uid;
gid_t gid;
char *lastc;
} link_req_t;
/* Structure for REQ_SLINK request */
typedef struct slink_req {
endpoint_t fs_e;
ino_t parent_dir;
uid_t uid;
gid_t gid;
char *lastc;
endpoint_t who_e;
char *path_addr;
unsigned short path_length;
} slink_req_t;
/* Structure for REQ_RDLINK request */
typedef struct rdlink_req {
endpoint_t fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
endpoint_t who_e;
char *path_buffer;
unsigned short max_length;
} rdlink_req_t;
/* Structure for REQ_RENAME request */
typedef struct rename_req {
endpoint_t fs_e;
ino_t old_dir;
ino_t new_dir;
uid_t uid;
gid_t gid;
char *old_name;
char *new_name;
} rename_req_t;
/* Structure for REQ_MOUNTPOINT request */
typedef struct mountpoint_req {
endpoint_t fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
} mountpoint_req_t;
/* Structure for REQ_READSUPER request */
typedef struct readsuper_req {
endpoint_t fs_e;
@ -242,16 +65,6 @@ typedef struct readsuper_res {
} readsuper_res_t;
/* Structure for REQ_TRUNC request */
typedef struct trunc_req {
endpoint_t fs_e;
ino_t inode_nr;
uid_t uid;
gid_t gid;
off_t length;
} trunc_req_t;
/* Structure for REQ_LOOKUP request */
typedef struct lookup_req {
/* Fields filled in by the caller */
@ -285,19 +98,4 @@ typedef struct lookup_res {
} lookup_res_t;
/* Structure for REQ_BREAD and REQ_BWRITE request (block spec files) */
typedef struct breadwrite_req {
int rw_flag;
short blocksize;
endpoint_t fs_e;
endpoint_t user_e;
endpoint_t driver_e;
dev_t dev;
u64_t pos;
unsigned int num_of_bytes;
char *user_addr;
} breadwrite_req_t;
/* Structure for REQ_ request */

View file

@ -47,7 +47,7 @@ PUBLIC int do_fchdir()
return ENOTDIR;
/* Issue request and handle error */
r = forbidden(rfilp->filp_vno, X_BIT);
r = forbidden(rfilp->filp_vno, X_BIT, 0 /*!use_realuid*/);
if (r != OK) return r;
rfilp->filp_vno->v_ref_count++; /* change_into expects a reference */
@ -122,18 +122,12 @@ int len; /* length of the directory name string */
{
/* Do the actual work for chdir() and chroot(). */
struct vnode *vp;
struct lookup_req lookup_req;
int r;
if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup_vp(&lookup_req, &vp)) != OK) return r;
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* Is it a dir? */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
@ -143,7 +137,7 @@ int len; /* length of the directory name string */
}
/* Access check */
r = forbidden(vp, X_BIT);
r = forbidden(vp, X_BIT, 0 /*!use_realuid*/);
if (r != OK) {
put_vnode(vp);
return r;
@ -174,22 +168,19 @@ struct vnode *vp; /* this is what the inode has to become */
PUBLIC int do_stat()
{
/* Perform the stat(name, buf) system call. */
struct node_details res;
struct lookup_req lookup_req;
int r;
struct vnode *vp;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Fill in lookup request fields */
lookup_req.path = user_fullpath;
lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK)
return r;
/* Issue request */
return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0);
r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
put_vnode(vp);
return r;
}
@ -246,13 +237,13 @@ PUBLIC int do_fstatfs()
/*===========================================================================*
* do_lstat *
* do_lstat *
*===========================================================================*/
PUBLIC int do_lstat()
{
/* Perform the lstat(name, buf) system call. */
struct node_details res;
struct lookup_req lookup_req;
struct vnode *vp;
int r;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
@ -263,10 +254,15 @@ PUBLIC int do_lstat()
lookup_req.flags = EAT_PATH_OPAQUE;
/* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r;
if ((r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp)) != OK)
return r;
/* Issue request */
return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0);
r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
put_vnode(vp);
return r;
}

View file

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

View file

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

View file

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

View file

@ -21,3 +21,13 @@ typedef struct { /* V2.x disk inode */
time_t d2_ctime; /* when was inode data last changed */
zone_t d2_zone[V2_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
} d2_inode;
#if 1
extern struct dmap {
int _PROTOTYPE ((*dmap_opcl), (int, Dev_t, int, int) );
int _PROTOTYPE ((*dmap_io), (int, message *) );
int dmap_driver;
int dmap_flags;
} dmap[];
#endif

View file

@ -143,10 +143,14 @@ PUBLIC time_t clock_time()
* rate and that such things as leap seconds do not exist.
*/
register int k;
register int r;
clock_t uptime;
time_t boottime;
r= getuptime2(&uptime, &boottime);
if (r != OK)
panic(__FILE__,"clock_time err", r);
if ( (k=getuptime(&uptime)) != OK) panic(__FILE__,"clock_time err", k);
return( (time_t) (boottime + (uptime/HZ)));
}

View file

@ -5,8 +5,6 @@ EXTERN struct vmnt {
dev_t m_dev; /* device number */
int m_driver_e; /* device driver process' kernel endpoint */
int m_flags; /* mount flags */
int m_max_file_size; /* maximum file size on partition */
unsigned short m_block_size; /* block size */
struct vnode *m_mounted_on; /* the vnode on which the partition is mounted */
struct vnode *m_root_node; /* root vnode */
} vmnt[NR_MNTS];

View file

@ -19,86 +19,6 @@
#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 *
@ -114,6 +34,7 @@ int line;
if (vp->v_ref_count == 0)
{
vp->v_pipe= NO_PIPE;
vp->v_w_pipe_busy= FALSE;
vp->v_uid= -1;
vp->v_gid= -1;
vp->v_sdev= -1;

View file

@ -11,6 +11,7 @@ EXTERN struct vnode {
int v_fs_count; /* # reference at the underlying FS */
int v_ref_check; /* for consistency checks */
char v_pipe; /* set to I_PIPE if pipe */
char v_w_pipe_busy; /* true iff writer suspended */
off_t v_pipe_rd_pos;
off_t v_pipe_wr_pos;
endpoint_t v_bfs_e; /* endpoint number for the FS proces in case
@ -20,7 +21,6 @@ EXTERN struct vnode {
inode resides */
Dev_t v_sdev; /* device number for special files */
int v_blocksize; /* block size of the filesys */
unsigned short v_index; /* inode's index in the FS inode table */
struct vmnt *v_vmnt; /* vmnt object of the partition */