summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2008-05-27 00:17:02 +0200
committerChristophe Grenier <grenier@cgsecurity.org>2008-05-27 00:17:02 +0200
commit4f2949ac4c466b3243a5c2db0eaf87c58c40a8cb (patch)
treec93886894818366023900537a9e68e95bcd88b60 /src
parentbd354a7f0aa968d8945a54c40da6a6415866b725 (diff)
support for file copy from ext2/ext3
Diffstat (limited to 'src')
-rw-r--r--src/dir.c51
-rw-r--r--src/dir.h1
-rw-r--r--src/ext2_dir.c77
3 files changed, 128 insertions, 1 deletions
diff --git a/src/dir.c b/src/dir.c
index 7cc8323..251931d 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -731,3 +731,54 @@ int filesort(const struct td_list_head *a, const struct td_list_head *b)
/* Files and directories are sorted by name */
return strcmp(file_a->name,file_b->name);
}
+
+/*
+ * The mode_xlate function translates a linux mode into a native-OS mode_t.
+ */
+
+static struct {
+ unsigned int lmask;
+ mode_t mask;
+} mode_table[] = {
+ { LINUX_S_IRUSR, S_IRUSR },
+ { LINUX_S_IWUSR, S_IWUSR },
+ { LINUX_S_IXUSR, S_IXUSR },
+ { LINUX_S_IRGRP, S_IRGRP },
+ { LINUX_S_IWGRP, S_IWGRP },
+ { LINUX_S_IXGRP, S_IXGRP },
+ { LINUX_S_IROTH, S_IROTH },
+ { LINUX_S_IWOTH, S_IWOTH },
+ { LINUX_S_IXOTH, S_IXOTH },
+ { 0, 0 }
+};
+
+static mode_t mode_xlate(unsigned int lmode)
+{
+ mode_t mode = 0;
+ int i;
+
+ for (i=0; mode_table[i].lmask; i++) {
+ if (lmode & mode_table[i].lmask)
+ mode |= mode_table[i].mask;
+ }
+ return mode;
+}
+
+/**
+ * set_mode - Set the file's date and time
+ * @pathname: Path and name of the file to alter
+ * @mode: Mode using LINUX values
+ *
+ * Give a file a particular mode.
+ *
+ * Return: 1 Success, set the file's mode
+ * 0 Error, failed to change the file's mode
+ */
+int set_mode(const char *pathname, unsigned int mode)
+{
+#if defined(HAVE_CHMOD) && ! ( defined(__CYGWIN__) || defined(__MINGW32__) || defined(DJGPP) || defined(__OS2__))
+ return chmod(pathname, mode_xlate(mode));
+#else
+ return 0;
+#endif
+}
diff --git a/src/dir.h b/src/dir.h
index 08d77be..f9c58ac 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -74,6 +74,7 @@ int dir_whole_partition_log(disk_t *disk_car, const partition_t *partition, dir_
void mode_string (const unsigned int mode, char *str);
FILE *create_file(const char *filename);
int set_date(const char *pathname, time_t actime, time_t modtime);
+int set_mode(const char *pathname, unsigned int mode);
#define LINUX_S_IFMT 00170000
#define LINUX_S_IFSOCK 0140000
diff --git a/src/ext2_dir.c b/src/ext2_dir.c
index 22bef02..a747093 100644
--- a/src/ext2_dir.c
+++ b/src/ext2_dir.c
@@ -27,6 +27,9 @@
#ifdef HAVE_STRING_H
#include <string.h>
#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -66,6 +69,7 @@ static errcode_t my_flush(io_channel channel);
static io_channel alloc_io_channel(disk_t *disk_car,my_data_t *my_data);
static void dir_partition_ext2_close(dir_data_t *dir_data);
+static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_data_t *file);
static struct struct_io_manager my_struct_manager = {
magic: EXT2_ET_MAGIC_IO_MANAGER,
@@ -293,7 +297,7 @@ int dir_partition_ext2_init(disk_t *disk_car, const partition_t *partition, dir_
dir_data->verbose=verbose;
dir_data->capabilities=0;
dir_data->get_dir=ext2_dir;
- dir_data->copy_file=NULL;
+ dir_data->copy_file=ext2_copy;
dir_data->close=&dir_partition_ext2_close;
dir_data->local_dir=NULL;
dir_data->private_dir_data=ls;
@@ -303,6 +307,77 @@ int dir_partition_ext2_init(disk_t *disk_car, const partition_t *partition, dir_
#endif
}
+static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_data_t *file)
+{
+ int error=0;
+ FILE *f_out;
+ struct ext2_dir_struct *ls = (struct ext2_dir_struct *)dir_data->private_dir_data;
+ char *new_file;
+ {
+ int l1=strlen(dir_data->local_dir);
+ int l2=strlen(dir_data->current_directory);
+ new_file=MALLOC(l1+l2+1);
+ l1=filename_convert(new_file, dir_data->local_dir, l1+1);
+ filename_convert(new_file+l1, dir_data->current_directory, l2+1);
+ }
+ f_out=create_file(new_file);
+ if(!f_out)
+ {
+ log_critical("Can't create file %s: %s\n", new_file, strerror(errno));
+ free(new_file);
+ return -4;
+ }
+ {
+ errcode_t retval;
+ struct ext2_inode inode;
+ char buffer[8192];
+ ext2_file_t e2_file;
+ int nbytes;
+ unsigned int got;
+
+ if (ext2fs_read_inode(ls->current_fs, file->filestat.st_ino, &inode)!=0)
+ {
+ free(new_file);
+ return -1;
+ }
+
+ retval = ext2fs_file_open(ls->current_fs, file->filestat.st_ino, 0, &e2_file);
+ if (retval) {
+ log_error("Error while opening ext2 file %s\n", dir_data->current_directory);
+ free(new_file);
+ return -2;
+ }
+ while (1)
+ {
+ retval = ext2fs_file_read(e2_file, buffer, sizeof(buffer), &got);
+ if (retval)
+ {
+ log_error("Error while reading ext2 file %s\n", dir_data->current_directory);
+ error=-3;
+ }
+ if (got == 0)
+ break;
+ nbytes = fwrite(buffer, 1, got, f_out);
+ if ((unsigned) nbytes != got)
+ {
+ log_error("Error while writing file %s\n", new_file);
+ error=-5;
+ }
+ }
+ retval = ext2fs_file_close(e2_file);
+ if (retval)
+ {
+ log_error("Error while closing ext2 file\n");
+ error=-6;
+ }
+ fclose(f_out);
+ set_date(new_file, file->filestat.st_atime, file->filestat.st_mtime);
+ set_mode(new_file, file->filestat.st_mode);
+ }
+ free(new_file);
+ return error;
+}
+
const char*td_ext2fs_version(void)
{
const char *ext2fs_version="none";