Пример #1
0
static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
				 int size, const void *buf)
{
	struct inode_private_data *data;
	errcode_t	retval = 0;

	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
	data = (struct inode_private_data *) channel->private_data;
	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);

	if ((retval = ext2fs_file_lseek(data->file, offset,
					EXT2_SEEK_SET, 0)))
		return retval;

	return ext2fs_file_write(data->file, buf, size, 0);
}
Пример #2
0
static errcode_t inode_write_blk64(io_channel channel,
				unsigned long long block, int count, const void *buf)
{
	struct inode_private_data *data;
	errcode_t	retval;

	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
	data = (struct inode_private_data *) channel->private_data;
	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);

	if ((retval = ext2fs_file_lseek(data->file,
					block * channel->block_size,
					EXT2_SEEK_SET, 0)))
		return retval;

	count = (count < 0) ? -count : (count * channel->block_size);

	return ext2fs_file_write(data->file, buf, count, 0);
}
Пример #3
0
static int read_journal_block(const char *cmd, struct journal_source *source,
			      off_t offset, char *buf, unsigned int size)
{
	int retval;
	unsigned int got;

	if (source->where == JOURNAL_IS_EXTERNAL) {
		if (lseek(source->fd, offset, SEEK_SET) < 0) {
			retval = errno;
			goto seek_err;
		}
		retval = read(source->fd, buf, size);
		if (retval < 0) {
			retval = errno;
			goto read_err;
		}
		got = retval;
		retval = 0;
	} else {
		retval = ext2fs_file_lseek(source->file, offset,
					   EXT2_SEEK_SET, NULL);
		if (retval) {
		seek_err:
			com_err(cmd, retval, "while seeking in reading journal");
			return retval;
		}
		retval = ext2fs_file_read(source->file, buf, size, &got);
		if (retval) {
		read_err:
			com_err(cmd, retval, "while reading journal");
			return retval;
		}
	}
	if (got != size) {
		com_err(cmd, 0, "short read (read %u, expected %u) "
			"while reading journal", got, size);
		retval = -1;
	}
	return retval;
}
Пример #4
0
static int read_journal_block(const char *cmd, struct journal_source *source,
			      off_t offset, char *buf, int size,
			      unsigned int *got)
{
	int retval;

	if (source->where == JOURNAL_IS_EXTERNAL) {
		if (lseek(source->fd, offset, SEEK_SET) < 0) {
			retval = errno;
			com_err(cmd, retval, "while seeking in reading journal");
			return retval;
		}
		retval = read(source->fd, buf, size);
		if (retval >= 0) {
			*got = retval;
			retval = 0;
		} else
			retval = errno;
	} else {
		retval = ext2fs_file_lseek(source->file, offset,
					   EXT2_SEEK_SET, NULL);
		if (retval) {
			com_err(cmd, retval, "while seeking in reading journal");
			return retval;
		}

		retval = ext2fs_file_read(source->file, buf, size, got);
	}

	if (retval)
		com_err(cmd, retval, "while reading journal");
	else if (*got != (unsigned int) size) {
		com_err(cmd, 0, "short read (read %d, expected %d) "
			"while reading journal", *got, size);
		retval = -1;
	}

	return retval;
}
Пример #5
0
/* Name:	tail()
 *
 * Description:
 *
 * This function displays the last lines at the end of a file in an ext2
 * file system.
 *
 * Algorithm:
 *
 * Get the directory and basename of the file
 * Determine the inode number for the file
 * Open the file for reading
 * Skip to the last block in the file
 * While we have not found the last num_lines of newline characters
 *	  Skip backwards in the file one block and read it
 * Display the contents of the block from that point on.
 * Display the rest of the file if not contained in the block
 * Save the current location of the file.
 * If we are following the file as it grows
 *	  While forever
 *		  Sleep
 *		  Re-read the inode for the file
 *		  If the size has changed
 *			  Display the file from the saved point on
 *            Save the current location of the file.
 *	  
 *	  
 * Global Variables:
 *
 * None
 *
 * Arguments:
 *
 * ext2_filsys *fs;             Our filesystem
 * ext2_ino_t root;             The root directory inode number
 * char *input;                 The name of the input file to tail
 * int num_lines;               The number of lines to display
 * int follow;                  Flag indicating if the we should follow any
 *                              new contents to the file.
 * int sleep_int;               The number of seconds to sleep between checking
 *                              for new lines
 * char *cur_filesys
 *
 * Return Values:
 *
 * 0 - the last number of lines was displayed correctly.
 * an error occurred.
 *
 * Author: Keith W. Sheffield
 * Date:   08/07/2002
 *
 * Modification History:
 *
 * MM/DD/YY		 Name				Description
 */
static long
tail(ext2_filsys *fs_ptr, ext2_ino_t root, char *input, int num_lines,
     int follow, int sleep_int, char *cur_filesys)
{
  ext2_filsys fs = *fs_ptr;
  ext2_ino_t cwd;
  ext2_ino_t tail_ino;
  ext2_ino_t t_tail_ino;
  char *tail_dir;
  char *tail_name;
  long retval;
  char buf[BLK_SIZE];
  unsigned int bytes_to_read;
  unsigned int bytes_read;
  char *ptr;
  struct ext2_inode inode;
  ext2_file_t tail_fd;    
  ext2_off_t offset;
  ext2_off_t cur_pos;

  if (get_file_parts(fs, root, input, &cwd, &tail_dir, &tail_name))
    {
      ext2fs_close(fs);
      return(-1);
    }          

  /* get the inode number for the source file */
  if ((retval = ext2fs_namei(fs, cwd, cwd, tail_name, &tail_ino)))
    {
      fprintf(stderr, "%s: file %s\n",error_message(retval),
              tail_name);
      return(retval);
    }

  /* open the file */
  if ((retval = ext2fs_file_open(fs, tail_ino, 0, &tail_fd)))
    {
      fputs(error_message(retval), stderr);
      return retval;
    }

  /* get the length of the file and determine where to start reading */
  inode.i_size = offset = ext2fs_file_get_size(tail_fd);
  bytes_to_read = offset % BLK_SIZE;
  if (bytes_to_read == 0)
    bytes_to_read = BLK_SIZE;

  offset -= bytes_to_read;
  if (((int32_t)offset) < 0)
    offset = 0;

  do
    {
      /* seek to the start of the last block in the file */
      if ((retval = ext2fs_file_lseek(tail_fd, offset, EXT2_SEEK_SET, NULL)))
        {
          fputs(error_message(retval), stderr);
          return retval;
        }
      /* read the last block in the file */
      if ((retval = ext2fs_file_read(tail_fd, buf, bytes_to_read,
                                     &bytes_read)))
        {
          fputs(error_message(retval), stderr);
          return retval;
        }
      if (bytes_to_read != bytes_read)
        {
          fputs("error reading file\n", stderr);
          return(-1);
        }
      
      ptr = buf + bytes_read - 1;
      while (bytes_to_read--)
        {
          if (*ptr == '\n' && num_lines-- == 0)
            {
              /* if the newline wasn't the last character in the buffer, then
               * print what's remaining.
               */
              if (bytes_to_read != bytes_read - 1)
                {
                  ptr++;
		  if (0 > write(1, ptr, bytes_read - bytes_to_read - 1))
		    {
		      perror("writing bytes to stdout");
		      return -1;
		    }
                }
              offset = 0;       /* make sure we break out of the main loop */
              break;
            }
          ptr--;
        }

      offset -= (offset < BLK_SIZE) ? offset : BLK_SIZE;
      bytes_to_read = BLK_SIZE;
    }
  while (offset > 0);

  /* if we are here and have any lines left, we hit the beginning, so
   * dump the rest of what's in memory out.
   */
  
  if (num_lines > 0)
    {
      if (0 > write(1, buf, bytes_read)) {
	perror("writing bytes to stdout");
	return -1;
      }
    }
    
  /* retreive the current position in the file */
  if ((retval = ext2fs_file_lseek(tail_fd, 0, EXT2_SEEK_CUR, &cur_pos)))
    {
      fputs(error_message(retval), stderr);
      return retval;
    }

  /* ok, if we are before the end of the file, then dump the rest of it */
  if (cur_pos < inode.i_size)
    {
      if ((retval = read_to_eof(tail_fd, 1, cur_pos, &cur_pos)))
        {
          return retval;
        }
    }

  if ((retval = ext2fs_file_close(tail_fd)))
    {
      fputs(error_message(retval), stderr);
      return retval;
    }

  if (follow)
    {
      while(1)
        {
          sleep(sleep_int);
          /* I don't know how to force a re-read of the file system info yet,
           * so, just close the file system and reopen it.
           */
          ext2fs_close(fs);
          if ((retval = open_filesystem(cur_filesys, &fs, &root, 0)))
            {
              *fs_ptr = NULL;
              fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys);
              return retval;
            }
          *fs_ptr = fs;

          /* if we are following the name, find the directory and file name
           * again.
           */
          if (follow == FOLLOW_NAME)
            {
              cwd = root;
              
              if (tail_dir != NULL && *tail_dir != '\0' &&
                  strcmp(tail_dir, ",") != 0 &&
                  (retval = change_cwd(fs, root, &cwd, tail_dir)))
                {
                  fprintf(stderr, "Error changing to directory %s\n",
                          tail_dir);
                  return(retval);
                }

              /* get the inode number for the source file */
              if ((retval = ext2fs_namei(fs, cwd, cwd, tail_name,
                                         &t_tail_ino)))
                {
                  fprintf(stderr, "%s: file %s\n",error_message(retval),
                          tail_name);
                  return(retval);
                }

              /* if we are dealing with a new file, then start from the
               * beginning.
               */
              
              if (t_tail_ino != tail_ino)
                {
                  tail_ino = t_tail_ino;
                  cur_pos = 0;
                }
            }
          
          if ((retval = ext2fs_read_inode(fs, tail_ino, &inode)))
            {
              fputs(error_message(retval), stderr);
              return retval;
            }
          if (inode.i_size > cur_pos)
            {
              if ((retval = retrieve_data(fs, tail_ino, 1, NULL, 0, cur_pos,
                                          &cur_pos)))
                {
                  fputs(error_message(retval), stderr);
                  return retval;
                }
            }
          else if (inode.i_size < cur_pos)
            {
              /* the file was truncated, so bail */
              return(0);
            }          
        }
    }
  return(0);
}
Пример #6
0
static errcode_t copy_file(ext2_filsys fs, int fd, ext2_ino_t newfile,
			   int bufsize, int make_holes)
{
	ext2_file_t	e2_file;
	errcode_t	retval, close_ret;
	int		got;
	unsigned int	written;
	char		*buf;
	char		*ptr;
	char		*zero_buf;
	int		cmp;

	retval = ext2fs_file_open(fs, newfile,
				  EXT2_FILE_WRITE, &e2_file);
	if (retval)
		return retval;

	retval = ext2fs_get_mem(bufsize, &buf);
	if (retval) {
		com_err("copy_file", retval, "can't allocate buffer\n");
		goto out_close;
	}

	/* This is used for checking whether the whole block is zero */
	retval = ext2fs_get_memzero(bufsize, &zero_buf);
	if (retval) {
		com_err("copy_file", retval, "can't allocate zero buffer\n");
		goto out_free_buf;
	}

	while (1) {
		got = read(fd, buf, bufsize);
		if (got == 0)
			break;
		if (got < 0) {
			retval = errno;
			goto fail;
		}
		ptr = buf;

		/* Sparse copy */
		if (make_holes) {
			/* Check whether all is zero */
			cmp = memcmp(ptr, zero_buf, got);
			if (cmp == 0) {
				 /* The whole block is zero, make a hole */
				retval = ext2fs_file_lseek(e2_file, got,
							   EXT2_SEEK_CUR,
							   NULL);
				if (retval)
					goto fail;
				got = 0;
			}
		}

		/* Normal copy */
		while (got > 0) {
			retval = ext2fs_file_write(e2_file, ptr,
						   got, &written);
			if (retval)
				goto fail;

			got -= written;
			ptr += written;
		}
	}

fail:
	ext2fs_free_mem(&zero_buf);
out_free_buf:
	ext2fs_free_mem(&buf);
out_close:
	close_ret = ext2fs_file_close(e2_file);
	if (retval == 0)
		retval = close_ret;
	return retval;
}