• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

copy_dir.c

Go to the documentation of this file.
00001 
00002 /****************************************************************************
00003  *
00004  * MODULE:       GRASS GIS library - copy_dir.c
00005  * AUTHOR(S):    Huidae Cho
00006  * PURPOSE:      Function to recursively copy a directory
00007  * COPYRIGHT:    (C) 2008 by the GRASS Development Team
00008  *
00009  * NOTE:         Extracted from general/manage/lib/do_copy.c
00010  *
00011  *               This program is free software under the GNU General Public
00012  *               License (>=v2). Read the file COPYING that comes with GRASS
00013  *               for details.
00014  *
00015  *****************************************************************************/
00016 
00017 #include <stdio.h>
00018 #include <errno.h>
00019 #include <string.h>
00020 
00021 #include <grass/gis.h>
00022 
00023 #include <fcntl.h>
00024 #include <unistd.h>
00025 #include <dirent.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 
00029 /* RULE:
00030  * 1. If destination does not exist, copy source to destination as expected.
00031  * 2. If destination already exists and it's a file, destination will be
00032  *    deleted first and apply RULE 1.
00033  * 3. If destination already exists which is a directory and source is a file,
00034  *    try to copy source to destination directory.
00035  * 4. If destination already exists which is a directory and source is also a
00036  *    directory, try to copy all contents in source to destination directory.
00037  *
00038  * This rule is designed according to general/manage/lib/copy.sh.
00039  *
00040  * POSSIBLE CASES:
00041  * if src is a file:
00042  *      if dst does not exist:
00043  *              copy src to dst                         RULE 1
00044  *      if dst is a file:
00045  *              delete dst and copy src to dst          RULE 2
00046  *      if dst is a directory:
00047  *              try recursive_copy(src, dst/src)        RULE 3
00048  * if src is a directory:
00049  *      if dst does not exist:
00050  *              copy src to dst                         RULE 1
00051  *      if dst is a file:
00052  *              delete dst and copy src to dst          RULE 2
00053  *      if dst is a directory:
00054  *              try                                     RULE 4
00055  *              for i in `ls src`
00056  *              do
00057  *                      recursive_copy(src/$i, dst/$i)
00058  *              done
00059  *
00060  * RETURN: 0 if successful, otherwise 1
00061  */
00062 
00063 int G_recursive_copy(const char *src, const char *dst)
00064 {
00065     DIR *dirp;
00066     struct stat sb;
00067 
00068     if (G_lstat(src, &sb) < 0)
00069         return 1;
00070 
00071     /* src is a file */
00072     if (!S_ISDIR(sb.st_mode)) {
00073         char buf[4096];
00074         int fd, fd2;
00075         size_t len, len2;
00076 
00077         if (G_lstat(dst, &sb) == 0 && S_ISDIR(sb.st_mode)) {
00078             char path[GPATH_MAX];
00079             const char *p = strrchr(src, '/');
00080 
00081             /* src => dst/src */
00082             sprintf(path, "%s/%s", dst, (p ? p + 1 : src));
00083             return G_recursive_copy(src, path);
00084         }
00085 
00086         /* src => dst */
00087         if ((fd = open(src, O_RDONLY)) < 0)
00088             return 1;
00089 
00090         if ((fd2 =
00091              open(dst, O_CREAT | O_TRUNC | O_WRONLY,
00092                   sb.st_mode & 0777)) < 0) {
00093             close(fd);
00094             return 1;
00095         }
00096 
00097         while ((len = read(fd, buf, sizeof(buf))) > 0) {
00098             while (len && (len2 = write(fd2, buf, len)) >= 0)
00099                 len -= len2;
00100         }
00101 
00102         close(fd);
00103         close(fd2);
00104 
00105         return 0;
00106     }
00107 
00108     /* src is a directory */
00109     if (G_lstat(dst, &sb) < 0) {
00110         if (G_mkdir(dst))
00111             return 1;
00112     }
00113     else
00114         /* if dst already exists and it's a file, try to remove it */
00115     if (!S_ISDIR(sb.st_mode)) {
00116         if (remove(dst) < 0 || G_mkdir(dst) < 0)
00117             return 1;
00118     }
00119 
00120     dirp = opendir(src);
00121     if (!dirp)
00122         return 1;
00123 
00124     for (;;) {
00125         char path[GPATH_MAX], path2[GPATH_MAX];
00126         struct dirent *dp = readdir(dirp);
00127 
00128         if (!dp)
00129             break;
00130 
00131         /* do not copy hidden files */
00132         if (dp->d_name[0] == '.')
00133             continue;
00134 
00135         sprintf(path, "%s/%s", src, dp->d_name);
00136         sprintf(path2, "%s/%s", dst, dp->d_name);
00137 
00138         if (G_recursive_copy(path, path2) != 0)
00139             return 1;
00140     }
00141 
00142     closedir(dirp);
00143 
00144     return 0;
00145 }

Generated on Thu Dec 9 2010 20:46:05 for GRASS Programmer's Manual by  doxygen 1.7.2