diff options
author | Eric Andersen <andersen@codepoet.org> | 1999-10-09 00:25:00 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 1999-10-09 00:25:00 +0000 |
commit | f811e07b072600a3784a92e5a1dc8a93dac477eb (patch) | |
tree | 820c6366f8bdacf617a9591cc2ca9dfe107b1fa3 /coreutils/cp.c | |
parent | 8341a1565306a54e685455d19efb0516ad3328a1 (diff) | |
download | busybox-w32-f811e07b072600a3784a92e5a1dc8a93dac477eb.tar.gz busybox-w32-f811e07b072600a3784a92e5a1dc8a93dac477eb.tar.bz2 busybox-w32-f811e07b072600a3784a92e5a1dc8a93dac477eb.zip |
More stuff.
Diffstat (limited to 'coreutils/cp.c')
-rw-r--r-- | coreutils/cp.c | 206 |
1 files changed, 129 insertions, 77 deletions
diff --git a/coreutils/cp.c b/coreutils/cp.c index 078a57c56..797663d2b 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c | |||
@@ -1,89 +1,141 @@ | |||
1 | /* | ||
2 | * Mini cp implementation for busybox | ||
3 | * | ||
4 | * Copyright (C) 1998 by Erik Andersen <andersee@debian.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
1 | #include "internal.h" | 22 | #include "internal.h" |
2 | #include <stdio.h> | 23 | #include <stdio.h> |
3 | #include <sys/stat.h> | 24 | #include <time.h> |
4 | #include <sys/fcntl.h> | 25 | #include <utime.h> |
5 | #include <sys/param.h> | 26 | #include <dirent.h> |
6 | #include <errno.h> | 27 | |
7 | 28 | const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" | |
8 | const char cp_usage[] = "cp [-r] source-file destination-file\n" | 29 | " or: cp [OPTION]... SOURCE... DIRECTORY\n" |
9 | "\t\tcp [-r] source-file [source-file ...] destination-directory\n" | 30 | "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" |
10 | "\n" | 31 | "\n" |
11 | "\tCopy the source files to the destination.\n" | 32 | "\t-a\tsame as -dpR\n" |
12 | "\n" | 33 | "\t-d\tpreserve links\n" |
13 | "\t-r:\tRecursively copy all files and directories\n" | 34 | "\t-p\tpreserve file attributes if possable\n" |
14 | "\t\tunder the argument directory."; | 35 | "\t-R\tcopy directories recursively\n"; |
15 | 36 | ||
16 | extern int | 37 | |
17 | cp_fn(const struct FileInfo * i) | 38 | static int recursiveFlag = FALSE; |
39 | static int followLinks = FALSE; | ||
40 | static int preserveFlag = FALSE; | ||
41 | static const char *srcName; | ||
42 | static const char *destName; | ||
43 | |||
44 | |||
45 | static int fileAction(const char *fileName) | ||
18 | { | 46 | { |
19 | int sourceFd; | 47 | char newdestName[NAME_MAX]; |
20 | int destinationFd; | 48 | strcpy(newdestName, destName); |
21 | const char * destination = i->destination; | 49 | strcat(newdestName, fileName+(strlen(srcName))); |
22 | struct stat destination_stat; | 50 | fprintf(stderr, "A: copying %s to %s\n", fileName, newdestName); |
23 | int status; | 51 | return (copyFile(fileName, newdestName, preserveFlag, followLinks)); |
24 | char buf[8192]; | 52 | } |
25 | char d[PATH_MAX]; | 53 | |
26 | 54 | static int dirAction(const char *fileName) | |
27 | if ( (i->stat.st_mode & S_IFMT) == S_IFDIR ) { | 55 | { |
28 | if ( mkdir(destination, i->stat.st_mode & ~S_IFMT) | 56 | char newdestName[NAME_MAX]; |
29 | != 0 && errno != EEXIST ) { | 57 | struct stat statBuf; |
30 | name_and_error(destination); | 58 | struct utimbuf times; |
31 | return 1; | 59 | |
32 | } | 60 | strcpy(newdestName, destName); |
33 | return 0; | 61 | strcat(newdestName, fileName+(strlen(srcName))); |
62 | if (stat(newdestName, &statBuf)) { | ||
63 | if (mkdir( newdestName, 0777777 ^ umask (0))) { | ||
64 | perror(newdestName); | ||
65 | return( FALSE); | ||
66 | } | ||
34 | } | 67 | } |
35 | if ( (sourceFd = open(i->source, O_RDONLY)) < 0 ) { | 68 | else if (!S_ISDIR (statBuf.st_mode)) { |
36 | name_and_error(i->source); | 69 | fprintf(stderr, "`%s' exists but is not a directory", newdestName); |
37 | return 1; | 70 | return( FALSE); |
38 | } | 71 | } |
39 | if ( stat(destination, &destination_stat) == 0 ) { | 72 | if (preserveFlag==TRUE) { |
40 | if ( i->stat.st_ino == destination_stat.st_ino | 73 | /* Try to preserve premissions, but don't whine on failure */ |
41 | && i->stat.st_dev == destination_stat.st_dev ) { | 74 | if (stat(newdestName, &statBuf)) { |
42 | fprintf(stderr | 75 | perror(newdestName); |
43 | ,"copy of %s to %s would copy file to itself.\n" | 76 | return( FALSE); |
44 | ,i->source | 77 | } |
45 | ,destination); | 78 | chmod(newdestName, statBuf.st_mode); |
46 | close(sourceFd); | 79 | chown(newdestName, statBuf.st_uid, statBuf.st_gid); |
47 | return 1; | 80 | times.actime = statBuf.st_atime; |
48 | } | 81 | times.modtime = statBuf.st_mtime; |
82 | utime(newdestName, ×); | ||
49 | } | 83 | } |
50 | /* | 84 | return TRUE; |
51 | * If the destination is a directory, create a file within it. | 85 | } |
52 | */ | 86 | |
53 | if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) { | 87 | extern int cp_main(int argc, char **argv) |
54 | destination = join_paths( | 88 | { |
55 | d | 89 | |
56 | ,i->destination | 90 | int dirFlag; |
57 | ,&i->source[i->directoryLength]); | 91 | |
58 | 92 | if (argc < 3) { | |
59 | if ( stat(destination, &destination_stat) == 0 ) { | 93 | fprintf(stderr, "Usage: %s", cp_usage); |
60 | if ( i->stat.st_ino == destination_stat.st_ino | 94 | return (FALSE); |
61 | && i->stat.st_dev == destination_stat.st_dev ) { | ||
62 | fprintf(stderr | ||
63 | ,"copy of %s to %s would copy file to itself.\n" | ||
64 | ,i->source | ||
65 | ,destination); | ||
66 | close(sourceFd); | ||
67 | return 1; | ||
68 | } | ||
69 | } | ||
70 | } | 95 | } |
96 | argc--; | ||
97 | argv++; | ||
71 | 98 | ||
72 | destinationFd = creat(destination, i->stat.st_mode & 07777); | 99 | /* Parse any options */ |
100 | while (**argv == '-') { | ||
101 | while (*++(*argv)) | ||
102 | switch (**argv) { | ||
103 | case 'a': | ||
104 | followLinks = TRUE; | ||
105 | preserveFlag = TRUE; | ||
106 | recursiveFlag = TRUE; | ||
107 | break; | ||
108 | case 'd': | ||
109 | followLinks = TRUE; | ||
110 | break; | ||
111 | case 'p': | ||
112 | preserveFlag = TRUE; | ||
113 | break; | ||
114 | case 'R': | ||
115 | recursiveFlag = TRUE; | ||
116 | break; | ||
117 | default: | ||
118 | fprintf(stderr, "Usage: %s\n", cp_usage); | ||
119 | exit(FALSE); | ||
120 | } | ||
121 | argc--; | ||
122 | argv++; | ||
123 | } | ||
124 | |||
125 | |||
126 | destName = argv[argc - 1]; | ||
73 | 127 | ||
74 | while ( (status = read(sourceFd, buf, sizeof(buf))) > 0 ) { | 128 | dirFlag = isDirectory(destName); |
75 | if ( write(destinationFd, buf, status) != status ) { | 129 | |
76 | name_and_error(destination); | 130 | if ((argc > 3) && !dirFlag) { |
77 | close(sourceFd); | 131 | fprintf(stderr, "%s: not a directory\n", destName); |
78 | close(destinationFd); | 132 | return (FALSE); |
79 | return 1; | ||
80 | } | ||
81 | } | 133 | } |
82 | close(sourceFd); | 134 | |
83 | close(destinationFd); | 135 | while (argc-- >= 2) { |
84 | if ( status < 0 ) { | 136 | srcName = *(argv++); |
85 | name_and_error(i->source); | 137 | return recursiveAction(srcName, recursiveFlag, followLinks, |
86 | return 1; | 138 | fileAction, fileAction); |
87 | } | 139 | } |
88 | return 0; | 140 | return( TRUE); |
89 | } | 141 | } |