2 Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
17 #endif /* HAVE_CONFIG_H */
20 #include <sys/types.h>
35 #include <atalk/adouble.h>
36 #include <atalk/cnid.h>
37 #include <atalk/volinfo.h>
38 #include <atalk/util.h>
41 #define ADv2_DIRNAME ".AppleDouble"
51 static char *netatalk_dirs[] = {
59 Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
60 Returns pointer to name or NULL.
62 static const char *check_netatalk_dirs(const char *name)
66 for (c=0; netatalk_dirs[c]; c++) {
67 if ((strcmp(name, netatalk_dirs[c])) == 0)
68 return netatalk_dirs[c];
74 static void usage_cp(void)
77 "Usage: ad cp [-R [-L | -P]] [-pv] <source_file> <target_file>\n"
78 "Usage: ad cp [-R [-L | -P]] [-pv] <source_file [source_file ...]> <target_directory>\n"
82 static int ad_cp_copy(const afpvol_t *srcvol, const afpvol_t *dstvol,
83 char *srcfile, char *dstfile, struct stat *st)
85 printf("copy: '%s' -> '%s'\n", srcfile, dstfile);
89 static int ad_cp_r(const afpvol_t *srcvol, const afpvol_t *dstvol, char *srcdir, char *dstdir)
91 int ret = 0, dirprinted = 0, dirempty;
92 static char srcpath[MAXPATHLEN+1];
93 static char dstpath[MAXPATHLEN+1];
97 static struct stat st; /* Save some stack space */
99 strlcat(srcpath, srcdir, sizeof(srcpath));
100 strlcat(dstpath, dstdir, sizeof(dstpath));
102 if ((dp = opendir (srcdir)) == NULL) {
103 perror("Couldn't opendir .");
107 /* First run: copy files */
108 while ((ep = readdir (dp))) {
109 /* Check if its "." or ".." */
110 if (DIR_DOT_OR_DOTDOT(ep->d_name))
113 /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
114 if ((check_netatalk_dirs(ep->d_name)) != NULL)
117 if (lstat(ep->d_name, &st) < 0) {
118 perror("Can't stat");
122 /* Build paths, copy, strip name */
123 strlcat(srcpath, "/", sizeof(srcpath));
124 strlcat(dstpath, "/", sizeof(dstpath));
125 strlcat(srcpath, ep->d_name, sizeof(srcpath));
126 strlcat(dstpath, ep->d_name, sizeof(dstpath));
128 ret = ad_cp_copy(srcvol, dstvol, srcpath, dstpath, &st);
130 if ((tmp = strrchr(srcpath, '/')))
132 if ((tmp = strrchr(dstpath, '/')))
139 /* Second run: recurse to dirs */
141 while ((ep = readdir (dp))) {
142 /* Check if its "." or ".." */
143 if (DIR_DOT_OR_DOTDOT(ep->d_name))
146 /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
147 if (check_netatalk_dirs(ep->d_name) != NULL)
150 if (lstat(ep->d_name, &st) < 0) {
151 perror("Can't stat");
156 if (S_ISDIR(st.st_mode)) {
157 strlcat(srcpath, "/", sizeof(srcpath));
158 strlcat(dstpath, "/", sizeof(dstpath));
159 ret = ad_cp_r(srcvol, dstvol, ep->d_name, ep->d_name);
169 if ((tmp = strrchr(srcpath, '/')))
171 if ((tmp = strrchr(dstpath, '/')))
177 int ad_cp(int argc, char **argv)
185 char *srcfile = NULL;
187 char *dstfile = NULL;
189 char path[MAXPATHLEN+1];
192 while ((c = getopt(argc, argv, ":npvLPR")) != -1) {
220 /* How many pathnames do we have */
221 numpaths = argc - optind;
222 printf("Number of paths: %u\n", numpaths);
228 while ( argv[argc-1][(strlen(argv[argc-1]) - 1)] == '/')
229 argv[argc-1][(strlen(argv[argc-1]) - 1)] = 0;
230 printf("Destination is: %s\n", argv[argc-1]);
232 /* Create vol for destination */
233 newvol(argv[argc-1], &dstvol);
236 /* Case 1: 2 paths */
237 if (stat(argv[optind], &sst) != 0)
239 if (S_ISREG(sst.st_mode)) {
240 /* Either file to file or file to dir copy */
241 newvol(argv[optind], &srcvol);
242 ad_cp_copy(&srcvol, &dstvol, srcfile, path, &sst);
246 } else if (S_ISDIR(sst.st_mode)) {
247 /* dir to dir copy. Check if -R is requested */
255 /* Case 2: >2 paths */
256 while (optind < (argc-1)) {
257 printf("Source is: %s\n", argv[optind]);
258 newvol(argv[optind], &srcvol);
259 if (stat(argv[optind], &sst) != 0)
261 if (S_ISDIR(sst.st_mode)) {
262 /* Source is a directory */
264 printf("Source %s is a directory\n", argv[optind]);
267 srcdir = argv[optind];
268 dstdir = argv[argc-1];
270 ad_cp_r(&srcvol, &dstvol, srcdir, dstdir);
273 /* Source is a file */
274 srcfile = argv[optind];
275 if (numpaths != 2 && !dstdir) {
280 strlcat(path, dstdir, sizeof(path));
281 basenametmp = strdup(srcfile);
282 strlcat(path, basename(basenametmp), sizeof(path));
284 printf("%s %s\n", srcfile, path);
285 if (ad_cp_copy(&srcvol, &dstvol, srcfile, path, &sst) != 0) {
294 } /* else (numpath>2) */