1/* vi: set sw=4 ts=4: */ 2/* 3 * Mini cp implementation for busybox 4 * 5 * 6 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include <sys/types.h> 25#include <sys/stat.h> 26#include <unistd.h> 27#include <fcntl.h> 28#include <utime.h> 29#include <errno.h> 30#include <dirent.h> 31#include <stdlib.h> 32 33#include "busybox.h" 34 35extern int cp_main(int argc, char **argv) 36{ 37 int status = 0; 38 int opt; 39 int flags = 0; 40 int i; 41 42 while ((opt = getopt(argc, argv, "adfipR")) != -1) 43 switch (opt) { 44 case 'a': 45 flags |= FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR; 46 /* fallthrough */ 47 case 'd': 48 flags |= FILEUTILS_PRESERVE_SYMLINKS; 49 break; 50 case 'f': 51 flags |= FILEUTILS_FORCE; 52 break; 53 case 'i': 54 flags |= FILEUTILS_INTERACTIVE; 55 break; 56 case 'p': 57 flags |= FILEUTILS_PRESERVE_STATUS; 58 break; 59 case 'R': 60 flags |= FILEUTILS_RECUR; 61 break; 62 default: 63 show_usage(); 64 } 65 66 if (optind + 2 > argc) 67 show_usage(); 68 69 /* If there are only two arguments and... */ 70 if (optind + 2 == argc) { 71 struct stat source_stat; 72 struct stat dest_stat; 73 int source_exists = 1; 74 int dest_exists = 1; 75 76 if (((flags & FILEUTILS_PRESERVE_SYMLINKS) && 77 lstat(argv[optind], &source_stat) < 0) || 78 (!(flags & FILEUTILS_PRESERVE_SYMLINKS) && 79 stat(argv[optind], &source_stat))) { 80 if (errno != ENOENT) 81 perror_msg_and_die("unable to stat `%s'", argv[optind]); 82 source_exists = 0; 83 } 84 85 if (stat(argv[optind + 1], &dest_stat) < 0) { 86 if (errno != ENOENT) 87 perror_msg_and_die("unable to stat `%s'", argv[optind + 1]); 88 dest_exists = 0; 89 } 90 91 /* ...if neither is a directory or... */ 92 if (((!source_exists || !S_ISDIR(source_stat.st_mode)) && 93 (!dest_exists || !S_ISDIR(dest_stat.st_mode))) || 94 /* ...recursing, the first is a directory, and the 95 * second doesn't exist, then... */ 96 ((flags & FILEUTILS_RECUR) && S_ISDIR(source_stat.st_mode) && 97 !dest_exists)) { 98 /* ...do a simple copy. */ 99 if (copy_file(argv[optind], argv[optind + 1], flags) < 0) 100 status = 1; 101 return status; 102 } 103 } 104 105 for (i = optind; i < argc - 1; i++) { 106 char *dest = concat_path_file(argv[argc - 1], 107 get_last_path_component(argv[i])); 108 if (copy_file(argv[i], dest, flags) < 0) 109 status = 1; 110 free(dest); 111 } 112 113 return status; 114} 115