Example #1
0
/*================================================================
 *	    eat_dir  -  recursively install directory
 *===============================================================*/
void
eat_dir(ino_t parent)
{
  /* Read prototype lines and set up directory. Recurse if need be. */
  char *token[MAX_TOKENS], *p;
  char line[LINE_LEN];
  int mode, usrid, grpid, maj, min, f;
  ino_t n;
  zone_t z;
  size_t size;

  while (1) {
	get_line(line, token);
	p = token[0];
	if (*p == '$') return;
	p = token[1];
	mode = mode_con(p);
	usrid = atoi(token[2]);
	grpid = atoi(token[3]);
	n = alloc_inode(mode, usrid, grpid);

	/* Enter name in directory and update directory's size. */
	enter_dir(parent, token[0], n);
	incr_size(parent, sizeof(struct direct));

	/* Check to see if file is directory or special. */
	incr_link(n);
	if (*p == 'd') {
		/* This is a directory. */
		z = alloc_zone();	/* zone for new directory */
		add_zone(n, z, 2 * sizeof(struct direct), current_time);
		enter_dir(n, ".", n);
		enter_dir(n, "..", parent);
		incr_link(parent);
		incr_link(n);
		eat_dir(n);
	} else if (*p == 'b' || *p == 'c') {
		/* Special file. */
		maj = atoi(token[4]);
		min = atoi(token[5]);
		size = 0;
		if (token[6]) size = atoi(token[6]);
		size = block_size * size;
		add_zone(n, (zone_t) (makedev(maj,min)), size, current_time);
	} else if (*p == 's') {
		enter_symlink(n, token[4]);
	} else {
		/* Regular file. Go read it. */
		if ((f = open(token[4], O_RDONLY)) < 0) {
			fprintf(stderr, "%s: Can't open %s: %s\n",
				progname, token[4], strerror(errno));
		} else {
			eat_file(n, f);
		}
	}
  }

}
Example #2
0
/*================================================================
 *              rootdir  -  install the root directory
 *===============================================================*/
void
rootdir(ino_t inode)
{
  zone_t z;

  z = alloc_zone();
  add_zone(inode, z, 2 * sizeof(struct direct), current_time);
  enter_dir(inode, ".", inode);
  enter_dir(inode, "..", inode);
  incr_link(inode);
  incr_link(inode);
}
Example #3
0
void
enter_symlink(ino_t inode, char *lnk)
{
  zone_t z;
  size_t len;
  char *buf;

  buf = alloc_block();
  z = alloc_zone();
  len = strlen(lnk);
  if (len >= block_size)
	pexit("symlink too long, max length is %u", (unsigned)block_size - 1);
  strcpy(buf, lnk);
  put_block((z << zone_shift), buf);

  add_zone(inode, z, len, current_time);

  free(buf);
}
Example #4
0
/* Zonesize >= blocksize */
void
eat_file(ino_t inode, int f)
{
  int ct = 0, i, j;
  zone_t z = 0;
  char *buf;
  time_t timeval;

  buf = alloc_block();

  do {
	for (i = 0, j = 0; i < zone_per_block; i++, j += ct) {
		memset(buf, 0, block_size);
		if ((ct = read(f, buf, block_size)) > 0) {
			if (i == 0) z = alloc_zone();
			put_block((z << zone_shift) + i, buf);
		}
	}
	timeval = (dflag ? current_time : file_time(f));
	if (ct) add_zone(inode, z, (size_t) j, timeval);
  } while (ct == block_size);
  close(f);
  free(buf);
}
Example #5
0
void
add_zone(ino_t n, zone_t z, size_t bytes, time_t mtime)
{
  /* Add zone z to inode n. The file has grown by 'bytes' bytes. */

  int off, i, j;
  block_t b;
  zone_t indir, dindir;
  struct inode *p, *inode;
  zone_t *blk, *dblk;

  assert(inodes_per_block*sizeof(*inode) == block_size);
  if(!(inode = alloc_block()))
  	err(1, "Couldn't allocate block of inodes");

  b = ((n - 1) / inodes_per_block) + inode_offset;
  off = (n - 1) % inodes_per_block;
  get_block(b, inode);
  p = &inode[off];
  p->i_size += bytes;
  p->i_mtime = mtime;
#ifndef MFS_INODE_ONLY_MTIME /* V1 file systems did not have them... */
  p->i_atime = p->i_ctime = current_time;
#endif
  for (i = 0; i < NR_DZONES; i++)
	if (p->i_zone[i] == 0) {
		p->i_zone[i] = z;
		put_block(b, inode);
  		free(inode);
		return;
	}

  assert(indir_per_block*sizeof(*blk) == block_size);
  if(!(blk = alloc_block()))
  	err(1, "Couldn't allocate indirect block");

  /* File has grown beyond a small file. */
  if (p->i_zone[S_INDIRECT_IDX] == 0)
	p->i_zone[S_INDIRECT_IDX] = alloc_zone();
  indir = p->i_zone[S_INDIRECT_IDX] << zone_shift;
  put_block(b, inode);
  --indir; /* Compensate for ++indir below */
  for (i = 0; i < (indir_per_zone); i++) {
	if (i % indir_per_block == 0)
		get_block(++indir, blk);
	if (blk[i % indir_per_block] == 0) {
		blk[i] = z;
		put_block(indir, blk);
  		free(blk);
  		free(inode);
		return;
	}
  }

  /* File has grown beyond single indirect; we need a double indirect */
  assert(indir_per_block*sizeof(*dblk) == block_size);
  if(!(dblk = alloc_block()))
  	err(1, "Couldn't allocate double indirect block");

  if (p->i_zone[D_INDIRECT_IDX] == 0)
	p->i_zone[D_INDIRECT_IDX] = alloc_zone();
  dindir = p->i_zone[D_INDIRECT_IDX] << zone_shift;
  put_block(b, inode);
  --dindir; /* Compensate for ++indir below */
  for (j = 0; j < (indir_per_zone); j++) {
	if (j % indir_per_block == 0)
		get_block(++dindir, dblk);
	if (dblk[j % indir_per_block] == 0)
		dblk[j % indir_per_block] = alloc_zone();
	indir = dblk[j % indir_per_block] << zone_shift;
	--indir; /* Compensate for ++indir below */
	for (i = 0; i < (indir_per_zone); i++) {
		if (i % indir_per_block == 0)
			get_block(++indir, blk);
		if (blk[i % indir_per_block] == 0) {
			blk[i] = z;
			put_block(dindir, dblk);
			put_block(indir, blk);
	  		free(dblk);
	  		free(blk);
	  		free(inode);
			return;
		}
	}
  }

  pexit("File has grown beyond double indirect");
}
Example #6
0
/*================================================================
 *	    directory & inode management assist group
 *===============================================================*/
void
enter_dir(ino_t parent, char const *name, ino_t child)
{
  /* Enter child in parent directory */
  /* Works for dir > 1 block and zone > block */
  unsigned int k;
  block_t b, indir;
  zone_t z;
  int off;
  struct inode *ino;
  struct inode *inoblock = alloc_block();
  zone_t *indirblock = alloc_block();

  assert(!(block_size % sizeof(struct direct)));

  /* Obtain the inode structure */
  b = ((parent - 1) / inodes_per_block) + inode_offset;
  off = (parent - 1) % inodes_per_block;
  get_block(b, inoblock);
  ino = inoblock + off;

  for (k = 0; k < NR_DZONES; k++) {
	z = ino->i_zone[k];
	if (z == 0) {
		z = alloc_zone();
		ino->i_zone[k] = z;
	}

	if(dir_try_enter(z, child, __UNCONST(name))) {
		put_block(b, inoblock);
		free(inoblock);
		free(indirblock);
		return;
	}
  }

  /* no space in directory using just direct blocks; try indirect */
  if (ino->i_zone[S_INDIRECT_IDX] == 0)
  	ino->i_zone[S_INDIRECT_IDX] = alloc_zone();

  indir = ino->i_zone[S_INDIRECT_IDX] << zone_shift;
  --indir; /* Compensate for ++indir below */
  for(k = 0; k < (indir_per_zone); k++) {
	if (k % indir_per_block == 0)
		get_block(++indir, indirblock);
  	z = indirblock[k % indir_per_block];
	if(!z) {
		z = indirblock[k % indir_per_block] = alloc_zone();
		put_block(indir, indirblock);
	}
	if(dir_try_enter(z, child, __UNCONST(name))) {
		put_block(b, inoblock);
		free(inoblock);
		free(indirblock);
		return;
	}
  }

  pexit("Directory-inode %u beyond single indirect blocks.  Could not enter %s",
         (unsigned)parent, name);
}
Example #7
0
/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  rdwt_zones
 *  Description:  read of write the buf to the zones
 *  @param pos:	  the current position in the file
 *  @param buf_len:		the length of the buf
 *  @param src:			the source of the buf
 *  @param buf:			the buf should be read or written
 *  @param i_nr_sects:	the current amount of the sects of the file
 *  @param i_zone:		the i_zone of this inode
 *  @param mode:		READ or WRITE
 *  @return :			how many bytes writed or read
 * =====================================================================================
 */
PRIVATE int
rdwt_zones ( int pos, int len, int src, char * buf, struct inode * pin, int mode)
{
	//check if the mode is right
	assert(WRITE == mode || READ == mode);

	int i;
	int align = 0;
	int pos_end = pos + len;

	//larger than file in read mode
	if (READ == mode) {
		if (pos > pin->i_size) {
			//read start is larger than the file, get nothing
			return 0;
		} else if (pos_end > pin->i_size) {
			//read end is larger than the file, just end at the EOF
			len -= (pos_end - pin->i_size);
			pos_end = pin->i_size;
		}
	}

	//how many sects does the buf need to take
	int nr_sect_start = pos >> SECTOR_SIZE_SHIFT;
	int nr_rw_sect = len >> SECTOR_SIZE_SHIFT;
	int off = pos_end % SECTOR_SIZE;

	//if the buf is not n * SECTOR_SIZE, just give one more sector
	if (off > 0) {
		nr_rw_sect ++;
	}

	int nr_sect = nr_sect_start + nr_rw_sect;

	//if the sects in the file is not enough
	if (nr_sect > pin->i_nr_sects) {
		//allocate the sectors that needed
		assert(WRITE == mode);
		u32 zone_amount = alloc_zone(pin->i_dev, pin->i_nr_sects, nr_sect - pin->i_nr_sects, pin->i_zone);
		assert(nr_sect - pin->i_nr_sects == zone_amount);
		pin->i_nr_sects += zone_amount;
	}

	if (nr_sect_start < NR_DIRECT_ZONE) {
		//the sectors are only in the direct zone
		int flag_direct_zone = 1;

		//asumpt the amount of the sect is less than direct zone
		int direct_nr_rw_sect = nr_rw_sect;
		if (nr_sect > NR_DIRECT_ZONE) {
			//the amount of sects is more than the direct zone
			flag_direct_zone = 0;
			direct_nr_rw_sect = NR_DIRECT_ZONE - nr_sect_start;
			nr_rw_sect -= direct_nr_rw_sect;
		}
		for (i = 0; i < direct_nr_rw_sect; i++, align++) {
			if (WRITE == mode) {
  				phys_copy((void*)va2la(TASK_FS, fsbuf),
						(void*)va2la(src, buf + align * SECTOR_SIZE),
						SECTOR_SIZE);
				WR_SECT(pin->i_dev, pin->i_zone[nr_sect_start + i]);
			} else if (READ == mode) {
				RD_SECT(pin->i_dev, pin->i_zone[nr_sect_start + i]);
				phys_copy((void*)va2la(src, buf + align * SECTOR_SIZE),
						(void*)va2la(TASK_FS, fsbuf),
						SECTOR_SIZE);
			}
		}
		if (flag_direct_zone) {
			return len;
		}
	}

	//the first level indirect zone
	zone_t sectors[NR_ZONE_PER_SECT];

	if (nr_sect_start < NR_SECOND_LEVEL_ZONE) {
		int second_level_start = NR_DIRECT_ZONE;
		if (nr_sect_start > second_level_start) {
			second_level_start = nr_sect_start;
		}
		//the sectors are only reach the second level
		int flag_second_level = 1;
		int second_nr_rw_sect = nr_rw_sect;
		if (nr_sect > NR_SECOND_LEVEL_ZONE) {
			//the amount of sects is more than the second level zone
			flag_second_level = 0;
			second_nr_rw_sect = NR_SECOND_LEVEL_ZONE - second_level_start;
			nr_rw_sect -= second_nr_rw_sect;
		}

		//get the begin and end in second level zone
		second_level_start -= NR_DIRECT_ZONE;

		RD_SECT(pin->i_dev, pin->i_zone[SECOND_LEVEL_ZONE]);
		memcpy((void *)sectors,
				(void *)fsbuf,
				NR_ZONE_PER_SECT * sizeof(int) );

		for (i = 0; i < second_nr_rw_sect; i++, align++) {
            if (WRITE == mode) {
                phys_copy((void*)va2la(TASK_FS, fsbuf),
                        (void*)va2la(src, buf + align * SECTOR_SIZE),
                        SECTOR_SIZE);
                WR_SECT(pin->i_dev, sectors[second_level_start + i]);
            } else if(READ == mode) {
                RD_SECT(pin->i_dev, sectors[second_level_start + i]);
                phys_copy((void*)va2la(src, buf + align * SECTOR_SIZE),
                        (void*)va2la(TASK_FS, fsbuf),
                        SECTOR_SIZE);
            }

		}

		//if the zones only reach second level
		if (flag_second_level) {
			return len;
		}
	} 

	if (nr_sect_start < NR_THIRD_LEVEL_ZONE) {
		//less than the third level indirect zone
		int third_level_start = NR_SECOND_LEVEL_ZONE;
		if (nr_sect_start > third_level_start) {
			third_level_start = nr_sect_start;
		}
		//the sectors are only reach the third level
		int flag_third_level = 1;
		int third_nr_rw_sect = nr_rw_sect;
		if (nr_sect > NR_THIRD_LEVEL_ZONE) {
			//the amount of sects is more than the third level zone
			flag_third_level = 0;
			third_nr_rw_sect = NR_THIRD_LEVEL_ZONE - third_level_start;
			nr_rw_sect -= third_nr_rw_sect;
		}

		//get the start and end in third level zone
		third_level_start -= NR_SECOND_LEVEL_ZONE;

		RD_SECT(pin->i_dev, pin->i_zone[THIRD_LEVEL_ZONE]);
		memcpy((void *)sectors,
				(void *)fsbuf,
				NR_ZONE_PER_SECT * sizeof(int) );

		int current_second_level_zone = NO_ZONE;
		zone_t current_zones[NR_ZONE_PER_SECT];
		for (i = 0; i < third_nr_rw_sect; i++, align++) {
			int second_level_index	=
				(third_level_start + i) /
				NR_SECT_PER_SECOND_LEVEL_ZONE;
			int third_level_index = 
				(third_level_start + i) %
				NR_SECT_PER_SECOND_LEVEL_ZONE;

			if (NO_ZONE == current_second_level_zone
					|| current_second_level_zone != sectors[second_level_index]){
				RD_SECT(pin->i_dev, sectors[second_level_index]);
				memcpy((void *)current_zones,
						(void *)fsbuf,
						NR_ZONE_PER_SECT * sizeof(int) );
			}

			//record the current second level zone for compare in next time
			//to comfirm if that the current second level zone is finished
			current_second_level_zone = sectors[second_level_index];

            if (WRITE == mode) {
                phys_copy((void*)va2la(TASK_FS, fsbuf),
                        (void*)va2la(src, buf + align * SECTOR_SIZE),
                        SECTOR_SIZE);
                WR_SECT(pin->i_dev, current_zones[third_level_index]);
            } else if(READ == mode) {
                RD_SECT(pin->i_dev, current_zones[third_level_index]);
                phys_copy((void*)va2la(src, buf + align * SECTOR_SIZE),
                        (void*)va2la(TASK_FS, fsbuf),
                        SECTOR_SIZE);
            }

		}

		//if the zones only reach third level
		if (flag_third_level) {
			return len;
		}
	}

	if (nr_sect > NR_THIRD_LEVEL_ZONE) {
		//do not support zones larger than third level
		panic("buf is too large");
	}

	return -1;
}		/* -----  end of function rdwt_zones  ----- */