diff options
author | Hans Ulrich Niedermann <hun@n-dimensional.de> | 2007-12-14 16:08:25 +0100 |
---|---|---|
committer | Hans Ulrich Niedermann <hun@n-dimensional.de> | 2007-12-14 16:08:25 +0100 |
commit | 6749719af90afe9544db14bdd8e2742926f1439c (patch) | |
tree | 9bb8edef05f9625be2ccd9bce5cb245af63effc4 /mv.c | |
download | e2tools-upstream.tar.gz e2tools-upstream.tar.xz e2tools-upstream.zip |
Diffstat (limited to 'mv.c')
-rw-r--r-- | mv.c | 554 |
1 files changed, 554 insertions, 0 deletions
@@ -0,0 +1,554 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/mv.c,v 0.1 2002/03/21 09:03:25 ksheff Exp $ */ +/* + * mv.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + */ + + +#ifndef MV_C +#define MV_C +#endif + +/* Description */ +/* + * Module to move/rename files + * + */ +/* + * $Log: mv.c,v $ + * Revision 0.1 2002/03/21 09:03:25 ksheff + * initial revision. + * + */ + +/* Feature Test Switches */ +/* Headers */ +#include "e2tools.h" + +/* Macros */ +#define USAGE "Usage: e2mv [-vfs] source1 [... sourceN] destination\n" + +/* Local Prototypes */ +static long +do_swap(int force, int verbose, int curidx, int argc, char **argv); + +/* Name: do_mv() + * + * Description: + * + * This function reads the command line arguments and moves or renames files + * in an ext2fs file system + * + * Algorithm: + * + * Read any command line switches + * Get the first source file specification + * If we are performing a file swap, call do_swap() + * Open the file system + * Get the destination and determine if it is a directory + * If not, then get the destination's directory and basename + * Also check that the number of source files are no more than one + * For each source file + * Get the directory and basename of the source file + * Determine the inode number for the source file + * Create the link + * Unlink the original source file. + * + * Global Variables: + * + * None + * + * Arguments: + * + * int argc; The number of arguments + * char *argv[]; The command line arguments + * + * Return Values: + * + * 0 - the file was move successfully + * an error occurred. + * + * Author: Keith W. Sheffield + * Date: 03/20/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + */ +long +do_mv(int argc, char *argv[]) +{ + int verbose=0; + int force=0; + int swap_files=0; + int num_files; + int errcnt=0; + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t srcd; + ext2_ino_t destd; + ext2_ino_t source_file; + char *src_dir; + char *dest_dir; + char *src_name; + char *dest_name; + char *result_name; + long retval; + int c; + int curidx; + +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt(argc, argv, "vfs")) != EOF) + { + switch (c) + { + case 'v': + verbose = 1; + break; + case 'f': + force = E2T_FORCE; + break; + case 's': + swap_files = 1; + break; + default: + errcnt++; + break; + } + } + + curidx = optind; + + force |= E2T_DO_MV; + + if (errcnt || argc < curidx+2) + { + fputs(USAGE, stderr); + return(1); + } + + if (swap_files) + return(do_swap(force, verbose, curidx, argc, argv)); + + cur_filesys = argv[curidx++]; + if (NULL == (src_dir = strchr(cur_filesys, ':'))) + { + fprintf(stderr, "Invalid file specification: %s\n", cur_filesys); + return(1); + } + *src_dir++ = '\0'; + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 1))) + { + fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys); + return retval; + } + + + /* get the destination directory */ + dest_name = NULL; + if (strcmp(dest_dir = argv[argc-1], ".") != 0) + { + /* check to see if the file name already exists in the current + * directory and also see if it is a directory. + */ + if ((retval = ext2fs_namei(fs, root, root, dest_dir, &destd)) || + (retval = ext2fs_check_directory(fs, destd))) + { + if (retval != EXT2_ET_FILE_NOT_FOUND && + retval != EXT2_ET_NO_DIRECTORY) + { + fprintf(stderr, "%s\n",error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + /* ok, so it's either not there or it's not a directory, so + * get the real destination directory and file name. + */ + if (curidx+1 < argc) + { + fprintf(stderr, "%s must be a directory!\n", dest_dir); + ext2fs_close(fs); + return(1); + } + + if (get_file_parts(fs, root, dest_dir, &destd, &dest_dir, + &dest_name)) + { + ext2fs_close(fs); + return(-1); + } + } + else /* we have a directory!!! */ + dest_name = NULL; + } + else + { + destd = root; + dest_name = NULL; + } + + do + { + /* move to the source directory */ + if (get_file_parts(fs, root, src_dir, &srcd, &src_dir, &src_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the source file */ + if ((retval = ext2fs_namei(fs, srcd, srcd, src_name, &source_file))) + { + fprintf(stderr, "%s: source file %s\n",error_message(retval), + src_name); + ext2fs_close(fs); + return(retval); + } + + result_name = (dest_name) ? dest_name : src_name; + + /* now create the link */ + if ((retval = create_hard_link(fs, destd, source_file, result_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((src_dir == NULL) ? "." : src_dir), src_name, + ((dest_dir == NULL) ? "." : dest_dir), result_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, srcd, src_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", src_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + if (verbose) + fprintf(stderr, "moved %s/%s as %s/%s\n", + ((src_dir == NULL) ? "." : src_dir), src_name, + ((dest_dir == NULL) ? "." : dest_dir), result_name); + src_dir = argv[curidx++]; + } + while (curidx < argc); + + ext2fs_close(fs); + return(0); + +} /* end of do_mv */ + +/* Name: get_file_parts() + * + * Description: + * + * This function returns each of the following file 'parts': directory name, + * base name, inode number of the directory + * + * Algorithm: + * + * Use the root directory as the current working directory + * Find the last / in the full pathname + * If none are found, set the basename to the full pathname, + * and the directory to NULL + * Otherwise, + * Separate the basename from the directory + * Change the working directory + * Set the return pointers. + * + * Global Variables: + * + * None. + * + * Arguments: + * + * ext2_filsys fs; the filesystem being used + * ext2_ino_t root; the root directory of the filesystem + * char *pathname; the full pathname of the file + * ext2_ino_t *dir_ino; The inode number of the directory + * char **dir_name; the directory the file is in + * char **base_name; The basename of the file + * + * Return Values: + * + * 0 - retrieved the information ok + * otherwise the error code of what went wrong + * + * Author: Keith W. Sheffield + * Date: 03/21/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +long +get_file_parts(ext2_filsys fs, ext2_ino_t root, char *pathname, + ext2_ino_t *dir_ino, char **dir_name, char **base_name) +{ + char *fname; + long retval; + + /* move to the source directory */ + *dir_name = pathname; + *dir_ino = root; + if (NULL == (fname = strrchr(pathname, '/'))) + { + fname = pathname; + *dir_name = NULL; + } + else + { + *fname++ = '\0'; + if ((*pathname != '\0' && strcmp(pathname, ".") != 0) && + (retval = change_cwd(fs, root, dir_ino, pathname))) + { + fprintf(stderr, "Error changing to directory %s\n", + pathname); + return(retval); + } + } + + *base_name = fname; + return(0); +} /* end of get_file_parts */ + + +/* Name: do_swap() + * + * Description: + * + * This function swaps the names of two files and optionally assigns the + * first file a new name: + * + * file1 file2 file3 + * + * After the operation, file1 will reference the file that was originally file2, and file3 will reference the what used to be file1. + * + * Algorithm: + * + * check input parameters + * Get the directory and inode numbers for the first two files + * If a third file exists + * Get the directory info for the file + * Rename the first file to the third + * Rename the 2nd file to the first + * Otherwise + * Remove the first file from its directory + * Rename the 2nd file to the first + * Add the first file back as the 2nd file. + * + * Global Variables: + * + * None. + * + * Arguments: + * + * int force; Flag indicating if existing files are to be removed + * int verbose; Flag to print lots of output + * int curidx; The current index in the command line args + * int argc; The total number of arguments + * char **argv; Pointer to an array of argument strings. + * + * Return Values: + * + * 0 - the operation was successful + * otherwise the error code of what went wrong. + * + * Author: Keith W. Sheffield + * Date: 03/21/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ + +static long +do_swap(int force, int verbose, int curidx, int argc, char **argv) +{ + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t file1_dirno; + ext2_ino_t file2_dirno; + ext2_ino_t file3_dirno; + ext2_ino_t file1_no; + ext2_ino_t file2_no; + char *file1_dir; + char *file2_dir; + char *file3_dir; + char *file1_name; + char *file2_name; + char *file3_name; + long retval; + + if (curidx + 2 > argc) + { + fputs(USAGE, stderr); + return(1); + } + + cur_filesys = argv[curidx++]; + if (NULL == (file1_dir = strchr(cur_filesys, ':'))) + { + fprintf(stderr, "Invalid file specification: %s\n", cur_filesys); + return(1); + } + *file1_dir++ = '\0'; + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 1))) + { + fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys); + return retval; + } + + /* move to the file 1 directory */ + if (get_file_parts(fs, root, file1_dir, &file1_dirno, &file1_dir, + &file1_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the file 1 file */ + if ((retval = ext2fs_namei(fs, file1_dirno, file1_dirno, file1_name, + &file1_no))) + { + fprintf(stderr, "%s: file 1 file %s\n",error_message(retval), + file1_name); + ext2fs_close(fs); + return(retval); + } + + + /* move to the file 2 directory */ + if (get_file_parts(fs, root, argv[curidx++], &file2_dirno, &file2_dir, + &file2_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the file 2 file */ + if ((retval = ext2fs_namei(fs, file2_dirno, file2_dirno, file2_name, + &file2_no))) + { + fprintf(stderr, "%s: file 2 file %s\n",error_message(retval), + file2_name); + ext2fs_close(fs); + return(retval); + } + + if (curidx < argc) + { + /* move to the file 3 directory */ + if (get_file_parts(fs, root, argv[curidx++], &file3_dirno, &file3_dir, + &file3_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* now move the first file to the 3rd */ + if ((retval = create_hard_link(fs, file3_dirno, file1_no, file3_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file3_dir == NULL) ? "." : file3_dir), file3_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, file1_dirno, file1_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file1_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + + /* now move the 2nd file to the 1st */ + if ((retval = create_hard_link(fs, file1_dirno, file2_no, file1_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file2_dir == NULL) ? "." : file2_dir), file2_name, + ((file1_dir == NULL) ? "." : file1_dir), file1_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, file2_dirno, file2_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file2_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + if (verbose) + fprintf(stderr, "renamed file %s/%s as %s/%s\n" + "renamed file %s/%s as %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file3_dir == NULL) ? "." : file3_dir), file3_name, + ((file2_dir == NULL) ? "." : file2_dir), file2_name, + ((file1_dir == NULL) ? "." : file1_dir), file1_name); + } + else + { + /* now remove the first file */ + if ((retval = ext2fs_unlink(fs, file1_dirno, file1_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file1_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + /* now move the 2nd file to the 1st */ + if ((retval = create_hard_link(fs, file1_dirno, file2_no, file1_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file2_dir == NULL) ? "." : file2_dir), file2_name, + ((file1_dir == NULL) ? "." : file1_dir), file1_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, file2_dirno, file2_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file2_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + if ((retval = create_hard_link(fs, file2_dirno, file1_no, file2_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file2_dir == NULL) ? "." : file2_dir), file2_name); + ext2fs_close(fs); + return(1); + } + + if (verbose) + fprintf(stderr, "swapped files %s/%s <-> %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file2_dir == NULL) ? "." : file2_dir), file2_name); + + } + + ext2fs_close(fs); + return(0); + +} /* end of do_swap */ |