3 // Copyright (C) 2007 Daniel Hokka Zakrisson
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
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.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include "lib_internal/pathinfo.h"
27 #include "lib_internal/unify.h"
37 #include <sys/param.h>
39 #define ENSC_WRAPPERS_PREFIX "vclone: "
40 #define ENSC_WRAPPERS_UNISTD 1
41 #define ENSC_WRAPPERS_FCNTL 1
42 #define ENSC_WRAPPERS_DIRENT 1
45 #define CMD_HELP 0x8000
46 #define CMD_VERSION 0x8001
56 unsigned int verbosity;
59 static struct WalkdownInfo global_info;
60 static struct Arguments const * global_args;
62 int wrapper_exit_code = 1;
66 { "help", no_argument, 0, CMD_HELP },
67 { "version", no_argument, 0, CMD_VERSION },
73 showHelp(int fd, char const *cmd, int res)
75 VSERVER_DECLARE_CMD(cmd);
77 WRITE_MSG(fd, "Usage:\n ");
80 " <source> <absolute path to destination>\n\n"
81 "Please report bugs to " PACKAGE_BUGREPORT "\n");
89 "vclone " VERSION " -- clones a guest\n"
90 "This program is part of " PACKAGE_STRING "\n\n"
91 "Copyright (C) 2007 Daniel Hokka Zakrisson\n"
92 VERSION_COPYRIGHT_DISCLAIMER);
96 int Global_getVerbosity() {
97 return global_args->verbosity;
100 bool Global_doRenew() {
104 #include "vserver-visitdir.hc"
107 visitDirEntry(struct dirent const *ent)
109 char const * dirname = ent->d_name;
110 if (isDotfile(dirname)) return 0;
113 PathInfo src_path = global_info.state;
114 PathInfo src_d_path = {
118 char path_buf[ENSC_PI_APPSZ(src_path, src_d_path)];
119 struct stat f_stat = { .st_dev = 0 };
121 PathInfo_append(&src_path, &src_d_path, path_buf);
124 if (lstat(dirname, &f_stat)==-1)
125 perror(ENSC_WRAPPERS_PREFIX "lstat()");
127 PathInfo dst_path = global_info.dst;
128 char dst_path_buf[ENSC_PI_APPSZ(dst_path, src_path)];
130 PathInfo_append(&dst_path, &src_path, dst_path_buf);
132 /* skip files that already exist */
133 if (access(dst_path.d, F_OK)!=-1)
135 else if (S_ISREG(f_stat.st_mode) && Unify_isIUnlinkable(src_d_path.d) == unifyBUSY) {
136 Elink(src_d_path.d, dst_path.d);
140 if (!Unify_copy(src_d_path.d, &f_stat, dst_path.d)) {
141 perror(ENSC_WRAPPERS_PREFIX "Unify_copy()");
142 exit(wrapper_exit_code);
146 if (S_ISDIR(f_stat.st_mode))
147 res = visitDir(dirname, &f_stat);
153 int main(int argc, char *argv[])
155 struct Arguments args = {
163 int c = getopt_long(argc, argv, "+",
168 case CMD_HELP : showHelp(1, argv[0], 0);
169 case CMD_VERSION : showVersion();
171 WRITE_MSG(2, "Try '");
172 WRITE_STR(2, argv[0]);
173 WRITE_MSG(2, " --help' for more information.\n");
179 num_args = argc - optind;
181 WRITE_MSG(2, "Source is missing; try '");
182 WRITE_STR(2, argv[0]);
183 WRITE_MSG(2, " --help' for more information.\n");
186 else if (num_args < 2) {
187 WRITE_MSG(2, "Destination is missing; try '");
188 WRITE_STR(2, argv[0]);
189 WRITE_MSG(2, " --help' for more information.\n");
192 else if (num_args > 2) {
193 WRITE_MSG(2, "Too many arguments; try '");
194 WRITE_STR(2, argv[0]);
195 WRITE_MSG(2, " --help' for more information.\n");
198 else if (*argv[optind+1] != '/') {
199 WRITE_MSG(2, "The destination must be an absolute path; try '");
200 WRITE_STR(2, argv[0]);
201 WRITE_MSG(2, " --help' for more information.\n");
204 ENSC_PI_SETSTR(global_info.src, argv[optind]);
205 ENSC_PI_SETSTR(global_info.dst, argv[optind+1]);
207 if (global_args->verbosity>3)
208 WRITE_MSG(1, "Starting to traverse directories...\n");
210 Echdir(global_info.src.d);
211 res = visitDir("/", 0);
213 return res>0 ? 1 : 0;