]> arthur.barton.de Git - netatalk.git/blob - bin/cnid/ad_cp.c
Fix dbd vs cnid_dbd locking
[netatalk.git] / bin / cnid / ad_cp.c
1 /* 
2    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
3    
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.
8  
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.
13 */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif /* HAVE_CONFIG_H */
18
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <limits.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <dirent.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30 #include <pwd.h>
31 #include <grp.h>
32 #include <time.h>
33 #include <libgen.h>
34
35 #include <atalk/adouble.h>
36 #include <atalk/cnid.h>
37 #include <atalk/volinfo.h>
38 #include <atalk/util.h>
39 #include "ad.h"
40
41 #define ADv2_DIRNAME ".AppleDouble"
42
43 /* options */
44 static int cp_R;
45 static int cp_L;
46 static int cp_P;
47 static int cp_n;
48 static int cp_p;
49 static int cp_v;
50
51 static char           *netatalk_dirs[] = {
52     ADv2_DIRNAME,
53     ".AppleDB",
54     ".AppleDesktop",
55     NULL
56 };
57
58 /*
59   Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
60   Returns pointer to name or NULL.
61 */
62 static const char *check_netatalk_dirs(const char *name)
63 {
64     int c;
65
66     for (c=0; netatalk_dirs[c]; c++) {
67         if ((strcmp(name, netatalk_dirs[c])) == 0)
68             return netatalk_dirs[c];
69     }
70     return NULL;
71 }
72
73
74 static void usage_cp(void)
75 {
76     printf(
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"
79         );
80 }
81
82 static int ad_cp_copy(const afpvol_t *srcvol, const afpvol_t *dstvol,
83                       char *srcfile, char *dstfile, struct stat *st)
84 {
85     printf("copy: '%s' -> '%s'\n", srcfile, dstfile);
86     return 0;
87 }
88
89 static int ad_cp_r(const afpvol_t *srcvol, const afpvol_t *dstvol, char *srcdir, char *dstdir)
90 {
91     int ret = 0, dirprinted = 0, dirempty;
92     static char srcpath[MAXPATHLEN+1];
93     static char dstpath[MAXPATHLEN+1];
94     char *tmp;
95     DIR *dp = NULL;
96     struct dirent *ep;
97     static struct stat st;      /* Save some stack space */
98
99     strlcat(srcpath, srcdir, sizeof(srcpath));
100     strlcat(dstpath, dstdir, sizeof(dstpath));
101
102     if ((dp = opendir (srcdir)) == NULL) {
103         perror("Couldn't opendir .");
104         return -1;
105     }
106
107     /* First run: copy files */
108     while ((ep = readdir (dp))) {
109         /* Check if its "." or ".." */
110         if (DIR_DOT_OR_DOTDOT(ep->d_name))
111             continue;
112
113         /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
114         if ((check_netatalk_dirs(ep->d_name)) != NULL)
115             continue;
116
117         if (lstat(ep->d_name, &st) < 0) {
118             perror("Can't stat");
119             return -1;
120         }
121
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));
127
128         ret = ad_cp_copy(srcvol, dstvol, srcpath, dstpath, &st);
129
130         if ((tmp = strrchr(srcpath, '/')))
131             *tmp = 0;
132         if ((tmp = strrchr(dstpath, '/')))
133             *tmp = 0;
134
135         if (ret != 0)
136             goto exit;
137     }
138
139     /* Second run: recurse to dirs */
140     rewinddir(dp);
141     while ((ep = readdir (dp))) {
142         /* Check if its "." or ".." */
143         if (DIR_DOT_OR_DOTDOT(ep->d_name))
144             continue;
145         
146         /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
147         if (check_netatalk_dirs(ep->d_name) != NULL)
148             continue;
149         
150         if (lstat(ep->d_name, &st) < 0) {
151             perror("Can't stat");
152             return -1;
153         }
154         
155         /* Recursion */
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);
160         }
161         if (ret != 0)
162             goto exit;
163     }
164
165 exit:
166     if (dp)
167         closedir(dp);
168  
169     if ((tmp = strrchr(srcpath, '/')))
170         *tmp = 0;
171     if ((tmp = strrchr(dstpath, '/')))
172         *tmp = 0;
173
174     return ret;
175 }
176
177 int ad_cp(int argc, char **argv)
178 {
179     int c, numpaths;
180     afpvol_t srcvvol;
181     struct stat sst;
182     struct stat dst;
183     afpvol_t srcvol;
184     afpvol_t dstvol;
185     char *srcfile = NULL;
186     char *srcdir = NULL;    
187     char *dstfile = NULL;
188     char *dstdir = NULL;
189     char path[MAXPATHLEN+1];
190     char *basenametmp;
191
192     while ((c = getopt(argc, argv, ":npvLPR")) != -1) {
193         switch(c) {
194         case 'n':
195             cp_n = 1;
196             break;
197         case 'p':
198             cp_p = 1;
199             break;
200         case 'v':
201             cp_v = 1;
202             break;
203         case 'L':
204             cp_L = 1;
205             break;
206         case 'P':
207             cp_P = 1;
208             break;
209         case 'R':
210             cp_R = 1;
211             break;
212         case ':':
213         case '?':
214             usage_cp();
215             return -1;
216             break;
217         }
218     }
219
220     /* How many pathnames do we have */
221     numpaths = argc - optind;
222     printf("Number of paths: %u\n", numpaths);
223     if (numpaths < 2) {
224         usage_cp();
225         exit(EXIT_FAILURE);
226     }
227
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]);
231
232     /* Create vol for destination */
233     newvol(argv[argc-1], &dstvol);
234
235     if (numpaths == 2) {
236         /* Case 1: 2 paths */
237         if (stat(argv[optind], &sst) != 0)
238             goto next;
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);
243             freevol(&srcvol);
244             freevol(&dstvol);
245             
246         } else if (S_ISDIR(sst.st_mode)) {
247             /* dir to dir copy. Check if -R is requested */
248             if (!cp_R) {
249                 usage_cp();
250                 exit(EXIT_FAILURE);
251             }
252         }
253
254     } else {
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)
260                 goto next;
261             if (S_ISDIR(sst.st_mode)) {
262                 /* Source is a directory */
263                 if (!cp_R) {
264                     printf("Source %s is a directory\n", argv[optind]);
265                     goto next;
266                 }
267                 srcdir = argv[optind];
268                 dstdir = argv[argc-1];
269                 
270                 ad_cp_r(&srcvol, &dstvol, srcdir, dstdir);
271                 freevol(&srcvol);
272             } else {
273                 /* Source is a file */
274                 srcfile = argv[optind];
275                 if (numpaths != 2 && !dstdir) {
276                     usage_cp();
277                     exit(EXIT_FAILURE);
278                 }
279                 path[0] = 0;
280                 strlcat(path, dstdir, sizeof(path));
281                 basenametmp = strdup(srcfile);
282                 strlcat(path, basename(basenametmp), sizeof(path));
283                 free(basenametmp);
284                 printf("%s %s\n", srcfile, path);
285                 if (ad_cp_copy(&srcvol, &dstvol, srcfile, path, &sst) != 0) {
286                     freevol(&srcvol);
287                     freevol(&dstvol);
288                     exit(EXIT_FAILURE);
289                 }
290             } /* else */
291         next:
292             optind++;
293         } /* while */
294     } /* else (numpath>2) */
295
296     freevol(&dstvol);
297
298     return 0;
299
300 }