#include #include #include #include #include #include #include #include #include #include "list.h" #ifdef __MINGW32__ #define mkdir(name, mode) mkdir(name) #define lstat(path, sb) stat(path, sb) #endif static int recursive_copy(const char *src, const char *dst); /* * returns 0 - success * 1 - error */ int do_copy (int n, char *old, char *mapset, char *new) { int i, ret, len; char path[1024], path2[1024]; int result = 0; G_debug (3, "Copy %s", list[n].alias ); fprintf (stdout,"COPY [%s] to current mapset as [%s]\n", G_fully_qualified_name(old, mapset), new); len = get_description_len(n); hold_signals(1); if ( strcmp(list[n].alias, "vect") == 0 ) { ret = Vect_copy ( old, mapset, new, stderr ); if ( ret == -1 ) { G_warning ("Cannot copy %s to current mapset as %s", G_fully_qualified_name(old, mapset), new ); result = 1; } } else { for (i = 0; i < list[n].nelem; i++) { fprintf (stdout," %-*s ", len, list[n].desc[i]); fflush (stdout); G__make_mapset_element (list[n].element[i]); G__file_name (path, list[n].element[i], old, mapset); if (access (path, 0) != 0) { G_remove (list[n].element[i], new); fprintf (stdout,"MISSING\n"); continue; } G__file_name (path2, list[n].element[i], new, G_mapset()); if ( recursive_copy(path, path2) == 1 ) { result = 1; } fprintf (stdout,"\n"); } } /* special case: remove (yes, remove) the secondary color table, if it exists */ if (strcmp (list[n].element[0], "cell") == 0) { char colr2[50]; sprintf (colr2, "colr2/%s", G_mapset()); G_remove (colr2, new); } hold_signals(0); return result; } /* RULE: * 1. If destination does not exist, copy source to destination as expected. * 2. If destination already exists and it's a file, destination will be * deleted first and apply RULE 1. * 3. If destination already exists which is a directory and source is a file, * try to copy source to destination directory. * 4. If destination already exists which is a directory and source is also a * directory, try to copy all contents in source to destination directory. * * This rule is designed according to general/manage/lib/copy.sh. * * POSSIBLE CASES: * if src is a file: * if dst does not exist: * copy src to dst RULE 1 * if dst is a file: * delete dst and copy src to dst RULE 2 * if dst is a directory: * try recursive_copy(src, dst/src) RULE 3 * if src is a directory: * if dst does not exist: * copy src to dst RULE 1 * if dst is a file: * delete dst and copy src to dst RULE 2 * if dst is a directory: * try RULE 4 * for i in `ls src` * do * recursive_copy(src/$i, dst/$i) * done * * RETURN: 0 if successful, otherwise 1 */ static int recursive_copy(const char *src, const char *dst) { DIR *dirp; struct dirent *dp; struct stat sb; char buf[1024], buf2[1024]; int fd, fd2; size_t len, len2; mode_t mode; if(lstat(src, &sb)) return 1; /* src is a file */ if(!S_ISDIR((mode = sb.st_mode))) { if(!lstat(dst, &sb) && S_ISDIR(sb.st_mode)) { const char *p = strrchr(src, '/'); /* src => dst/src */ sprintf(buf, "%s/%s", dst, (p?p+1:src)); return recursive_copy(src, buf); } /* src => dst */ if((fd = open(src, O_RDONLY)) < 0) return 1; if((fd2 = open(dst, O_CREAT|O_TRUNC|O_WRONLY, mode & 0777)) < 0) { close(fd); return 1; } while((len = read(fd, buf, 1024)) > 0) { while(len && (len2 = write(fd2, buf, len)) >= 0) len -= len2; } close(fd); close(fd2); return 0; } /* src is a directory */ if(lstat(dst, &sb)) { if(mkdir(dst, mode & 0777)) return 1; }else /* if dst already exists and it's a file, try to remove it */ if(!S_ISDIR(sb.st_mode)) { if(remove(dst) || mkdir(dst, mode & 0777)) return 1; } if((dirp = opendir(src)) == NULL) return 1; while((dp = readdir(dirp)) != NULL) { /* do not copy hidden files */ if(dp->d_name[0] == '.') continue; sprintf(buf, "%s/%s", src, dp->d_name); sprintf(buf2, "%s/%s", dst, dp->d_name); if(recursive_copy(buf, buf2)) return 1; } closedir(dirp); return 0; }