[comp.os.minix] fs patches part 3/3

poole@forty2.UUCP (Simon Poole) (03/14/89)

echo x - fs/Makefile.cdiff
gres '^X' '' > fs/Makefile.cdiff << '/'
X*** Makefile	Thu Mar  2 23:36:33 1989
X--- ../Makefile	Thu Mar  2 23:45:07 1989
X***************
X*** 9,15 ****
X  	  path.o mount.o link.o super.o inode.o cache.o filedes.o \
X  	  stadir.o protect.o time.o misc.o utility.o table.o putc.o
X  HDR	= ../h/callnr.h ../h/com.h ../h/const.h ../h/error.h \
X! 	  ../h/signal.h ../h/stat.h ../h/type.h \
X  	  buf.h const.h dev.h file.h fproc.h \
X  	  glo.h inode.h param.h super.h type.h
X  ALL	= fs.mix
X--- 9,15 ----
X  	  path.o mount.o link.o super.o inode.o cache.o filedes.o \
X  	  stadir.o protect.o time.o misc.o utility.o table.o putc.o
X  HDR	= ../h/callnr.h ../h/com.h ../h/const.h ../h/error.h \
X! 	  ../h/fcntl.h ../h/signal.h ../h/stat.h ../h/type.h \
X  	  buf.h const.h dev.h file.h fproc.h \
X  	  glo.h inode.h param.h super.h type.h
X  ALL	= fs.mix
/
echo x - fs/cache.c.cdiff
gres '^X' '' > fs/cache.c.cdiff << '/'
X*** cache.c	Thu Mar  5 21:25:02 1989
X--- ../cache.c	Thu Mar  5 21:29:26 1989
X***************
X*** 260,266 ****
X  
X    if (bp->b_dev != NO_DEV) {
X  	pos = (long) bp->b_blocknr * BLOCK_SIZE;
X! 	r = dev_io(rw_flag, bp->b_dev, pos, BLOCK_SIZE, FS_PROC_NR, bp->b_data);
X  	if (r < 0) {
X  		dev = bp->b_dev;
X  		if (r != EOF) {
X--- 260,266 ----
X  
X    if (bp->b_dev != NO_DEV) {
X  	pos = (long) bp->b_blocknr * BLOCK_SIZE;
X! 	r = dev_io(rw_flag, FALSE, bp->b_dev, pos, BLOCK_SIZE, FS_PROC_NR, bp->b_data);
X  	if (r < 0) {
X  		dev = bp->b_dev;
X  		if (r != EOF) {
/
echo x - fs/const.h.cdiff
gres '^X' '' > fs/const.h.cdiff << '/'
X*** const.h	Thu Feb  8 00:13:32 1989
X--- ../const.h	Thu Feb  7 00:07:10 1989
X***************
X*** 24,30 ****
X  #define NORMAL	           0	/* forces get_block to do disk read */
X  #define NO_READ            1	/* prevents get_block from doing disk read */
X  
X! #define XPIPE  	           0	/* used in fp_task when suspended on pipe */
X  #define NO_BIT    (bit_nr) 0	/* returned by alloc_bit() to signal failure */
X  #define DUP_MASK        0100	/* mask to distinguish dup2 from dup */
X  
X--- 24,32 ----
X  #define NORMAL	           0	/* forces get_block to do disk read */
X  #define NO_READ            1	/* prevents get_block from doing disk read */
X  
X! #define XPIPE  -(NR_TASKS+1)	/* used in fp_task when suspended on pipe */
X! #define XOPEN  -(NR_TASKS+2)	/* used in fp_task when suspended in open */
X! 
X  #define NO_BIT    (bit_nr) 0	/* returned by alloc_bit() to signal failure */
X  #define DUP_MASK        0100	/* mask to distinguish dup2 from dup */
X  
/
echo x - fs/device.c.cdiff
gres '^X' '' > fs/device.c.cdiff << '/'
X*** device.c	Thu Mar  5 21:32:14 1989
X--- ../device.c	Thu Mar  5 22:00:14 1989
X***************
X*** 33,41 ****
X  /*===========================================================================*
X   *				dev_open				     *
X   *===========================================================================*/
X! PUBLIC int dev_open(dev, mod)
X! dev_nr dev;			/* which device to open */
X! int mod;			/* how to open it */
X  {
X  /* Special files may need special processing upon open. */
X  
X--- 33,42 ----
X  /*===========================================================================*
X   *				dev_open				     *
X   *===========================================================================*/
X! PUBLIC int dev_open(dev, mod, nonblock)
X! dev_nr dev;			/* which device to open */
X! int mod;			/* how to open it */
X! int nonblock;			/* TRUE if nonblocking open */
X  {
X  /* Special files may need special processing upon open. */
X  
X***************
X*** 62,69 ****
X  /*===========================================================================*
X   *				dev_io					     *
X   *===========================================================================*/
X! PUBLIC int dev_io(rw_flag, dev, pos, bytes, proc, buff)
X! int rw_flag;			/* READING or WRITING */
X  dev_nr dev;			/* major-minor device number */
X  long pos;			/* byte position */
X  int bytes;			/* how many bytes to transfer */
X--- 63,71 ----
X  /*===========================================================================*
X   *				dev_io					     *
X   *===========================================================================*/
X! PUBLIC int dev_io(rw_flag, nonblock, dev, pos, bytes, proc, buff)
X! int rw_flag;			/* READING or WRITING */
X! int nonblock;			/* TRUE if nonblocking op */
X  dev_nr dev;			/* major-minor device number */
X  long pos;			/* byte position */
X  int bytes;			/* how many bytes to transfer */
X***************
X*** 81,86 ****
X--- 83,89 ----
X    dev_mess.PROC_NR  = proc;
X    dev_mess.ADDRESS  = buff;
X    dev_mess.COUNT    = bytes;
X+   dev_mess.TTY_FLAGS = nonblock; /* temporary kludge */
X  
X    /* Call the task. */
X    (*dmap[major].dmap_rw)(task, &dev_mess);
/
echo x - fs/file.h.cdiff
gres '^X' '' > fs/file.h.cdiff << '/'
X*** file.h	Thu Feb  9 19:13:07 1989
X--- ../file.h	Thu Feb 11 23:50:20 1989
X***************
X*** 4,9 ****
X--- 4,10 ----
X  
X  EXTERN struct filp {
X    mask_bits filp_mode;		/* RW bits, telling how file is opened */
X+   int filp_flags;		/* flags from open and fcntl */
X    int filp_count;		/* how many file descriptors share this slot? */
X    struct inode *filp_ino;	/* pointer to the inode */
X    file_pos filp_pos;		/* file position */
/
echo x - fs/filedes.c.cdif
gres '^X' '' > fs/filedes.c.cdif << '/'
X*** filedes.c	Thu Feb 12 00:47:22 1989
X--- ../filedes.c	Thu Feb 12 16:38:40 1989
X***************
X*** 19,25 ****
X  /*===========================================================================*
X   *				get_fd					     *
X   *===========================================================================*/
X! PUBLIC int get_fd(bits, k, fpt)
X  mask_bits bits;			/* mode of the file to be created (RWX bits) */
X  int *k;				/* place to return file descriptor */
X  struct filp **fpt;		/* place to return filp slot */
X--- 19,26 ----
X  /*===========================================================================*
X   *				get_fd					     *
X   *===========================================================================*/
X! PUBLIC int get_fd(start, bits, k, fpt)
X! int start;			/* start of search (used for F_DUPFD) */
X  mask_bits bits;			/* mode of the file to be created (RWX bits) */
X  int *k;				/* place to return file descriptor */
X  struct filp **fpt;		/* place to return filp slot */
X***************
X*** 35,41 ****
X    *k = -1;			/* we need a way to tell if file desc found */
X  
X    /* Search the fproc table for a free file descriptor. */
X!   for (i = 0; i < NR_FDS; i++) {
X  	if (fp->fp_filp[i] == NIL_FILP) {
X  		/* A file descriptor has been located. */
X  		*k = i;
X--- 36,42 ----
X    *k = -1;			/* we need a way to tell if file desc found */
X  
X    /* Search the fproc table for a free file descriptor. */
X!   for (i = start; i < NR_FDS; i++) {
X  	if (fp->fp_filp[i] == NIL_FILP) {
X  		/* A file descriptor has been located. */
X  		*k = i;
X***************
X*** 51,56 ****
X--- 52,58 ----
X  	if (f->filp_count == 0) {
X  		f->filp_mode = bits;
X  		f->filp_pos = 0L;
X+ 		f->filp_flags = 0;
X  		*fpt = f;
X  		return(OK);
X  	}
/
echo x - fs/inode.c.cdiff
gres '^X' '' > fs/inode.c.cdiff << '/'
X*** inode.c	Thu Feb  7 21:56:40 1989
X--- ../inode.c	Thu Feb 12 13:38:47 1989
X***************
X*** 83,91 ****
X  		/* i_nlinks == 0 means free the inode. */
X  		truncate(rip);	/* return all the disk blocks */
X  		rip->i_mode = I_NOT_ALLOC;	/* clear I_TYPE field */
X! 		rip->i_pipe = NO_PIPE;
X! 		free_inode(rip->i_dev, rip->i_num);
X! 	}
X  
X  	if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
X    }
X--- 83,92 ----
X  		/* i_nlinks == 0 means free the inode. */
X  		truncate(rip);	/* return all the disk blocks */
X  		rip->i_mode = I_NOT_ALLOC;	/* clear I_TYPE field */
X! 		free_inode(rip->i_dev, rip->i_num);
X! 	}
X! 	else if (rip->i_pipe == I_PIPE) truncate(rip);
X! 	rip->i_pipe = NO_PIPE;  /* should always be cleared */
X  
X  	if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
X    }
/
echo x - fs/misc.c.cdiff
gres '^X' '' > fs/misc.c.cdiff << '/'
X*** misc.c	Thu Feb  6 23:40:22 1989
X--- ../misc.c	Thu Feb 14 00:20:00 1989
X***************
X*** 4,9 ****
X--- 4,10 ----
X   *
X   * The entry points into this file are
X   *   do_dup:	perform the DUP system call
X+  *   do_fcntl:	perform the FCNTL system call
X   *   do_sync:	perform the SYNC system call
X   *   do_fork:	adjust the tables after MM has performed a FORK system call
X   *   do_exit:	a process has exited; note that in the tables
X***************
X*** 16,21 ****
X--- 17,23 ----
X  #include "../h/callnr.h"
X  #include "../h/com.h"
X  #include "../h/error.h"
X+ #include "../h/fcntl.h"
X  #include "const.h"
X  #include "type.h"
X  #include "buf.h"
X***************
X*** 35,54 ****
X  /* Perform the dup(fd) or dup(fd,fd2) system call. */
X  
X    register int rfd;
X!   register struct fproc *rfp;
X    struct filp *dummy;
X    int r;
X    extern struct filp *get_filp();
X  
X    /* Is the file descriptor valid? */
X    rfd = fd & ~DUP_MASK;		/* kill off dup2 bit, if on */
X!   rfp = fp;
X!   if (get_filp(rfd) == NIL_FILP) return(err_code);
X  
X    /* Distinguish between dup and dup2. */
X    if (fd == rfd) {			/* bit not on */
X  	/* dup(fd) */
X! 	if ( (r = get_fd(0, &fd2, &dummy)) != OK) return(r);
X    } else {
X  	/* dup2(fd, fd2) */
X  	if (fd2 < 0 || fd2 >= NR_FDS) return(EBADF);
X--- 37,55 ----
X  /* Perform the dup(fd) or dup(fd,fd2) system call. */
X  
X    register int rfd;
X!   register struct filp *f;
X    struct filp *dummy;
X    int r;
X    extern struct filp *get_filp();
X  
X    /* Is the file descriptor valid? */
X    rfd = fd & ~DUP_MASK;		/* kill off dup2 bit, if on */
X!   if ((f = get_filp(rfd)) == NIL_FILP) return(err_code);
X  
X    /* Distinguish between dup and dup2. */
X    if (fd == rfd) {			/* bit not on */
X  	/* dup(fd) */
X! 	if ( (r = get_fd(0, 0, &fd2, &dummy)) != OK) return(r);
X    } else {
X  	/* dup2(fd, fd2) */
X  	if (fd2 < 0 || fd2 >= NR_FDS) return(EBADF);
X***************
X*** 58,68 ****
X    }
X  
X    /* Success. Set up new file descriptors. */
X!   rfp->fp_filp[fd2] = rfp->fp_filp[rfd];
X!   rfp->fp_filp[fd2]->filp_count++;
X    return(fd2);
X  }
X  
X  
X  /*===========================================================================*
X   *				do_sync					     *
X--- 59,105 ----
X    }
X  
X    /* Success. Set up new file descriptors. */
X!   f->filp_count++;
X!   fp->fp_filp[fd2] = f;
X    return(fd2);
X  }
X  
X+ /*===========================================================================*
X+  *				do_fcntl				     *
X+  *===========================================================================*/
X+ PUBLIC int do_fcntl()
X+ {
X+ /* Perform the fcntl(fd, request, addr) system call. */
X+ 
X+   register struct filp *f;
X+   int new_fd;
X+   struct filp *dummy;
X+   int r;
X+   extern struct filp *get_filp();
X+ 
X+   /* Is the file descriptor valid? */
X+   if ((f = get_filp(fd)) == NIL_FILP) return(err_code);
X+ 
X+   switch (request) {
X+      case F_DUPFD: /* DUP */
X+ 	if (addr < 0 || addr >= NR_FDS) break;
X+ 	if ((r = get_fd(addr, 0, &new_fd, &dummy)) != OK) return(r);
X+    	f->filp_count++;
X+   	fp->fp_filp[new_fd] = f;
X+   	return(new_fd);
X+      case F_GETFD: /* get close-on-exec flag */
X+ 	break;	
X+      case F_SETFD: /* set close-on-exec flag */
X+ 	break;	
X+      case F_GETFL: /* get file status flags */
X+ 	return(f->filp_flags);	
X+      case F_SETFL: /* set file status flags */
X+ 	f->filp_flags = (f->filp_flags & ~F_FL_LEGAL) | (addr & F_FL_LEGAL);
X+ 	return(OK);
X+   }
X+   return(EINVAL);
X+ }
X+ 
X  
X  /*===========================================================================*
X   *				do_sync					     *
X***************
X*** 165,171 ****
X  {
X  /* Perform the file system portion of the exit(status) system call. */
X  
X!   register int i, exitee;
X  
X    /* Only MM may do the EXIT call directly. */
X    if (who != MM_PROC_NR) return(ERROR);
X--- 202,208 ----
X  {
X  /* Perform the file system portion of the exit(status) system call. */
X  
X!   register int i, exitee, task;
X  
X    /* Only MM may do the EXIT call directly. */
X    if (who != MM_PROC_NR) return(ERROR);
X***************
X*** 179,185 ****
X  	tty_exit();
X  
X    if (fp->fp_suspended == SUSPENDED) {
X! 	if (fp->fp_task == XPIPE) susp_count--;
X  	pro = exitee;
X  	do_unpause();
X  	fp->fp_suspended = NOT_SUSPENDED;
X--- 216,223 ----
X  	tty_exit();
X  
X    if (fp->fp_suspended == SUSPENDED) {
X! 	task = -fp->fp_task;
X! 	if (task == XPIPE || task == XOPEN) susp_count--;
X  	pro = exitee;
X  	do_unpause();
X  	fp->fp_suspended = NOT_SUSPENDED;
/
echo x - fs/open.c
gres '^X' '' > fs/open.c << '/'
X/* This file contains the procedures for creating, opening, closing, and
X * seeking on files.
X *
X * The entry points into this file are
X *   do_creat:	perform the CREAT system call
X *   do_mknod:	perform the MKNOD system call
X *   do_open:	perform the OPEN system call
X *   do_close:	perform the CLOSE system call
X *   do_lseek:  perform the LSEEK system call
X */
X
X#include "../h/const.h"
X#include "../h/type.h"
X#include "../h/callnr.h"
X#include "../h/error.h"
X#include "../h/fcntl.h"
X#include "const.h"
X#include "type.h"
X#include "buf.h"
X#include "file.h"
X#include "fproc.h"
X#include "glo.h"
X#include "inode.h"
X#include "param.h"
X
XPRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
X
X/*===========================================================================*
X *				do_creat				     *
X *===========================================================================*/
XPUBLIC int do_creat()
X{
X/* Perform the creat(name, mode) system call. */
X  /* get name */
X  if (fetch_name(name, name_length, M3) != OK) return(err_code);
X  return common_open(O_WRONLY | O_CREAT | O_TRUNC, (mask_bits) mode);
X}
X
X
X/*===========================================================================*
X *				do_mknod				     *
X *===========================================================================*/
XPUBLIC int do_mknod()
X{
X/* Perform the mknod(name, mode, addr) system call. */
X
X  register mask_bits bits;
X  struct inode *new_node();
X
X  /* only super_user may make nodes other than fifo's */
X  if (!super_user && (mode & I_TYPE != I_NAMED_PIPE)) return(EPERM);
X  if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
X  bits = (mode & I_TYPE) | (mode  & ALL_MODES & fp->fp_umask);
X  put_inode(new_node(user_path, bits, (zone_nr) addr));
X  return(err_code);
X}
X
X
X/*===========================================================================*
X *				new_node				     *
X *===========================================================================*/
XPRIVATE struct inode *new_node(path, bits, z0)
Xchar *path;			/* pointer to path name */
Xmask_bits bits;			/* mode of the new inode */
Xzone_nr z0;			/* zone number 0 for new inode */
X{
X/* This function is called by common_open() and do_mknod().  In both cases it
X * allocates a new inode, makes a directory entry for it on the path 'path',
X * and initializes it.  It returns a pointer to the inode if it can do this;
X * err_code is set to OK or EEXIST. If it can't, it returns NIL_INODE and
X * 'err_code' contains the appropriate message.
X */
X
X  register struct inode *rlast_dir_ptr, *rip;
X  register int r;
X  char string[NAME_SIZE];
X  extern struct inode *alloc_inode(), *advance(), *last_dir();
X
X  /* See if the path can be opened down to the last directory. */
X  if ((rlast_dir_ptr = last_dir(path, string)) == NIL_INODE) return(NIL_INODE);
X
X  /* The final directory is accessible. Get final component of the path. */
X  rip = advance(rlast_dir_ptr, string);
X  if ( rip == NIL_INODE && err_code == ENOENT) {
X	/* Last path component does not exist.  Make new directory entry. */
X	if ( (rip = alloc_inode(rlast_dir_ptr->i_dev, bits)) == NIL_INODE) {
X		/* Can't creat new inode: out of inodes. */
X		put_inode(rlast_dir_ptr);
X		return(NIL_INODE);
X	}
X
X	/* Force inode to the disk before making directory entry to make
X	 * the system more robust in the face of a crash: an inode with
X	 * no directory entry is much better than the opposite.
X	 */
X	rip->i_nlinks++;
X	rip->i_zone[0] = z0;
X	rw_inode(rip, WRITING);		/* force inode to disk now */
X
X	/* New inode acquired.  Try to make directory entry. */
X	if ((r = search_dir(rlast_dir_ptr, string, &rip->i_num,ENTER)) != OK) {
X		put_inode(rlast_dir_ptr);
X		rip->i_nlinks--;	/* pity, have to free disk inode */
X		rip->i_dirt = DIRTY;	/* dirty inodes are written out */
X		put_inode(rip);	/* this call frees the inode */
X		err_code = r;
X		return(NIL_INODE);
X	}
X
X  } else {
X	/* Either last component exists, or there is some problem. */
X	if (rip != NIL_INODE)
X		r = EEXIST;
X	else
X		r = err_code;
X  }
X
X  /* Return the directory inode and exit. */
X  put_inode(rlast_dir_ptr);
X  err_code = r;
X  return(rip);
X}
X
X
X/*===========================================================================*
X *				do_open					     *
X *===========================================================================*/
XPUBLIC int do_open()
X{
X/* Perform the open(name, flags,...) system call. */
X
X  int create_mode = 0;
X  int r;
X
X  /* check if mode flags are legal */
X  if (mode & ~O_LEGAL) return(EINVAL);
X
X  /* if O_CREAT is set, open has three parameters, otherwise two */
X  if (mode & O_CREAT) {
X	create_mode = c_mode;	
X	r = fetch_name(c_name, name1_length, M1);
X  }
X  else r = fetch_name(name, name_length, M3);
X
X  if (r != OK) return(err_code); /* name was bad */
X  return common_open(mode, (mask_bits) create_mode);
X}
X
X
X/*===========================================================================*
X *				common_open				     *
X *===========================================================================*/
XPRIVATE int common_open(oflags, omode)
Xregister int oflags;
Xmask_bits omode;
X{
X/* common code from do_creat and do_open */
X
X  register struct inode *rip;
X  register int r;
X  register mask_bits bits;
X  struct filp *fil_ptr;
X  int exist = TRUE;
X  int trunc;
X  extern struct inode *eat_path();
X
X
X  /* remap the bottom two bits of oflags */
X  bits = (mask_bits) mode_map[oflags & 3];
X  /* See if file descriptor and filp slots are available. */
X  if ( (r = get_fd(0, bits, &fd, &fil_ptr)) != OK) return(r);
X
X  /* if O_CREATE is set, try to make the file */ 
X  if (oflags & O_CREAT) {
X  	/* Create a new inode by calling new_node(). */
X        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
X    	rip = new_node(user_path, omode, NO_ZONE);
X    	r = err_code;
X    	if (r == OK) exist = FALSE;      /* we just created the file */
X	else if (r != EEXIST) return(r); /* other error */
X	else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
X					    flag is set this is an error */
X  }
X  else  /* Scan path name. */
X    	if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
X
X
X  /* only do the normal open code if we didn't just create the file */
X  if (exist) {
X
X  	/* O_TRUNC and O_CREAT implies W_BIT */
X	if (trunc = (oflags & (O_TRUNC | O_CREAT))) bits |= W_BIT;
X
X  	/* check protections */
X  	if ((r = forbidden(rip, bits, 0)) == OK) {
X  		/* 
X         	 * Opening regular files, 
X   	 	 * directories and special files are different. 
X   	 	 */
X	  	switch (rip->i_mode & I_TYPE) {
X    		   case I_REGULAR: /* truncate regular file if O_TRUNC */
X		      if (trunc) truncate(rip);
X		      break;
X 
X	    	   case I_DIRECTORY: /* can only read directories */
X		      r = bits & W_BIT ? EISDIR : OK;
X		      break;
X
X	     	   case I_CHAR_SPECIAL:
X     		   case I_BLOCK_SPECIAL:
X		      r = dev_open((dev_nr) rip->i_zone[0], (int) bits, 
X					oflags & O_NONBLOCK);
X		      break;
X
X		   case I_NAMED_PIPE:
X		      r = pipe_open(rip, bits, oflags);
X		      break;
X 		}
X  	}
X  }
X
X  /* If error, return inode. */
X  if (r != OK) {
X	put_inode(rip);
X	return(r);
X  }
X  
X  /* Claim the file descriptor and filp slot and fill them in. */
X  fp->fp_filp[fd] = fil_ptr;
X  fil_ptr->filp_count = 1;
X  fil_ptr->filp_ino = rip;
X  fil_ptr->filp_flags = oflags;
X  return(fd);
X}
X
X/*===========================================================================*
X *				pipe_open				     *
X *===========================================================================*/
XPRIVATE int pipe_open(rip, bits, oflags)
Xregister struct inode *rip;
Xregister mask_bits bits;
Xregister int oflags;
X{
X/*  this function is called from do_creat and do_open, it checks if
X *  there is at least one reader/writer pair for the pipe, if not
X *  it suspends the caller, otherwise it revives all other blocked
X *  processes hanging on the pipe.
X */
X
X  if (find_filp(rip, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { 
X	if (oflags & O_NONBLOCK)
X		return bits & W_BIT ? ENXIO : OK;  
X	suspend(XOPEN); /* suspend caller */
X  }	
X  else if (susp_count > 0) {/* revive blocked processes */
X	release(rip, OPEN, susp_count);
X	release(rip, CREAT, susp_count);
X  }
X  rip->i_pipe = I_PIPE; 
X
X  return OK ;
X}
X
X
X/*===========================================================================*
X *				do_close				     *
X *===========================================================================*/
XPUBLIC int do_close()
X{
X/* Perform the close(fd) system call. */
X
X  register struct filp *rfilp;
X  register struct inode *rip;
X  int rw;
X  int mode_word;
X  extern struct filp *get_filp();
X
X  /* First locate the inode that belongs to the file descriptor. */
X  if ( (rfilp = get_filp(fd)) == NIL_FILP) return(err_code);
X  rip = rfilp->filp_ino;	/* 'rip' points to the inode */
X
X  /* Check to see if the file is special. */
X  mode_word = rip->i_mode & I_TYPE;
X  if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
X	if (mode_word == I_BLOCK_SPECIAL)  {
X		/* Invalidate cache entries unless special is mounted or ROOT.*/
X		do_sync();	/* purge cache */
X		if (mounted(rip) == FALSE) invalidate((dev_nr) rip->i_zone[0]);
X	}
X	dev_close((dev_nr) rip->i_zone[0]);
X  }
X
X  /* If the inode being closed is a pipe, release everyone hanging on it. */
X  if (rip->i_pipe) {
X	rw = (rfilp->filp_mode & R_BIT ? WRITE : READ);
X	release(rip, rw, NR_PROCS);
X  }
X
X  /* If a write has been done, the inode is already marked as DIRTY. */
X  if (--rfilp->filp_count == 0) put_inode(rip);
X
X  fp->fp_filp[fd] = NIL_FILP;
X  return(OK);
X}
X
X
X/*===========================================================================*
X *				do_lseek				     *
X *===========================================================================*/
XPUBLIC int do_lseek()
X{
X/* Perform the lseek(ls_fd, offset, whence) system call. */
X
X  register struct filp *rfilp;
X  register file_pos pos;
X  extern struct filp *get_filp();
X
X  /* Check to see if the file descriptor is valid. */
X  if ( (rfilp = get_filp(ls_fd)) == NIL_FILP) return(err_code);
X
X  /* No lseek on pipes. */
X  if (rfilp->filp_ino->i_pipe == I_PIPE) return(ESPIPE);
X
X  /* The value of 'whence' determines the algorithm to use. */
X  switch(whence) {
X	case 0:	pos = offset;	break;
X	case 1: pos = rfilp->filp_pos + offset;	break;
X	case 2: pos = rfilp->filp_ino->i_size + offset;	break;
X	default: return(EINVAL);
X  }
X  if (pos < (file_pos) 0) return(EINVAL);
X
X  rfilp->filp_ino->i_seek = ISEEK;	/* inhibit read ahead */
X  rfilp->filp_pos = pos;
X
X  reply_l1 = pos;		/* insert the long into the output message */
X  return(OK);
X}
/
echo x - fs/param.h.cdiff
gres '^X' '' > fs/param.h.cdiff << '/'
X*** param.h	Thu Feb  9 23:15:02 1989
X--- ../param.h	Thu Feb  9 23:25:50 1989
X***************
X*** 16,21 ****
X--- 16,23 ----
X  #define ls_fd	      m.m2_i1
X  #define mk_mode	      m.m1_i2
X  #define mode	      m.m3_i2
X+ #define c_mode        m.m1_i3
X+ #define c_name        m.m1_p1
X  #define name	      m.m3_p1
X  #define name1	      m.m1_p1
X  #define name2	      m.m1_p2
/
echo x - fs/pipe.c.cdiff
gres '^X' '' > fs/pipe.c.cdiff << '/'
X*** pipe.c	Thu Feb  6 01:10:36 1989
X--- ../pipe.c	Thu Feb 12 22:36:07 1989
X***************
X*** 19,24 ****
X--- 19,25 ----
X  #include "../h/com.h"
X  #include "../h/error.h"
X  #include "../h/signal.h"
X+ #include "../h/fcntl.h"
X  #include "const.h"
X  #include "type.h"
X  #include "file.h"
X***************
X*** 46,55 ****
X  
X    /* Acquire two file descriptors. */
X    rfp = fp;
X!   if ( (r = get_fd(R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
X!   rfp->fp_filp[fil_des[0]] = fil_ptr0;
X!   fil_ptr0->filp_count = 1;
X!   if ( (r = get_fd(W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
X  	rfp->fp_filp[fil_des[0]] = NIL_FILP;
X  	fil_ptr0->filp_count = 0;
X  	return(r);
X--- 47,56 ----
X  
X    /* Acquire two file descriptors. */
X    rfp = fp;
X!   if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
X!   rfp->fp_filp[fil_des[0]] = fil_ptr0;
X!   fil_ptr0->filp_count = 1;
X!   if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
X  	rfp->fp_filp[fil_des[0]] = NIL_FILP;
X  	fil_ptr0->filp_count = 0;
X  	return(r);
X***************
X*** 81,89 ****
X  /*===========================================================================*
X   *				pipe_check				     *
X   *===========================================================================*/
X! PUBLIC int pipe_check(rip, rw_flag, virgin, bytes, position)
X! register struct inode *rip;	/* the inode of the pipe */
X! int rw_flag;			/* READING or WRITING */
X  int virgin;			/* 1 if no data transferred yet, else 0 */
X  register int bytes;		/* bytes to be read or written (all chunks) */
X  register file_pos *position;	/* pointer to current file position */
X--- 82,91 ----
X  /*===========================================================================*
X   *				pipe_check				     *
X   *===========================================================================*/
X! PUBLIC int pipe_check(rip, rw_flag, oflags, virgin, bytes, position)
X! register struct inode *rip;	/* the inode of the pipe */
X! int rw_flag;			/* READING or WRITING */
X! int oflags;			/* flags set by open or fcntl */
X  int virgin;			/* 1 if no data transferred yet, else 0 */
X  register int bytes;		/* bytes to be read or written (all chunks) */
X  register file_pos *position;	/* pointer to current file position */
X***************
X*** 96,113 ****
X  
X    extern struct filp *find_filp();
X  
X    /* If reading, check for empty pipe. */
X    if (rw_flag == READING) {
X  	if (*position >= rip->i_size) {
X  		/* Process is reading from an empty pipe. */
X  		if (find_filp(rip, W_BIT) != NIL_FILP) {
X  			/* Writer exists; suspend rdr if no data already read.*/
X! 			if (virgin) suspend(XPIPE);	/* block reader */
X! 
X! 			/* If need be, activate sleeping writer. */
X! 			if (susp_count > 0) release(rip, WRITE, 1);
X! 		}
X! 		return(0);
X  	}
X    } else {
X  	/* Process is writing to a pipe. */
X--- 98,119 ----
X  
X    extern struct filp *find_filp();
X  
X+   int r = 0;
X+ 
X    /* If reading, check for empty pipe. */
X    if (rw_flag == READING) {
X  	if (*position >= rip->i_size) {
X  		/* Process is reading from an empty pipe. */
X  		if (find_filp(rip, W_BIT) != NIL_FILP) {
X  			/* Writer exists; suspend rdr if no data already read.*/
X! 			if (virgin) {
X! 				if (oflags & O_NONBLOCK) r = EAGAIN;
X! 				else suspend(XPIPE);	/* block reader */
X! 			}
X! 			/* If need be, activate sleeping writers. */
X! 			if (susp_count > 0) release(rip, WRITE, susp_count);
X! 		}
X! 		return(r);
X  	}
X    } else {
X  	/* Process is writing to a pipe. */
X***************
X*** 119,130 ****
X  	}
X  
X  	if (*position + bytes > PIPE_SIZE) {
X  		suspend(XPIPE);	/* stop writer -- pipe full */
X  		return(0);
X  	}
X  
X! 	/* Writing to an empty pipe.  Search for suspended reader. */
X! 	if (*position == 0) release(rip, READ, 1);
X    }
X  
X    return(1);
X--- 125,137 ----
X  	}
X  
X  	if (*position + bytes > PIPE_SIZE) {
X+ 		if (oflags & O_NONBLOCK) return(EAGAIN);
X  		suspend(XPIPE);	/* stop writer -- pipe full */
X  		return(0);
X  	}
X  
X! 	/* Writing to an empty pipe.  Search for suspended readers. */
X! 	if (*position == 0) release(rip, READ, susp_count);
X    }
X  
X    return(1);
X***************
X*** 143,149 ****
X   * but they are needed for pipes, and it is not worth making the distinction.)
X   */
X  
X!   if (task == XPIPE) susp_count++;	/* count procs suspended on pipe */
X    fp->fp_suspended = SUSPENDED;
X    fp->fp_fd = fd << 8 | fs_call;
X    fp->fp_buffer = buffer;
X--- 150,156 ----
X   * but they are needed for pipes, and it is not worth making the distinction.)
X   */
X  
X!   if (task == XPIPE || task == XOPEN) susp_count++;/* count procs suspended on pipe */
X    fp->fp_suspended = SUSPENDED;
X    fp->fp_fd = fd << 8 | fs_call;
X    fp->fp_buffer = buffer;
X***************
X*** 192,197 ****
X--- 199,205 ----
X   */
X  
X    register struct fproc *rfp;
X+   register int task;
X  
X    if (proc_nr < 0 || proc_nr >= NR_PROCS) panic("revive err", proc_nr);
X    rfp = &fproc[proc_nr];
X***************
X*** 202,216 ****
X     * For TTY revival, the work is already done, for pipes it is not: the proc
X     * must be restarted so it can try again.
X     */
X!   if (rfp->fp_task == XPIPE) {
X  	/* Revive a process suspended on a pipe. */
X  	rfp->fp_revived = REVIVING;
X  	reviving++;		/* process was waiting on pipe */
X    } else {
X! 	/* Revive a process suspended on TTY or other device. */
X! 	rfp->fp_suspended = NOT_SUSPENDED;
X! 	rfp->fp_nbytes = bytes;	/* pretend it only wants what there is */
X! 	reply(proc_nr, bytes);	/* unblock the process */
X    }
X  }
X  
X--- 210,229 ----
X     * For TTY revival, the work is already done, for pipes it is not: the proc
X     * must be restarted so it can try again.
X     */
X!   task = -rfp->fp_task;
X!   if (task == XPIPE) {
X  	/* Revive a process suspended on a pipe. */
X  	rfp->fp_revived = REVIVING;
X  	reviving++;		/* process was waiting on pipe */
X    } else {
X! 	rfp->fp_suspended = NOT_SUSPENDED;
X! 	if (task == XOPEN) /* process blocked in open or create */
X! 		reply(proc_nr, rfp->fp_fd>>8);
X! 	else {
X! 		/* Revive a process suspended on TTY or other device. */
X! 		rfp->fp_nbytes = bytes;	/* pretend it only wants what there is */
X! 		reply(proc_nr, bytes);	/* unblock the process */
X! 	}
X    }
X  }
X  
X***************
X*** 238,253 ****
X    task = -rfp->fp_task;
X  
X    if (task != XPIPE) {
X! 	fild = (rfp->fp_fd >> 8) & BYTE;	/* extract file descriptor */
X! 	if (fild < 0 || fild >= NR_FDS) panic("unpause err 2", NO_NUM);
X! 	f = rfp->fp_filp[fild];
X! 	dev = f->filp_ino->i_zone[0];	/* device on which proc is hanging */
X! 	mess.TTY_LINE = (dev >> MINOR) & BYTE;
X! 	mess.PROC_NR = proc_nr;
X! 	mess.m_type = CANCEL;
X! 	rw_dev(task, &mess);
X! 	revive(proc_nr, EINTR);	/* signal interrupted call */
X!   }
X! 
X!   return(OK);
X! }
X--- 251,268 ----
X    task = -rfp->fp_task;
X  
X    if (task != XPIPE) {
X! 	if (task != XOPEN) {
X! 		fild = (rfp->fp_fd >> 8) & BYTE;/* extract file descriptor */
X! 		if (fild < 0 || fild >= NR_FDS) panic("unpause err 2", NO_NUM);
X! 		f = rfp->fp_filp[fild];
X! 		dev = f->filp_ino->i_zone[0];	/* device on which proc is hanging */
X! 		mess.TTY_LINE = (dev >> MINOR) & BYTE;
X! 		mess.PROC_NR = proc_nr;
X! 		mess.m_type = CANCEL;
X! 		rw_dev(task, &mess);
X! 	}
X! 	rfp->fp_suspended = NOT_SUSPENDED;
X! 	reply(proc_nr, EINTR);	/* signal interrupted call */
X!   }
X!   return(OK);
X! }
/
echo x - fs/read.c.cdiff
gres '^X' '' > fs/read.c.cdiff << '/'
X*** read.c	Thu Feb  7 20:07:23 1989
X--- ../read.c	Thu Mar  5 21:29:26 1989
X***************
X*** 15,20 ****
X--- 15,21 ----
X  #include "../h/type.h"
X  #include "../h/com.h"
X  #include "../h/error.h"
X+ #include "../h/fcntl.h"
X  #include "const.h"
X  #include "type.h"
X  #include "buf.h"
X***************
X*** 52,59 ****
X    register struct filp *f;
X    register file_pos bytes_left, f_size;
X    register unsigned off, cum_io;
X!   file_pos position;
X!   int r, chunk, virg, mode_word, usr, seg;
X    struct filp *wf;
X    extern struct super_block *get_super();
X    extern struct filp *find_filp(), *get_filp();
X--- 53,61 ----
X    register struct filp *f;
X    register file_pos bytes_left, f_size;
X    register unsigned off, cum_io;
X!   register int oflags;
X!   file_pos position;
X!   int r, chunk, virg, mode_word, usr, seg, regular;
X    struct filp *wf;
X    extern struct super_block *get_super();
X    extern struct filp *find_filp(), *get_filp();
X***************
X*** 77,105 ****
X  	return(EBADF);
X    position = f->filp_pos;
X    if (position < (file_pos) 0) return(EINVAL);
X    rip = f->filp_ino;
X    f_size = rip->i_size;
X    r = OK;
X    cum_io = 0;
X    virg = TRUE;
X    mode_word = rip->i_mode & I_TYPE;
X    if (mode_word == I_BLOCK_SPECIAL && f_size == 0) f_size = MAX_P_LONG;
X    rdwt_err = OK;		/* set to EIO if disk error occurs */
X  
X    /* Check for character special files. */
X    if (mode_word == I_CHAR_SPECIAL) {
X! 	if ((r = dev_io(rw_flag, (dev_nr) rip->i_zone[0], (long) position,
X! 						nbytes, who, buffer)) >= 0) {
X  		cum_io = r;
X  		position += r;
X  		r = OK;
X  	}
X    } else {
X  	if (rw_flag == WRITING && mode_word != I_BLOCK_SPECIAL) {
X  		/* Check in advance to see if file will grow too big. */
X  		if (position > get_super(rip->i_dev)->s_max_size - nbytes )
X  			return(EFBIG);
X  
X  		/* Clear the zone containing present EOF if hole about
X  		 * to be created.  This is necessary because all unwritten
X  		 * blocks prior to the EOF must read as zeros.
X--- 79,114 ----
X  	return(EBADF);
X    position = f->filp_pos;
X    if (position < (file_pos) 0) return(EINVAL);
X+   oflags = f->filp_flags;
X    rip = f->filp_ino;
X    f_size = rip->i_size;
X    r = OK;
X    cum_io = 0;
X    virg = TRUE;
X    mode_word = rip->i_mode & I_TYPE;
X+   regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
X+ 
X    if (mode_word == I_BLOCK_SPECIAL && f_size == 0) f_size = MAX_P_LONG;
X    rdwt_err = OK;		/* set to EIO if disk error occurs */
X  
X    /* Check for character special files. */
X    if (mode_word == I_CHAR_SPECIAL) {
X! 	if ((r = dev_io(rw_flag, oflags & O_NONBLOCK, (dev_nr) rip->i_zone[0], 
X! 			(long) position, nbytes, who, buffer)) >= 0) {
X  		cum_io = r;
X  		position += r;
X  		r = OK;
X  	}
X    } else {
X+ 
X  	if (rw_flag == WRITING && mode_word != I_BLOCK_SPECIAL) {
X  		/* Check in advance to see if file will grow too big. */
X  		if (position > get_super(rip->i_dev)->s_max_size - nbytes )
X  			return(EFBIG);
X  
X+ 		/* check for O_APPEND flag */
X+ 		if (oflags & O_APPEND) position = f_size;
X+ 
X  		/* Clear the zone containing present EOF if hole about
X  		 * to be created.  This is necessary because all unwritten
X  		 * blocks prior to the EOF must read as zeros.
X***************
X*** 108,114 ****
X  	}
X  
X  	/* Pipes are a little different.  Check. */
X! 	if (rip->i_pipe && (r = pipe_check(rip, rw_flag, virg,
X  				nbytes, &position)) <= 0) return(r);
X  
X  	/* Split the transfer into chunks that don't span two blocks. */
X--- 117,123 ----
X  	}
X  
X  	/* Pipes are a little different.  Check. */
X! 	if (rip->i_pipe && (r = pipe_check(rip, rw_flag, oflags, virg,
X  				nbytes, &position)) <= 0) return(r);
X  
X  	/* Split the transfer into chunks that don't span two blocks. */
X***************
X*** 140,147 ****
X  
X    /* On write, update file size and access time. */
X    if (rw_flag == WRITING) {
X! 	if (mode_word != I_CHAR_SPECIAL && mode_word != I_BLOCK_SPECIAL && 
X! 							position > f_size)
X  		rip->i_size = position;
X  	rip->i_modtime = clock_time();
X  	rip->i_dirt = DIRTY;
X--- 149,155 ----
X  
X    /* On write, update file size and access time. */
X    if (rw_flag == WRITING) {
X! 	if ((regular || mode_word == I_DIRECTORY) && position > f_size)
X  		rip->i_size = position;
X  	rip->i_modtime = clock_time();
X  	rip->i_dirt = DIRTY;
X***************
X*** 157,167 ****
X  
X    /* Check to see if read-ahead is called for, and if so, set it up. */
X    if (rw_flag == READING && rip->i_seek == NO_SEEK && position % BLOCK_SIZE == 0
X! 		&& (mode_word == I_REGULAR || mode_word == I_DIRECTORY)) {
X  	rdahed_inode = rip;
X  	rdahedpos = position;
X    }
X!   if (mode_word == I_REGULAR) rip->i_seek = NO_SEEK;
X  
X    if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */
X    if (rdwt_err == EOF) r = cum_io;
X--- 165,175 ----
X  
X    /* Check to see if read-ahead is called for, and if so, set it up. */
X    if (rw_flag == READING && rip->i_seek == NO_SEEK && position % BLOCK_SIZE == 0
X! 		&& (regular || mode_word == I_DIRECTORY)) {
X  	rdahed_inode = rip;
X  	rdahedpos = position;
X    }
X!   if (regular) rip->i_seek = NO_SEEK;
X  
X    if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */
X    if (rdwt_err == EOF) r = cum_io;
/
echo x - fs/table.c.cdiff
gres '^X' '' > fs/table.c.cdiff << '/'
X*** table.c	Thu Feb 11 02:01:02 1989
X--- ../table.c	Thu Feb 11 02:01:10 1989
X***************
X*** 27,33 ****
X  extern do_ioctl(), do_link(), do_lseek(), do_mknod(), do_mount(), do_open();
X  extern do_pipe(), do_read(), do_revive(), do_set(), do_stat(), do_stime();
X  extern do_sync(), do_time(), do_tims(), do_umask(), do_umount(), do_unlink();
X! extern do_unpause(), do_utime(), do_write(), no_call(), no_sys();
X  
X  extern char fstack[];
X  char *stackpt = &fstack[FS_STACK_BYTES];	/* initial stack pointer */
X--- 27,33 ----
X  extern do_ioctl(), do_link(), do_lseek(), do_mknod(), do_mount(), do_open();
X  extern do_pipe(), do_read(), do_revive(), do_set(), do_stat(), do_stime();
X  extern do_sync(), do_time(), do_tims(), do_umask(), do_umount(), do_unlink();
X! extern do_unpause(), do_utime(), do_write(), do_fcntl(), no_call(), no_sys();
X  
X  extern char fstack[];
X  char *stackpt = &fstack[FS_STACK_BYTES];	/* initial stack pointer */
X***************
X*** 88,94 ****
X  	no_sys,		/* 52 = (phys)	*/
X  	no_sys,		/* 53 = (lock)	*/
X  	do_ioctl,	/* 54 = ioctl	*/
X! 	no_sys,		/* 55 = unused	*/
X  	no_sys,		/* 56 = (mpx)	*/
X  	no_sys,		/* 57 = unused	*/
X  	no_sys,		/* 58 = unused	*/
X--- 88,94 ----
X  	no_sys,		/* 52 = (phys)	*/
X  	no_sys,		/* 53 = (lock)	*/
X  	do_ioctl,	/* 54 = ioctl	*/
X! 	do_fcntl,	/* 55 = fcntl	*/
X  	no_sys,		/* 56 = (mpx)	*/
X  	no_sys,		/* 57 = unused	*/
X  	no_sys,		/* 58 = unused	*/
/
-- 
----------------------------------------------------------------------------
UUCP:   ...mcvax!cernvax!forty2!poole			Simon Poole
BITNET: K538915@CZHRZU1A
----------------------------------------------------------------------------