GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
copy_dir.c
Go to the documentation of this file.
1/*!
2 * \file lib/gis/copy_dir.c
3 *
4 * \brief GIS Library - function to recursively copy a directory
5 *
6 * Extracted from general/manage/lib/do_copy.c
7 *
8 * SPDX-FileCopyrightText: 2008-2015 GRASS Development Team
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 *
11 * \author Huidae Cho
12 */
13
14#include <stdio.h>
15#include <errno.h>
16#include <string.h>
17
18#include <grass/gis.h>
19
20#include <fcntl.h>
21#include <unistd.h>
22#include <dirent.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25
26/*!
27 * \brief Copy recursively source directory to destination directory
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 * \verbatim
42 * if src is a file:
43 * if dst does not exist:
44 * copy src to dst RULE 1
45 * if dst is a file:
46 * delete dst and copy src to dst RULE 2
47 * if dst is a directory:
48 * try recursive_copy(src, dst/src) RULE 3
49 * if src is a directory:
50 * if dst does not exist:
51 * copy src to dst RULE 1
52 * if dst is a file:
53 * delete dst and copy src to dst RULE 2
54 * if dst is a directory:
55 * try RULE 4
56 * for i in `ls src`
57 * do
58 * recursive_copy(src/$i, dst/$i)
59 * done
60 * \endverbatim
61 *
62 * \param src source directory
63 * \param dst destination directory
64 *
65 * \return 0 if successful, otherwise 1
66 */
67int G_recursive_copy(const char *src, const char *dst)
68{
69 DIR *dirp;
70 struct stat sb;
71
72 if (G_lstat(src, &sb) < 0)
73 return 1;
74
75 /* src is a file */
76 if (!S_ISDIR(sb.st_mode)) {
77 char buf[4096];
78 int fd, fd2;
79 ssize_t len, len2;
80
81 if (G_lstat(dst, &sb) == 0 && S_ISDIR(sb.st_mode)) {
82 char path[GPATH_MAX];
83 const char *p = strrchr(src, '/');
84
85 /* src => dst/src */
86 snprintf(path, sizeof(path), "%s/%s", dst, (p ? p + 1 : src));
87 return G_recursive_copy(src, path);
88 }
89
90 /* src => dst */
91 if ((fd = open(src, O_RDONLY)) < 0)
92 return 1;
93
94 if ((fd2 = open(dst, O_CREAT | O_TRUNC | O_WRONLY, sb.st_mode & 0777)) <
95 0) {
96 close(fd);
97 return 1;
98 }
99
100 while ((len = read(fd, buf, sizeof(buf))) > 0) {
101 while ((len > 0) && (len2 = write(fd2, buf, (size_t)len)) >= 0)
102 len -= len2;
103 }
104
105 close(fd);
106 close(fd2);
107
108 return 0;
109 }
110
111 /* src is a directory */
112 if (G_lstat(dst, &sb) < 0) {
113 if (G_mkdir(dst))
114 return 1;
115 }
116 else
117 /* if dst already exists and it's a file, try to remove it */
118 if (!S_ISDIR(sb.st_mode)) {
119 if (remove(dst) < 0 || G_mkdir(dst) < 0)
120 return 1;
121 }
122
123 dirp = opendir(src);
124 if (!dirp)
125 return 1;
126
127 for (;;) {
128 char path[GPATH_MAX], path2[GPATH_MAX];
129 struct dirent *dp = readdir(dirp);
130
131 if (!dp)
132 break;
133
134 /* do not copy hidden files */
135 if (dp->d_name[0] == '.')
136 continue;
137
138 snprintf(path, sizeof(path), "%s/%s", src, dp->d_name);
139 snprintf(path2, sizeof(path2), "%s/%s", dst, dp->d_name);
140
141 if (G_recursive_copy(path, path2) != 0) {
142 closedir(dirp);
143 return 1;
144 }
145 }
146
147 closedir(dirp);
148
149 return 0;
150}
int G_recursive_copy(const char *src, const char *dst)
Copy recursively source directory to destination directory.
Definition copy_dir.c:67
int G_lstat(const char *, struct stat *)
Get file status.
Definition paths.c:145
int G_mkdir(const char *)
Creates a new directory.
Definition paths.c:27
struct DIR DIR
Definition dirent.h:18
Header file for msvc/fcntl.c.
#define open
Definition fcntl.h:32
#define GPATH_MAX
Definition gis.h:196
DIR * opendir(const char *name)
Definition msvc/dirent.c:15
struct dirent * readdir(DIR *dir)
Definition msvc/dirent.c:75
int closedir(DIR *dir)
Definition msvc/dirent.c:54
#define S_ISDIR(mode)
Definition stat.h:6
Definition path.h:15
#define read
Definition unistd.h:5
#define close
Definition unistd.h:8
#define write
Definition unistd.h:6