Example #1
0
/*===========================================================================*
 *				fs_sync					     *
 *===========================================================================*/
PUBLIC int fs_sync()
{
/* Perform the sync() system call.  Flush all the tables.
 * The order in which the various tables are flushed is critical.  The
 * blocks must be flushed last, since rw_inode() leaves its results in
 * the block cache.
 */
  struct inode *rip;
  struct buf *bp;
  int r;

  assert(nr_bufs > 0);
  assert(buf);

  if (superblock->s_rd_only)
	return(OK); /* nothing to sync */

  /* Write all the dirty inodes to the disk. */
  for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
	if(rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING);

  /* Write all the dirty blocks to the disk, one drive at a time. */
  for(bp = &buf[0]; bp < &buf[nr_bufs]; bp++)
	if(bp->b_dev != NO_DEV && bp->b_dirt == DIRTY)
		flushall(bp->b_dev);

  if (superblock->s_dev != NO_DEV) {
	superblock->s_wtime = clock_time();
	write_super(superblock);
  }

  return(OK);		/* sync() can't fail */
}
Example #2
0
/*===========================================================================*
 *				fs_newnode				     *
 *===========================================================================*/
int fs_newnode()
{
    register int r;
    mode_t bits;
    struct minix_inode *rip;

    caller_uid = fs_m_in.REQ_UID;
    caller_gid = fs_m_in.REQ_GID;
    bits = fs_m_in.REQ_MODE;

    /* Try to allocate the inode */
    if( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE)
        return err_code;

    switch (bits & S_IFMT) {
    case S_IFBLK:
    case S_IFCHR:
        rip->i_zone[0] = fs_m_in.REQ_DEV; /* major/minor dev numbers*/
        break;
    }

    rw_inode(rip, WRITING);	/* mark inode as allocated */
    rip->i_update = ATIME | CTIME | MTIME;

    /* Fill in the fields of the response message */
    fs_m_out.RES_INODE_NR = rip->i_num;
    fs_m_out.RES_MODE = rip->i_mode;
    fs_m_out.RES_FILE_SIZE_LO = rip->i_size;
    fs_m_out.RES_UID = rip->i_uid;
    fs_m_out.RES_GID = rip->i_gid;
    fs_m_out.RES_DEV = (dev_t) rip->i_zone[0];

    return(0);
}
Example #3
0
/*===========================================================================*
 *				do_pipe					     *
 *===========================================================================*/
PUBLIC int do_pipe()
{
/* Perform the pipe(fil_des) system call. */

  register struct fproc *rfp;
  register struct inode *rip;
  int r;
  struct filp *fil_ptr0, *fil_ptr1;
  int fil_des[2];		/* reply goes here */

  /* Acquire two file descriptors. */
  rfp = fp;
  if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
  rfp->fp_filp[fil_des[0]] = fil_ptr0;
  fil_ptr0->filp_count = 1;
  if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
	rfp->fp_filp[fil_des[0]] = NIL_FILP;
	fil_ptr0->filp_count = 0;
	return(r);
  }
  rfp->fp_filp[fil_des[1]] = fil_ptr1;
  fil_ptr1->filp_count = 1;

  /* Make the inode on the pipe device. */
  if ( (rip = alloc_inode(root_dev, I_REGULAR) ) == NIL_INODE) {
	rfp->fp_filp[fil_des[0]] = NIL_FILP;
	fil_ptr0->filp_count = 0;
	rfp->fp_filp[fil_des[1]] = NIL_FILP;
	fil_ptr1->filp_count = 0;
	return(err_code);
  }

  if (read_only(rip) != OK) 
  	panic(__FILE__,"pipe device is read only", NO_NUM);
 
  rip->i_pipe = I_PIPE;
  rip->i_mode &= ~I_REGULAR;
  rip->i_mode |= I_NAMED_PIPE;	/* pipes and FIFOs have this bit set */
  fil_ptr0->filp_ino = rip;
  fil_ptr0->filp_flags = O_RDONLY;
  dup_inode(rip);		/* for double usage */
  fil_ptr1->filp_ino = rip;
  fil_ptr1->filp_flags = O_WRONLY;
  rw_inode(rip, WRITING);	/* mark inode as allocated */
  m_out.reply_i1 = fil_des[0];
  m_out.reply_i2 = fil_des[1];
  rip->i_update = ATIME | CTIME | MTIME;
  return(OK);
}
Example #4
0
/*===========================================================================*
 *				fs_sync					     *
 *===========================================================================*/
int fs_sync()
{
/* Perform the sync() system call.  Flush all the tables.
 * The order in which the various tables are flushed is critical.  The
 * blocks must be flushed last, since rw_inode() leaves its results in
 * the block cache.
 */
  struct inode *rip;

  assert(lmfs_nr_bufs() > 0);

  /* Write all the dirty inodes to the disk. */
  for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
	  if(rip->i_count > 0 && IN_ISDIRTY(rip)) rw_inode(rip, WRITING);

  /* Write all the dirty blocks to the disk. */
  lmfs_flushall();

  return(OK);		/* sync() can't fail */
}
Example #5
0
/*===========================================================================*
 *				fs_sync					     *
 *===========================================================================*/
PUBLIC int fs_sync()
{
/* Perform the sync() system call.  Flush all the tables. 
 * The order in which the various tables are flushed is critical.  The
 * blocks must be flushed last, since rw_inode() leaves its results in
 * the block cache.
 */
  register struct inode *rip;
  register struct buf *bp;

  /* Write all the dirty inodes to the disk. */
  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
	if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING);

  /* Write all the dirty blocks to the disk, one drive at a time. */
  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
	if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) 
            flushall(bp->b_dev);

  return(OK);		/* sync() can't fail */
}
Example #6
0
int fs_bitmapfixer()
{
  /*
  m9_l1 dev
  m9_l3 fixertype
  */
  if(fs_m_in.m9_l3 == 0)  //fix inode bitmapblock
  {
    printf("enter mfs inode bitmap fixer!\n");
    // int errorcount = 0;
    struct super_block* sp = get_super(fs_m_in.m9_l1);
    //read inodebitmap blocks
    int i;
    for(i = 0;i < sp->s_imap_blocks;i++)
    {
      struct buf* bitmapblock = get_block(sp->s_dev, 2+i, NORMAL);
      bitchunk_t* mapchunks = (bitchunk_t*)bitmapblock->data;
      int k = 0;
      if(i == 0)
      {
        k = 1;
      }
      for(;k < 32768;k++)
      {
        if(i*32768 + k > sp->s_ninodes)
        {
          break;
        }
        if((mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) != 0)  //used inode
        {
          struct inode inodetmp;
          inodetmp.i_dev = sp->s_dev;
          inodetmp.i_num = i*32768 + k;
          rw_inode(&inodetmp,READING);
          if(inodetmp.i_nlinks == 0)
          {
            mapchunks[k / (sizeof(bitchunk_t) * 8)] &= ~((bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8)));
            printf("Inode %d fixed!\n",i*32768 + k);
          }
        }
        else
        {
          struct inode inodetmp;
          inodetmp.i_dev = sp->s_dev;
          inodetmp.i_num = i*32768 + k;
          rw_inode(&inodetmp,READING);
          if(inodetmp.i_nlinks != 0)
          {
            mapchunks[k / (sizeof(bitchunk_t) * 8)] |= ((bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8)));
            printf("Inode %d fixed!\n",i*32768 + k);
          }
        }
        // struct inode inodetmp;
        // inodetmp.i_dev = sp->s_dev;
        // inodetmp.i_num = i*32768 + k;
        // rw_inode(&inodetmp,READING);
        //
        // if(
        //   (inodetmp.i_nlinks !=0 && (mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) == 0) ||
        //   (inodetmp.i_nlinks ==0 && (mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) != 0)
        // )
        // {
        //   errorcount ++;
        // }
      }
      put_block(bitmapblock,0);
    }
    printf("inode bitmap fixer return\n");
    // printf("error_count:%d\n",errorcount);
    return 0;
  }
  else if(fs_m_in.m9_l3 == 1) //fix zone bitmap
  {
    printf("enter mfs zone bitmap fixer!\n");
    struct super_block* sp = get_super(fs_m_in.m9_l1);
    //first erase all zone bit map
    int logicalzonebitmapblockindex;
    for(logicalzonebitmapblockindex = 0;logicalzonebitmapblockindex < sp->s_zmap_blocks;logicalzonebitmapblockindex++)
    {
      struct buf* tmpbitmapblock = get_block(sp->s_dev,logicalzonebitmapblockindex + 2 + sp->s_imap_blocks,NORMAL);
      bitchunk_t* tmpchunktable = (bitchunk_t*)tmpbitmapblock->data;
      int chunkindex;
      for(chunkindex = 0;chunkindex < (sp->s_block_size / sizeof(bitchunk_t));chunkindex++)
      {
        if(logicalzonebitmapblockindex == 0 && chunkindex == 0)
        {
          tmpchunktable[chunkindex] &= (bitchunk_t) 1;
        }
        else
        {
          tmpchunktable[chunkindex] &= (bitchunk_t) 0;
        }
      }
      put_block(tmpbitmapblock,0);
    }
    //check all inode and fix zonebitmap
    // int i;
    // for(i = 0;i < sp->s_imap_blocks;i++)
    // {
    //   struct buf* bitmapblock = get_block(sp->s_dev, 2+i, NORMAL);
    //   bitchunk_t* mapchunks = (bitchunk_t*)bitmapblock->data;
    //   int k = 0;
    //   if(i == 0)
    //   {
    //     k = 1;
    //   }
    //   for(;k < 32768;k++)
    //   {
    //     if(i*32768 + k > sp->s_ninodes)
    //     {
    //       break;
    //     }
    //     if((mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) != 0)  //used inode
    //     {
    //       struct inode* inodetmp = NULL;
    //       inodetmp = get_inode(sp->s_dev,i * 32768 + k);
    //       int inodezoneindex;
    //       printf("fix inode%d zones\n",i*32768 + k);
    //       for(inodezoneindex = 0;inodezoneindex < V2_NR_TZONES;inodezoneindex++);
    //       {
    //         if(inodetmp->i_zone[inodezoneindex] != 0)
    //         {
    //           unsigned int bitsperblock = sp->s_block_size * 8;
    //           unsigned int bitsperchunk = sizeof(bitchunk_t) * 8;
    //           unsigned int logicalzoneindex = inodetmp->i_zone[inodezoneindex] - sp->s_firstdatazone;
    //           unsigned int physicalblockindex = (logicalzoneindex / bitsperblock) + 2 + sp->s_imap_blocks;
    //           unsigned int chunkindex = (logicalzoneindex % bitsperblock) / bitsperchunk;
    //           unsigned int bitindex = logicalzoneindex % bitsperchunk;
    //           struct buf* tmpzonebitmapblock = get_block(sp->s_dev,physicalblockindex,NORMAL);
    //           bitchunk_t* tmpchunktable = (bitchunk_t*)tmpzonebitmapblock->data;
    //           tmpchunktable[chunkindex] |= ((bitchunk_t)1 << bitindex);
    //           printf("%u  %u  %u  %u  %u  %u\n",bitsperblock,bitsperchunk,logicalzoneindex,physicalblockindex,chunkindex,bitindex);
    //           put_block(tmpzonebitmapblock,0);
    //         }
    //       }
    //       put_inode(inodetmp);
    //     }
    //   }
    //   put_block(bitmapblock,0);
    // }

    int i;
    for(i = 1;i <= sp->s_ninodes;i++)
    {
      struct inode inodetmp;
      inodetmp.i_dev = sp->s_dev;
      inodetmp.i_num = i;
      rw_inode(&inodetmp,READING);
      if(inodetmp.i_nlinks != 0)
      {
        printf("inode%d used\t",inodetmp.i_num);
        int k;
        for(k = 0;k < V2_NR_TZONES;k++)
        {
          if(inodetmp.i_zone[k] != 0)
          {
            printf("fix zone %u\t",inodetmp.i_zone[k]);
            unsigned int bitsperblock = sp->s_block_size * 8;
            unsigned int bitsperchunk = sizeof(bitchunk_t) * 8;
            unsigned int logicalzoneindex = inodetmp.i_zone[k] - sp->s_firstdatazone + 1;
            unsigned int physicalblockindex = (logicalzoneindex / bitsperblock) + 2 + sp->s_imap_blocks;
            unsigned int chunkindex = (logicalzoneindex % bitsperblock) / bitsperchunk;
            unsigned int bitindex = logicalzoneindex % bitsperchunk;
            struct buf* tmpzonebitmapblock = get_block(sp->s_dev,physicalblockindex,NORMAL);
            bitchunk_t* tmpchunktable = (bitchunk_t*)tmpzonebitmapblock->data;
            tmpchunktable[chunkindex] |= ((bitchunk_t)1 << bitindex);
            put_block(tmpzonebitmapblock,0);
          }
        }
        printf("\n");
      }
    }
    printf("zone bitmap fixer return\n");
    return 0;
  }
  else
  {
    return 0;
  }
}
Example #7
0
/*===========================================================================*
 *				new_node				     *
 *===========================================================================*/
PRIVATE struct inode *new_node(struct inode *ldirp,
	char *string, mode_t bits, zone_t z0)
{
/* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().  
 * In all cases it allocates a new inode, makes a directory entry for it in
 * the ldirp directory with string name, and initializes it.  
 * It returns a pointer to the inode if it can do this; 
 * otherwise it returns NULL.  It always sets 'err_code'
 * to an appropriate value (OK or an error code).
 * 
 * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
 * has to hold at least NAME_MAX bytes.
 */

  register struct inode *rip;
  register int r;

  if (ldirp->i_nlinks == NO_LINK) {	/* Dir does not actually exist */
  	err_code = ENOENT;
  	return(NULL);
  }

  /* Get final component of the path. */
  rip = advance(ldirp, string, IGN_PERM);

  if (S_ISDIR(bits) && (ldirp->i_nlinks >= LINK_MAX)) {
        /* New entry is a directory, alas we can't give it a ".." */
        put_inode(rip);
        err_code = EMLINK;
        return(NULL);
  }
  /* if creating a regular file, set it to be an immediate */
  else if((bits & I_TYPE) == I_REGULAR) bits |= I_IMMEDIATE;
  /* printf("new_node() - mode bits: 0%6o\n", bits); */

  if ( rip == NULL && err_code == ENOENT) {
	/* Last path component does not exist.  Make new directory entry. */
	if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NULL) {
		/* Can't creat new inode: out of inodes. */
		return(NULL);
	}

	/* Force inode to the disk before making directory entry to make
	 * the system more robust in the face of a crash: an inode with
	 * no directory entry is much better than the opposite.
	 */
	rip->i_nlinks++;
	rip->i_zone[0] = z0;		/* major/minor device numbers */
	rw_inode(rip, WRITING);		/* force inode to disk now */

	/* New inode acquired.  Try to make directory entry. */
	if((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM)) != OK) {
		rip->i_nlinks--;	/* pity, have to free disk inode */
		rip->i_dirt = DIRTY;	/* dirty inodes are written out */
		put_inode(rip);	/* this call frees the inode */
		err_code = r;
		return(NULL);
	}

  } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) {
  	r = EEXIST;
  } else { 
	/* Either last component exists, or there is some problem. */
	if (rip != NULL)
		r = EEXIST;
	else
		r = err_code;
  }

  /* The caller has to return the directory inode (*ldirp).  */
  err_code = r;
  return(rip);
}
Example #8
0
/*===========================================================================*
 *				new_node				     *
 *===========================================================================*/
static struct minix_inode *new_node(struct minix_inode *ldirp,
                                    char *string, mode_t bits, zone_t z0)
{
    /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
     * In all cases it allocates a new inode, makes a directory entry for it in
     * the ldirp directory with string name, and initializes it.
     * It returns a pointer to the inode if it can do this;
     * otherwise it returns NIL_INODE.  It always sets 'err_code'
     * to an appropriate value (0 or an error code).
     *
     * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
     * has to hold at least MINIXFS_NAME_MAX bytes.
     */

    register struct minix_inode *rip;
    register int r;

    /* Get final component of the path. */
    rip = advance(ldirp, string, IGN_PERM);

    if (S_ISDIR(bits) &&
            (ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == 1 ?
                                  CHAR_MAX : LINK_MAX)) {
        /* New entry is a directory, alas we can't give it a ".." */
        put_inode(rip);
        err_code = -EMLINK;
        return(NIL_INODE);
    }

    if ( rip == NIL_INODE && err_code == -ENOENT) {
        /* Last path component does not exist.  Make new directory entry. */
        if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NIL_INODE) {
            /* Can't creat new inode: out of inodes. */
            return(NIL_INODE);
        }

        /* Force inode to the disk before making directory entry to make
         * the system more robust in the face of a crash: an inode with
         * no directory entry is much better than the opposite.
         */
        rip->i_nlinks++;
        rip->i_zone[0] = z0;		/* major/minor device numbers */
        rw_inode(rip, WRITING);		/* force inode to disk now */

        /* New inode acquired.  Try to make directory entry. */
        if((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM)) != 0) {
            rip->i_nlinks--;	/* pity, have to free disk inode */
            rip->i_dirt = DIRTY;	/* dirty inodes are written out */
            put_inode(rip);	/* this call frees the inode */
            err_code = r;
            return(NIL_INODE);
        }

    } else if (err_code == -EENTERMOUNT || err_code == -ELEAVEMOUNT) {
        r = -EEXIST;
    } else {
        /* Either last component exists, or there is some problem. */
        if (rip != NIL_INODE)
            r = -EEXIST;
        else
            r = err_code;
    }

    /* The caller has to return the directory inode (*ldirp).  */
    err_code = r;
    return(rip);
}
Example #9
0
/*===========================================================================*
 *				new_node				     *
 *===========================================================================*/
static struct inode *new_node(struct inode *ldirp,
	char *string, mode_t bits, block_t b0)
{
/* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
 * In all cases it allocates a new inode, makes a directory entry for it in
 * the ldirp directory with string name, and initializes it.
 * It returns a pointer to the inode if it can do this;
 * otherwise it returns NULL.  It always sets 'err_code'
 * to an appropriate value (OK or an error code).
 */

  register struct inode *rip;
  register int r;

  if (ldirp->i_links_count == NO_LINK) { /* Dir does not actually exist */
	err_code = ENOENT;
	return(NULL);
  }

  /* Get final component of the path. */
  rip = advance(ldirp, string, IGN_PERM);

  if (S_ISDIR(bits) && (ldirp->i_links_count >= USHRT_MAX ||
			ldirp->i_links_count >= LINK_MAX)) {
        /* New entry is a directory, alas we can't give it a ".." */
        put_inode(rip);
        err_code = EMLINK;
        return(NULL);
  }

  if ( rip == NULL && err_code == ENOENT) {
	/* Last path component does not exist.  Make new directory entry. */
	if ( (rip = alloc_inode(ldirp, bits)) == NULL) {
		/* Can't creat new inode: out of inodes. */
		return(NULL);
	}

	/* Force inode to the disk before making directory entry to make
	 * the system more robust in the face of a crash: an inode with
	 * no directory entry is much better than the opposite.
	 */
	rip->i_links_count++;
	rip->i_block[0] = b0;		/* major/minor device numbers */
	rw_inode(rip, WRITING);		/* force inode to disk now */

	/* New inode acquired.  Try to make directory entry. */
	if ((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM,
			  rip->i_mode & I_TYPE)) != OK) {
		rip->i_links_count--;	/* pity, have to free disk inode */
		rip->i_dirt = IN_DIRTY;	/* dirty inodes are written out */
		put_inode(rip);	/* this call frees the inode */
		err_code = r;
		return(NULL);
	}

  } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) {
	r = EEXIST;
  } else {
	/* Either last component exists, or there is some problem. */
	if (rip != NULL)
		r = EEXIST;
	else
		r = err_code;
  }

  /* The caller has to return the directory inode (*ldirp).  */
  err_code = r;
  return(rip);
}
Example #10
0
/*===========================================================================*
 *				common_open				     *
 *===========================================================================*/
PRIVATE int common_open(register int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */

  struct inode *rip, *ldirp;
  int r, b, exist = TRUE;
  dev_t dev;
  mode_t bits;
  off_t pos;
  struct filp *fil_ptr, *filp2;

  /* Remap the bottom two bits of oflags. */
  bits = (mode_t) mode_map[oflags & O_ACCMODE];

  /* See if file descriptor and filp slots are available. */
  if ( (r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);

  /* If O_CREATE is set, try to make the file. */ 
  if (oflags & O_CREAT) {
  	/* Create a new inode by calling new_node(). */
        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
    	rip = new_node(&ldirp, user_path, omode, NO_ZONE, oflags&O_EXCL, NULL);
    	r = err_code;
        put_inode(ldirp);
    	if (r == OK) exist = FALSE;      /* we just created the file */
	else if (r != EEXIST) return(r); /* other error */
	else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
					    flag is set this is an error */
  } else {
	 /* Scan path name. */
    	if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  }

  /* 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);
  fil_ptr->filp_count = 1;
  fil_ptr->filp_ino = rip;
  fil_ptr->filp_flags = oflags;

  /* Only do the normal open code if we didn't just create the file. */
  if (exist) {
  	/* Check protections. */
  	if ((r = forbidden(rip, bits)) == OK) {
  		/* Opening reg. files directories and special files differ. */
	  	switch (rip->i_mode & I_TYPE) {
    		   case I_REGULAR: 
			/* Truncate regular file if O_TRUNC. */
			if (oflags & O_TRUNC) {
				if ((r = forbidden(rip, W_BIT)) !=OK) break;
				truncate_inode(rip, 0);
				wipe_inode(rip);
				/* Send the inode from the inode cache to the
				 * block cache, so it gets written on the next
				 * cache flush.
				 */
				rw_inode(rip, WRITING);
			}
			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:
			/* Invoke the driver for special processing. */
			dev = (dev_t) rip->i_zone[0];
			r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
			break;

		   case I_NAMED_PIPE:
			oflags |= O_APPEND;	/* force append mode */
			fil_ptr->filp_flags = oflags;
			r = pipe_open(rip, bits, oflags);
			if (r != ENXIO) {
				/* See if someone else is doing a rd or wt on
				 * the FIFO.  If so, use its filp entry so the
				 * file position will be automatically shared.
				 */
				b = (bits & R_BIT ? R_BIT : W_BIT);
				fil_ptr->filp_count = 0; /* don't find self */
				if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
					/* Co-reader or writer found. Use it.*/
					fp->fp_filp[m_in.fd] = filp2;
					filp2->filp_count++;
					filp2->filp_ino = rip;
					filp2->filp_flags = oflags;

					/* i_count was incremented incorrectly
					 * by eatpath above, not knowing that
					 * we were going to use an existing
					 * filp entry.  Correct this error.
					 */
					rip->i_count--;
				} else {
					/* Nobody else found.  Restore filp. */
					fil_ptr->filp_count = 1;
					if (b == R_BIT)
					     pos = rip->i_zone[V2_NR_DZONES+0];
					else
					     pos = rip->i_zone[V2_NR_DZONES+1];
					fil_ptr->filp_pos = pos;
				}
			}
			break;
 		}
  	}
  }

  /* If error, release inode. */
  if (r != OK) {
	if (r == SUSPEND) return(r);		/* Oops, just suspended */
	fp->fp_filp[m_in.fd] = NIL_FILP;
  	FD_CLR(m_in.fd, &fp->fp_filp_inuse);
	fil_ptr->filp_count= 0;
	put_inode(rip);
	return(r);
  }
  
  return(m_in.fd);
}
Example #11
0
/*===========================================================================*
 *				new_node				     *
 *===========================================================================*/
PRIVATE struct inode *new_node(struct inode **ldirp,
	char *path, mode_t bits, zone_t z0, int opaque, char *parsed)
{
/* New_node() is called by common_open(), do_mknod(), and do_mkdir().  
 * In all cases it allocates a new inode, makes a directory entry for it on 
 * the path 'path', and initializes it.  It returns a pointer to the inode if 
 * it can do this; otherwise it returns NIL_INODE.  It always sets 'err_code'
 * to an appropriate value (OK or an error code).
 * 
 * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
 * has to hold at least NAME_MAX bytes.
 */

  register struct inode *rip;
  register int r;
  char string[NAME_MAX];

  *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM);       
  if (*ldirp == NIL_INODE) return(NIL_INODE);

  /* The final directory is accessible. Get final component of the path. */
  rip = advance(ldirp, string);

  if (S_ISDIR(bits) && 
      (*ldirp)->i_nlinks >= ((*ldirp)->i_sp->s_version == V1 ?
      CHAR_MAX : SHRT_MAX)) {
        /* New entry is a directory, alas we can't give it a ".." */
        put_inode(rip);
        err_code = EMLINK;
        return(NIL_INODE);
  }

  if ( rip == NIL_INODE && err_code == ENOENT) {
	/* Last path component does not exist.  Make new directory entry. */
	if ( (rip = alloc_inode((*ldirp)->i_dev, bits)) == NIL_INODE) {
		/* Can't creat new inode: out of inodes. */
		return(NIL_INODE);
	}

	/* Force inode to the disk before making directory entry to make
	 * the system more robust in the face of a crash: an inode with
	 * no directory entry is much better than the opposite.
	 */
	rip->i_nlinks++;
	rip->i_zone[0] = z0;		/* major/minor device numbers */
	rw_inode(rip, WRITING);		/* force inode to disk now */

	/* New inode acquired.  Try to make directory entry. */
	if ((r = search_dir(*ldirp, string, &rip->i_num,ENTER)) != OK) {
		rip->i_nlinks--;	/* pity, have to free disk inode */
		rip->i_dirt = DIRTY;	/* dirty inodes are written out */
		put_inode(rip);	/* this call frees the inode */
		err_code = r;
		return(NIL_INODE);
	}

  } else {
	/* Either last component exists, or there is some problem. */
	if (rip != NIL_INODE)
		r = EEXIST;
	else
		r = err_code;
  }

  if(parsed) { /* Give the caller the parsed string if requested. */
	strncpy(parsed, string, NAME_MAX-1);
	parsed[NAME_MAX-1] = '\0';
  }

  /* The caller has to return the directory inode (*ldirp).  */
  err_code = r;
  return(rip);
}