Changes in uspace/app/bdsh/cmds/modules/cp/cp.c [1737bfb:6348376] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/cmds/modules/cp/cp.c
r1737bfb r6348376 33 33 #include <str.h> 34 34 #include <fcntl.h> 35 #include <sys/stat.h>36 #include <dirent.h>37 35 #include "config.h" 38 36 #include "util.h" … … 57 55 }; 58 56 59 typedef enum {60 TYPE_NONE,61 TYPE_FILE,62 TYPE_DIR63 } dentry_type_t;64 65 static int64_t copy_file(const char *src, const char *dest,66 size_t blen, int vb);67 68 /** Get the type of a directory entry.69 *70 * @param path Path of the directory entry.71 *72 * @return TYPE_DIR if the dentry is a directory.73 * @return TYPE_FILE if the dentry is a file.74 * @return TYPE_NONE if the dentry does not exists.75 */76 static dentry_type_t get_type(const char *path)77 {78 struct stat s;79 80 int r = stat(path, &s);81 82 if (r)83 return TYPE_NONE;84 else if (s.is_directory)85 return TYPE_DIR;86 else if (s.is_file)87 return TYPE_FILE;88 89 return TYPE_NONE;90 }91 92 57 static int strtoint(const char *s1) 93 58 { … … 102 67 return (int) t1; 103 68 } 104 105 /** Get the last component of a path.106 *107 * e.g. /data/a ---> a108 *109 * @param path Pointer to the path.110 *111 * @return Pointer to the last component or to the path itself.112 */113 static char *get_last_path_component(char *path)114 {115 char *ptr;116 117 ptr = str_rchr(path, '/');118 if (!ptr)119 return path;120 else121 return ptr + 1;122 }123 124 /** Merge two paths together.125 *126 * e.g. (path1 = /data/dir, path2 = a/b) --> /data/dir/a/b127 *128 * @param path1 Path to which path2 will be appended.129 * @param path1_size Size of the path1 buffer.130 * @param path2 Path that will be appended to path1.131 */132 static void merge_paths(char *path1, size_t path1_size, char *path2)133 {134 const char *delim = "/";135 136 str_rtrim(path1, '/');137 str_append(path1, path1_size, delim);138 str_append(path1, path1_size, path2);139 }140 141 static int64_t do_copy(const char *src, const char *dest,142 size_t blen, int vb, int recursive, int force)143 {144 int r = -1;145 char dest_path[PATH_MAX];146 char src_path[PATH_MAX];147 DIR *dir = NULL;148 struct dirent *dp;149 150 dentry_type_t src_type = get_type(src);151 dentry_type_t dest_type = get_type(dest);152 153 const size_t src_len = str_size(src);154 155 if (src_type == TYPE_FILE) {156 char *src_fname;157 158 /* Initialize the src_path with the src argument */159 str_cpy(src_path, src_len + 1, src);160 str_rtrim(src_path, '/');161 162 /* Get the last component name from the src path */163 src_fname = get_last_path_component(src_path);164 165 /* Initialize dest_path with the dest argument */166 str_cpy(dest_path, PATH_MAX, dest);167 168 if (dest_type == TYPE_DIR) {169 /* e.g. cp file_name /data */170 /* e.g. cp file_name /data/ */171 172 /* dest is a directory,173 * append the src filename to it.174 */175 merge_paths(dest_path, PATH_MAX, src_fname);176 dest_type = get_type(dest_path);177 } else if (dest_type == TYPE_NONE) {178 if (dest_path[str_size(dest_path) - 1] == '/') {179 /* e.g. cp /textdemo /data/dirnotexists/ */180 181 printf("The dest directory %s does not exists",182 dest_path);183 goto exit;184 }185 }186 187 if (dest_type == TYPE_DIR) {188 printf("Cannot overwrite existing directory %s\n",189 dest_path);190 goto exit;191 } else if (dest_type == TYPE_FILE) {192 /* e.g. cp file_name existing_file */193 194 /* dest already exists, if force is set we will195 * try to remove it.196 */197 if (force) {198 if (unlink(dest_path)) {199 printf("Unable to remove %s\n",200 dest_path);201 goto exit;202 }203 } else {204 printf("file already exists: %s\n", dest_path);205 goto exit;206 }207 }208 209 /* call copy_file and exit */210 r = (copy_file(src, dest_path, blen, vb) < 0);211 212 } else if (src_type == TYPE_DIR) {213 /* e.g. cp -r /x/srcdir /y/destdir/ */214 215 if (!recursive) {216 printf("Cannot copy the %s directory without the "217 "-r option\n", src);218 goto exit;219 } else if (dest_type == TYPE_FILE) {220 printf("Cannot overwrite a file with a directory\n");221 goto exit;222 }223 224 char *src_dirname;225 226 /* Initialize src_path with the content of src */227 str_cpy(src_path, src_len + 1, src);228 str_rtrim(src_path, '/');229 230 src_dirname = get_last_path_component(src_path);231 232 str_cpy(dest_path, PATH_MAX, dest);233 234 switch (dest_type) {235 case TYPE_DIR:236 if (str_cmp(src_dirname, "..") &&237 str_cmp(src_dirname, ".")) {238 /* The last component of src_path is239 * not '.' or '..'240 */241 merge_paths(dest_path, PATH_MAX, src_dirname);242 243 if (mkdir(dest_path, 0) == -1) {244 printf("Unable to create "245 "dest directory %s\n", dest_path);246 goto exit;247 }248 }249 break;250 default:251 case TYPE_NONE:252 /* dest does not exists, this means the user wants253 * to specify the name of the destination directory254 *255 * e.g. cp -r /src /data/new_dir_src256 */257 if (mkdir(dest_path, 0)) {258 printf("Unable to create "259 "dest directory %s\n", dest_path);260 goto exit;261 }262 break;263 }264 265 dir = opendir(src);266 if (!dir) {267 /* Something strange is happening... */268 printf("Unable to open src %s directory\n", src);269 goto exit;270 }271 272 /* Copy every single directory entry of src into the273 * destination directory.274 */275 while ((dp = readdir(dir))) {276 struct stat src_s;277 struct stat dest_s;278 279 char src_dent[PATH_MAX];280 char dest_dent[PATH_MAX];281 282 str_cpy(src_dent, PATH_MAX, src);283 merge_paths(src_dent, PATH_MAX, dp->d_name);284 285 str_cpy(dest_dent, PATH_MAX, dest_path);286 merge_paths(dest_dent, PATH_MAX, dp->d_name);287 288 /* Check if we are copying a directory into itself */289 stat(src_dent, &src_s);290 stat(dest_path, &dest_s);291 292 if (dest_s.index == src_s.index &&293 dest_s.fs_handle == src_s.fs_handle) {294 printf("Cannot copy a directory "295 "into itself\n");296 goto exit;297 }298 299 if (vb)300 printf("copy %s %s\n", src_dent, dest_dent);301 302 /* Recursively call do_copy() */303 r = do_copy(src_dent, dest_dent, blen, vb, recursive,304 force);305 if (r)306 goto exit;307 308 }309 } else310 printf("Unable to open source file %s\n", src);311 312 exit:313 if (dir)314 closedir(dir);315 return r;316 }317 318 69 319 70 static int64_t copy_file(const char *src, const char *dest, … … 376 127 static char helpfmt[] = 377 128 "Usage: %s [options] <source> <dest>\n" 378 "Options: \n"129 "Options: (* indicates not yet implemented)\n" 379 130 " -h, --help A short option summary\n" 380 131 " -v, --version Print version information and exit\n" 381 " -V, --verbose Be annoyingly noisy about what's being done\n" 382 " -f, --force Do not complain when <dest> exists\n" 383 " -r, --recursive Copy entire directories\n" 384 " -b, --buffer ## Set the read buffer size to ##\n"; 132 "* -V, --verbose Be annoyingly noisy about what's being done\n" 133 "* -f, --force Do not complain when <dest> exists\n" 134 "* -r, --recursive Copy entire directories\n" 135 " -b, --buffer ## Set the read buffer size to ##\n" 136 "Currently, %s is under development, some options may not work.\n"; 385 137 if (level == HELP_SHORT) { 386 138 printf("`%s' copies files and directories\n", cmdname); 387 139 } else { 388 140 help_cmd_cp(HELP_SHORT); 389 printf(helpfmt, cmdname );141 printf(helpfmt, cmdname, cmdname); 390 142 } 391 143 … … 396 148 { 397 149 unsigned int argc, verbose = 0; 398 int buffer = 0, recursive = 0; 399 int force = 0; 150 int buffer = 0; 400 151 int c, opt_ind; 401 152 int64_t ret; … … 416 167 break; 417 168 case 'f': 418 force = 1;419 169 break; 420 170 case 'r': 421 recursive = 1;422 171 break; 423 172 case 'b': … … 445 194 } 446 195 447 ret = do_copy(argv[optind], argv[optind + 1], buffer, verbose, 448 recursive, force); 449 450 if (ret == 0) 196 ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose); 197 198 if (verbose) 199 printf("%" PRId64 " bytes copied\n", ret); 200 201 if (ret >= 0) 451 202 return CMD_SUCCESS; 452 203 else
Note:
See TracChangeset
for help on using the changeset viewer.