GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
copy_dir.c
Go to the documentation of this file.
1 
2 /****************************************************************************
3  *
4  * MODULE: GRASS GIS library - copy_dir.c
5  * AUTHOR(S): Huidae Cho
6  * PURPOSE: Function to recursively copy a directory
7  * COPYRIGHT: (C) 2008 by the GRASS Development Team
8  *
9  * NOTE: Extracted from general/manage/lib/do_copy.c
10  *
11  * This program is free software under the GNU General Public
12  * License (>=v2). Read the file COPYING that comes with GRASS
13  * for details.
14  *
15  *****************************************************************************/
16 
17 #include <stdio.h>
18 #include <errno.h>
19 #include <string.h>
20 
21 #include <grass/gis.h>
22 
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <dirent.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 
29 /* RULE:
30  * 1. If destination does not exist, copy source to destination as expected.
31  * 2. If destination already exists and it's a file, destination will be
32  * deleted first and apply RULE 1.
33  * 3. If destination already exists which is a directory and source is a file,
34  * try to copy source to destination directory.
35  * 4. If destination already exists which is a directory and source is also a
36  * directory, try to copy all contents in source to destination directory.
37  *
38  * This rule is designed according to general/manage/lib/copy.sh.
39  *
40  * POSSIBLE CASES:
41  * if src is a file:
42  * if dst does not exist:
43  * copy src to dst RULE 1
44  * if dst is a file:
45  * delete dst and copy src to dst RULE 2
46  * if dst is a directory:
47  * try recursive_copy(src, dst/src) RULE 3
48  * if src is a directory:
49  * if dst does not exist:
50  * copy src to dst RULE 1
51  * if dst is a file:
52  * delete dst and copy src to dst RULE 2
53  * if dst is a directory:
54  * try RULE 4
55  * for i in `ls src`
56  * do
57  * recursive_copy(src/$i, dst/$i)
58  * done
59  *
60  * RETURN: 0 if successful, otherwise 1
61  */
62 
63 int G_recursive_copy(const char *src, const char *dst)
64 {
65  DIR *dirp;
66  struct stat sb;
67 
68  if (G_lstat(src, &sb) < 0)
69  return 1;
70 
71  /* src is a file */
72  if (!S_ISDIR(sb.st_mode)) {
73  char buf[4096];
74  int fd, fd2;
75  size_t len, len2;
76 
77  if (G_lstat(dst, &sb) == 0 && S_ISDIR(sb.st_mode)) {
78  char path[GPATH_MAX];
79  const char *p = strrchr(src, '/');
80 
81  /* src => dst/src */
82  sprintf(path, "%s/%s", dst, (p ? p + 1 : src));
83  return G_recursive_copy(src, path);
84  }
85 
86  /* src => dst */
87  if ((fd = open(src, O_RDONLY)) < 0)
88  return 1;
89 
90  if ((fd2 =
91  open(dst, O_CREAT | O_TRUNC | O_WRONLY,
92  sb.st_mode & 0777)) < 0) {
93  close(fd);
94  return 1;
95  }
96 
97  while ((len = read(fd, buf, sizeof(buf))) > 0) {
98  while (len && (len2 = write(fd2, buf, len)) >= 0)
99  len -= len2;
100  }
101 
102  close(fd);
103  close(fd2);
104 
105  return 0;
106  }
107 
108  /* src is a directory */
109  if (G_lstat(dst, &sb) < 0) {
110  if (G_mkdir(dst))
111  return 1;
112  }
113  else
114  /* if dst already exists and it's a file, try to remove it */
115  if (!S_ISDIR(sb.st_mode)) {
116  if (remove(dst) < 0 || G_mkdir(dst) < 0)
117  return 1;
118  }
119 
120  dirp = opendir(src);
121  if (!dirp)
122  return 1;
123 
124  for (;;) {
125  char path[GPATH_MAX], path2[GPATH_MAX];
126  struct dirent *dp = readdir(dirp);
127 
128  if (!dp)
129  break;
130 
131  /* do not copy hidden files */
132  if (dp->d_name[0] == '.')
133  continue;
134 
135  sprintf(path, "%s/%s", src, dp->d_name);
136  sprintf(path2, "%s/%s", dst, dp->d_name);
137 
138  if (G_recursive_copy(path, path2) != 0)
139  return 1;
140  }
141 
142  closedir(dirp);
143 
144  return 0;
145 }
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
DIR * opendir()
int G_mkdir(const char *path)
Creates a new directory.
Definition: paths.c:17
FILE * fd
Definition: g3dcolor.c:368
int G_recursive_copy(const char *src, const char *dst)
Definition: copy_dir.c:63
int G_lstat(const char *file_name, struct stat *buf)
Get file status.
Definition: paths.c:135
dir_entry * readdir()
int stat
Definition: g3dcolor.c:369
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
Definition: g3drange.c:62