summaryrefslogtreecommitdiffstats
path: root/read.c
diff options
context:
space:
mode:
authorHans Ulrich Niedermann <hun@n-dimensional.de>2007-12-14 16:08:25 +0100
committerHans Ulrich Niedermann <hun@n-dimensional.de>2007-12-14 16:08:25 +0100
commit6749719af90afe9544db14bdd8e2742926f1439c (patch)
tree9bb8edef05f9625be2ccd9bce5cb245af63effc4 /read.c
downloade2tools-6749719af90afe9544db14bdd8e2742926f1439c.tar.gz
e2tools-6749719af90afe9544db14bdd8e2742926f1439c.tar.xz
e2tools-6749719af90afe9544db14bdd8e2742926f1439c.zip
Upstream's 0.0.16v0.0.16upstream
Diffstat (limited to 'read.c')
-rw-r--r--read.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/read.c b/read.c
new file mode 100644
index 0000000..e469ccb
--- /dev/null
+++ b/read.c
@@ -0,0 +1,368 @@
+/* $Header: /home/ksheff/src/e2tools/RCS/read.c,v 0.2 2002/08/08 07:58:35 ksheff Exp $ */
+/*
+ * read.c
+ *
+ * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed
+ * under the terms of the GNU Public License.
+ *
+ * Derived from dump.c Copyright (C) 1994 Theodore Ts'o <tytso@mit.edu>
+ *
+ */
+
+static char rcsid[] = "$Id: read.c,v 0.2 2002/08/08 07:58:35 ksheff Exp $";
+
+static char copyright[] = "Copyright 2002 Keith W Sheffield";
+
+#ifndef READ_C
+#define READ_C
+#endif
+
+/* Description */
+/*
+ *
+ *
+ */
+/*
+ * $Log: read.c,v $
+ * Revision 0.2 2002/08/08 07:58:35 ksheff
+ * Split the read loop from retrieve_data() out to its own function:
+ * read_to_eof() and made retrieve_data() able to seek to an offset before
+ * starting to read.
+ *
+ * Revision 0.1 2002/02/27 04:48:52 ksheff
+ * initial revision
+ *
+ */
+
+/* Feature Test Switches */
+/* Headers */
+#include "e2tools.h"
+
+/* Local Prototypes */
+
+long
+get_file(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ char *infile, char *outfile, int keep);
+
+long
+retrieve_data(ext2_filsys fs, ext2_ino_t src, int dest_fd,
+ char *dest_name, int keep, ext2_off_t offset,
+ ext2_off_t *ret_pos);
+
+long
+read_to_eof(ext2_file_t infile, int dest_fd, ext2_off_t offset,
+ ext2_off_t *ret_pos);
+
+
+static void
+fix_perms(const struct ext2_inode *inode, int fd, const char *name);
+
+/* Name: get_file()
+ *
+ * Description:
+ *
+ * This function copies a file from the current ext2fs directory to disk
+ * or stdout.
+ *
+ * Algorithm:
+ *
+ * Check input parameters
+ * If the output file is NULL
+ * Get the file descriptor for stdout
+ * Otherwise
+ * Open the output file
+ * Get the inode number for the input file
+ * Copy the contents to the output file
+ * Close output file
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ * ext2_filsys fs; The current file system
+ * ext2_ino_t root; The root directory
+ * ext2_ino_t cwd; The current working directory
+ * char *infile; The name of the input file
+ * char *outfile; The name of the output file
+ * int keep; Flag indicating if the permissions should be kept
+ *
+ * Return Values:
+ *
+ * 0 - the file was copied successfully
+ * the error code of whatever went wrong.
+ *
+ * Author: Keith W. Sheffield
+ * Date: 02/20/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+
+long
+get_file(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ char *infile, char *outfile, int keep)
+{
+ int fd;
+ ext2_ino_t src;
+ int dest;
+ int retval;
+
+ if (fs == NULL || infile == NULL)
+ {
+ fputs("Invalid input parameter. Exiting get_file() with -1\n",
+ stderr);
+ return (-1);
+ }
+
+ /* open the output file if we need to */
+ if (outfile == NULL)
+ dest = fileno(stdout);
+ else if (-1 == (dest = open(outfile, O_CREAT | O_WRONLY | O_TRUNC, 0666)))
+ {
+ perror(outfile);
+ return(-1);
+ }
+
+ /* get the inode number associated with the input file */
+ if ((retval = ext2fs_namei(fs, root, cwd, infile, &src)))
+ {
+ if (retval == EXT2_ET_FILE_NOT_FOUND)
+ {
+ fprintf(stderr, "%s not found\n", infile);
+ if (outfile)
+ {
+ close(dest);
+#ifndef DEBUG
+ unlink(outfile);
+#endif
+ }
+ return(0);
+ }
+ fputs(error_message(retval), stderr);
+ return retval;
+ }
+
+ /* get the data from the ext2fs */
+ if ((retval = retrieve_data(fs, src, dest, outfile, keep, 0, NULL)))
+ {
+ if (outfile)
+ {
+ close(dest);
+#ifndef DEBUG
+ unlink(outfile);
+#endif
+ }
+ return(retval);
+ }
+ if (outfile)
+ close(dest);
+ return(0);
+
+} /* end of get_file */
+
+
+/* Name: retrieve_data()
+ *
+ * Description:
+ *
+ * This function retrieves the data stored as a file in an ext2fs file
+ * system.
+ *
+ * Algorithm:
+ *
+ * Get the inode associated with the file name
+ * Open the file in the ext2fs file system
+ * Copy the contents of the ext2fs file to the output file descriptor
+ * Close the ext2fs file
+ * If the permissions are to be kept
+ * Call fix_perms
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ * ext2_filsys fs; The filesystem being read from
+ * ext2_ino_t src; The source inode number
+ * int dest_fd; The destination file descriptor
+ * char *dest_name; The name of the destination file
+ * int keep; Keep the permissions/ownership, etc. from ext2fs
+ *
+ * Return Values:
+ *
+ * 0 - file read successfully
+ * error code of what went wrong.
+ *
+ * Author: Keith W. Sheffield
+ * Date: 02/20/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ * 08/07/02 K.Sheffield Moved the copy loop to read_to_eof()
+ *
+ */
+
+long
+retrieve_data(ext2_filsys fs, ext2_ino_t src, int dest_fd,
+ char *dest_name, int keep, ext2_off_t offset,
+ ext2_off_t *ret_pos)
+{
+ struct ext2_inode inode;
+ ext2_file_t infile;
+ int retval;
+
+ if (keep && (retval = ext2fs_read_inode(fs, src, &inode)))
+ {
+ fputs(error_message(retval), stderr);
+ return retval;
+ }
+
+ if ((retval = ext2fs_file_open(fs, src, 0, &infile)))
+ {
+ fputs(error_message(retval), stderr);
+ return retval;
+ }
+
+ if (read_to_eof(infile, dest_fd, offset, ret_pos))
+ {
+ if ((retval = ext2fs_file_close(infile)))
+ fputs(error_message(retval), stderr);
+ return(-1);
+ }
+
+ if ((retval = ext2fs_file_close(infile)))
+ {
+ fputs(error_message(retval), stderr);
+ return retval;
+ }
+
+ if (keep)
+ fix_perms(&inode, dest_fd, dest_name);
+
+ return(0);
+
+} /* end of retrieve_data */
+
+/* Name: read_to_eof()
+ *
+ * Description:
+ *
+ * This function reads from an ext2_file_t file and outputs the contents
+ * to a standard file descriptor.
+ *
+ * Algorithm:
+ *
+ * Seek to the desired location
+ * While one is able to read data from the ext2fs file
+ * Write data to the output file descriptor.
+ *
+ * Global Variables:
+ *
+ * None.
+ *
+ * Arguments:
+ *
+ * ext2_file_t infile; Input file
+ * int dest_fd; The destination file descriptor
+ * ext2_off_t offset; The offset in the file to seek
+ * ext2_off_t *ret_pos; The returned file position
+ *
+ * Return Values:
+ *
+ *
+ * Author: Keith W. Sheffield
+ * Date: 08/07/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+long
+read_to_eof(ext2_file_t infile, int dest_fd, ext2_off_t offset,
+ ext2_off_t *ret_pos)
+{
+ char buf[4096];
+ unsigned int bytes_read;
+ int bytes_written;
+ int retval;
+
+ if (offset != 0 &&
+ (retval = ext2fs_file_lseek(infile, offset, EXT2_SEEK_SET, NULL)))
+ {
+ fputs(error_message(retval), stderr);
+ return retval;
+ }
+
+ /* read all that we can and dump it to the output file descriptor */
+ do
+ {
+ if ((retval = ext2fs_file_read(infile, buf, sizeof(buf), &bytes_read)))
+ {
+ fputs(error_message(retval), stderr);
+ return retval;
+ }
+ }
+ while (bytes_read > 0 &&
+ bytes_read == (bytes_written = write(dest_fd, buf, bytes_read)));
+
+ if (bytes_read)
+ {
+ perror("read_to_eof");
+ return(-1);
+ }
+
+ if (ret_pos != NULL &&
+ (retval = ext2fs_file_lseek(infile, 0, EXT2_SEEK_CUR, ret_pos)))
+ {
+ fputs(error_message(retval), stderr);
+ return retval;
+ }
+
+ return(0);
+
+} /* end of read_to_eof */
+
+/* blatantly copied from code written by T Ts'o w/ minor changes */
+static void
+fix_perms(const struct ext2_inode *inode, int fd, const char *name)
+{
+ struct utimbuf ut;
+ int i;
+
+ if (fd != -1)
+ i = fchmod(fd, ext2_mode_xlate(inode->i_mode));
+ else
+ i = chmod(name, ext2_mode_xlate(inode->i_mode));
+ if (i == -1)
+ perror(name);
+
+#ifndef HAVE_FCHOWN
+ i = chown(name, inode->i_uid, inode->i_gid);
+#else
+ if (fd != -1)
+ i = fchown(fd, inode->i_uid, inode->i_gid);
+ else
+ i = chown(name, inode->i_uid, inode->i_gid);
+#endif
+ if (i == -1)
+ perror(name);
+
+ if (fd != -1)
+ close(fd);
+
+ ut.actime = inode->i_atime;
+ ut.modtime = inode->i_mtime;
+ if (utime(name, &ut) == -1)
+ perror(name);
+
+}
+
+
+