1 /*-
2 * Copyright (c) 2000-2005 MAEKAWA Masahide <maekawa@cvsync.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/uio.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36
37 #include <limits.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include "compat_stdbool.h"
42 #include "compat_stdint.h"
43 #include "compat_inttypes.h"
44 #include "compat_limits.h"
45
46 #include "attribute.h"
47 #include "collection.h"
48 #include "cvsync.h"
49 #include "logmsg.h"
50 #include "mdirent.h"
51 #include "network.h"
52 #include "scanfile.h"
53
54 #include "defs.h"
55
56 bool cvscan(struct collection *);
57 void usage(void);
58
59 int
main(int argc,char * argv[])60 main(int argc, char *argv[])
61 {
62 const char *cfname = NULL;
63 struct collection *cls = NULL, *cl, base_cl;
64 struct config *cf;
65 size_t len;
66 int ch, status = EXIT_SUCCESS;
67 bool log_flag = false;
68
69 cl = &base_cl;
70 collection_init(cl);
71
72 while ((ch = getopt(argc, argv, "FLc:f:hlqr:v")) != -1) {
73 switch (ch) {
74 case 'F':
75 if (!cl->cl_symfollow) {
76 usage();
77 /* NOTREACHED */
78 }
79 cl->cl_symfollow = false;
80 break;
81 case 'L':
82 if (cl->cl_errormode != CVSYNC_ERRORMODE_UNSPEC) {
83 usage();
84 /* NOTREACHED */
85 }
86 cl->cl_errormode = CVSYNC_ERRORMODE_FIXUP;
87 break;
88 case 'c':
89 if (cfname != NULL) {
90 usage();
91 /* NOTREACHED */
92 }
93 cfname = optarg;
94 break;
95 case 'f':
96 if (strlen(cl->cl_scan_name) != 0) {
97 usage();
98 /* NOTREACHED */
99 }
100 len = strlen(optarg);
101 if (len >= sizeof(cl->cl_scan_name)) {
102 usage();
103 /* NOTREACHED */
104 }
105 (void)memcpy(cl->cl_scan_name, optarg, len);
106 cl->cl_scan_name[len] = '\0';
107 break;
108 case 'h':
109 usage();
110 /* NOTREACHED */
111 case 'l':
112 if (cl->cl_errormode != CVSYNC_ERRORMODE_UNSPEC) {
113 usage();
114 /* NOTREACHED */
115 }
116 cl->cl_errormode = CVSYNC_ERRORMODE_IGNORE;
117 break;
118 case 'q':
119 if (log_flag) {
120 usage();
121 /* NOTREACHED */
122 }
123 logmsg_quiet = true;
124 log_flag = true;
125 break;
126 case 'r':
127 if (strlen(cl->cl_release) != 0) {
128 usage();
129 /* NOTREACHED */
130 }
131 len = strlen(optarg);
132 if (len >= sizeof(cl->cl_release)) {
133 usage();
134 /* NOTREACHED */
135 }
136 (void)memcpy(cl->cl_release, optarg, len);
137 cl->cl_release[len] = '\0';
138 break;
139 case 'v':
140 if (log_flag) {
141 usage();
142 /* NOTREACHED */
143 }
144 logmsg_detail = true;
145 log_flag = true;
146 break;
147 default:
148 usage();
149 /* NOTREACHED */
150 }
151 }
152 argc -= optind;
153 argv += optind;
154
155 if (cl->cl_errormode == CVSYNC_ERRORMODE_UNSPEC)
156 cl->cl_errormode = CVSYNC_ERRORMODE_ABORT;
157
158 if (!cvsync_init())
159 exit(EXIT_FAILURE);
160
161 if (cfname == NULL) {
162 if (argc != 1) {
163 usage();
164 /* NOTREACHED */
165 }
166 if (!collection_set_default(cl, argv[0]))
167 exit(EXIT_FAILURE);
168 if (strlen(cl->cl_scan_name) == 0) {
169 logmsg_err("Not specified the output file.");
170 exit(EXIT_FAILURE);
171 }
172 if (!cvscan(cl))
173 status = EXIT_FAILURE;
174 } else {
175 if (!collection_set_default(cl, NULL))
176 exit(EXIT_FAILURE);
177
178 if ((cf = config_load(cfname)) == NULL)
179 exit(EXIT_FAILURE);
180
181 switch (argc) {
182 case 0:
183 cls = cf->cf_collections;
184 break;
185 case 1:
186 cls = collection_lookup(cf->cf_collections, argv[0],
187 base_cl.cl_release);
188 if (cls == NULL) {
189 logmsg_err("Not such a collection: %s/%s",
190 argv[0], base_cl.cl_release);
191 config_destroy(cf);
192 exit(EXIT_FAILURE);
193 }
194 if (strlen(cls->cl_scan_name) == 0) {
195 logmsg_err("Not specified the output file.");
196 collection_destroy(cls);
197 config_destroy(cf);
198 exit(EXIT_FAILURE);
199 }
200 break;
201 default:
202 usage();
203 /* NOTREACHED */
204 }
205
206 for (cl = cls ; cl != NULL ; cl = cl->cl_next) {
207 if (!cvscan(cl))
208 status = EXIT_FAILURE;
209 }
210
211 if (argc != 0)
212 collection_destroy(cls);
213 config_destroy(cf);
214 }
215
216 exit(status);
217 /* NOTREACHED */
218 }
219
220 bool
cvscan(struct collection * cl)221 cvscan(struct collection *cl)
222 {
223 struct scanfile_create_args sca;
224 struct mdirent_args mda;
225
226 if (strlen(cl->cl_scan_name) == 0)
227 return (true);
228 if ((cl->cl_super != NULL) &&
229 (strcmp(cl->cl_super->cl_scan_name, cl->cl_scan_name) == 0)) {
230 return (true);
231 }
232
233 logmsg("Scanfile: name %s, release %s, prefix %s", cl->cl_name,
234 cl->cl_release, cl->cl_prefix);
235
236 mda.mda_errormode = cl->cl_errormode;
237 mda.mda_symfollow = cl->cl_symfollow;
238 mda.mda_remove = false;
239
240 sca.sca_name = cl->cl_scan_name;
241 sca.sca_prefix = cl->cl_prefix;
242 sca.sca_release = cl->cl_release;
243 sca.sca_rprefix = cl->cl_rprefix;
244 sca.sca_rprefixlen = cl->cl_rprefixlen;
245 sca.sca_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
246 sca.sca_mdirent_args = &mda;
247 sca.sca_umask = cl->cl_umask;
248
249 if (!scanfile_create(&sca))
250 return (false);
251
252 logmsg("Finished successfully");
253
254 return (true);
255 }
256
257 void
usage(void)258 usage(void)
259 {
260 logmsg_err("Usage: cvscan [-hqv] [-r <release>] -c <file> [<name>]\n"
261 " cvscan [-FLhlqv] [-r <release>] -f <file> "
262 "<directory>");
263 exit(EXIT_FAILURE);
264 }
265