Bug Summary

File:src/gnu/usr.bin/cvs/src/import.c
Warning:line 1370, column 11
Access to field '_flags' results in a dereference of a null pointer (loaded from variable 'fpuser')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name import.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/cvs/obj/src -resource-dir /usr/local/lib/clang/13.0.0 -D HAVE_CONFIG_H -I . -I /usr/src/gnu/usr.bin/cvs/src -I .. -I . -I /usr/src/gnu/usr.bin/cvs/lib -I /usr/src/gnu/usr.bin/cvs/diff -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.bin/cvs/obj/src -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.bin/cvs/src/import.c
1/*
2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
4 *
5 * You may distribute under the terms of the GNU General Public License as
6 * specified in the README file that comes with the CVS source distribution.
7 *
8 * "import" checks in the vendor release located in the current directory into
9 * the CVS source repository. The CVS vendor branch support is utilized.
10 *
11 * At least three arguments are expected to follow the options:
12 * repository Where the source belongs relative to the CVSROOT
13 * VendorTag Vendor's major tag
14 * VendorReleTag Tag for this particular release
15 *
16 * Additional arguments specify more Vendor Release Tags.
17 */
18
19#include "cvs.h"
20#include "savecwd.h"
21#include <assert.h>
22
23static char *get_comment PROTO((char *user))(char *user);
24static int add_rev PROTO((char *message, RCSNode *rcs, char *vfile,(char *message, RCSNode *rcs, char *vfile, char *vers)
25 char *vers))(char *message, RCSNode *rcs, char *vfile, char *vers);
26static int add_tags PROTO((RCSNode *rcs, char *vfile, char *vtag, int targc,(RCSNode *rcs, char *vfile, char *vtag, int targc, char *targv
[])
27 char *targv[]))(RCSNode *rcs, char *vfile, char *vtag, int targc, char *targv
[])
;
28static int import_descend PROTO((char *message, char *vtag, int targc, char *targv[]))(char *message, char *vtag, int targc, char *targv[]);
29static int import_descend_dir PROTO((char *message, char *dir, char *vtag,(char *message, char *dir, char *vtag, int targc, char *targv
[])
30 int targc, char *targv[]))(char *message, char *dir, char *vtag, int targc, char *targv
[])
;
31static int process_import_file PROTO((char *message, char *vfile, char *vtag,(char *message, char *vfile, char *vtag, int targc, char *targv
[])
32 int targc, char *targv[]))(char *message, char *vfile, char *vtag, int targc, char *targv
[])
;
33static int update_rcs_file PROTO((char *message, char *vfile, char *vtag, int targc,(char *message, char *vfile, char *vtag, int targc, char *targv
[], int inattic)
34 char *targv[], int inattic))(char *message, char *vfile, char *vtag, int targc, char *targv
[], int inattic)
;
35static void add_log PROTO((int ch, char *fname))(int ch, char *fname);
36
37static int repos_len;
38static char *vhead;
39static char *vbranch;
40static FILE *logfp;
41static char *repository;
42static int conflicts;
43static int use_file_modtime;
44static char *keyword_opt = NULL((void*)0);
45
46static const char *const import_usage[] =
47{
48 "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
49 " [-W spec] repository vendor-tag release-tags...\n",
50 "\t-d\tUse the file's modification time as the time of import.\n",
51 "\t-k sub\tSet default RCS keyword substitution mode.\n",
52 "\t-I ign\tMore files to ignore (! to reset).\n",
53 "\t-b bra\tVendor branch id.\n",
54 "\t-m msg\tLog message.\n",
55 "\t-W spec\tWrappers specification line.\n",
56 "(Specify the --help global option for a list of other help options)\n",
57 NULL((void*)0)
58};
59
60int
61import (argc, argv)
62 int argc;
63 char **argv;
64{
65 char *message = NULL((void*)0);
66 char *tmpfile;
67 char *cp;
68 int i, c, msglen, err;
69 List *ulist;
70 Node *p;
71 struct logfile_info *li;
72
73 if (argc == -1)
74 usage (import_usage);
75
76 ign_setup ();
77 wrap_setup ();
78
79 vbranch = xstrdup (CVSBRANCH"1.1.1");
80 optind = 0;
81 while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:")) != -1)
82 {
83 switch (c)
84 {
85 case 'Q':
86 case 'q':
87#ifdef SERVER_SUPPORT1
88 /* The CVS 1.5 client sends these options (in addition to
89 Global_option requests), so we must ignore them. */
90 if (!server_active)
91#endif
92 error (1, 0,
93 "-q or -Q must be specified before \"%s\"",
94 command_name);
95 break;
96 case 'd':
97#ifdef SERVER_SUPPORT1
98 if (server_active)
99 {
100 /* CVS 1.10 and older clients will send this, but it
101 doesn't do any good. So tell the user we can't
102 cope, rather than silently losing. */
103 error (0, 0,
104 "warning: not setting the time of import from the file");
105 error (0, 0, "due to client limitations");
106 }
107#endif
108 use_file_modtime = 1;
109 break;
110 case 'b':
111 free (vbranch);
112 vbranch = xstrdup (optarg);
113 break;
114 case 'm':
115#ifdef FORCE_USE_EDITOR
116 use_editor = 1;
117#else
118 use_editor = 0;
119#endif
120 message = xstrdup(optarg);
121 break;
122 case 'I':
123 ign_add (optarg, 0);
124 break;
125 case 'k':
126 /* RCS_check_kflag returns strings of the form -kxx. We
127 only use it for validation, so we can free the value
128 as soon as it is returned. */
129 free (RCS_check_kflag (optarg));
130 keyword_opt = optarg;
131 break;
132 case 'W':
133 wrap_add (optarg, 0);
134 break;
135 case '?':
136 default:
137 usage (import_usage);
138 break;
139 }
140 }
141 argc -= optind;
142 argv += optind;
143 if (argc < 3)
144 usage (import_usage);
145
146#ifdef SERVER_SUPPORT1
147 /* This is for handling the Checkin-time request. It might seem a
148 bit odd to enable the use_file_modtime code even in the case
149 where Checkin-time was not sent for a particular file. The
150 effect is that we use the time of upload, rather than the time
151 when we call RCS_checkin. Since those times are both during
152 CVS's run, that seems OK, and it is easier to implement than
153 putting the "was Checkin-time sent" flag in CVS/Entries or some
154 such place. */
155
156 if (server_active)
157 use_file_modtime = 1;
158#endif
159
160 for (i = 1; i < argc; i++) /* check the tags for validity */
161 {
162 int j;
163
164 RCS_check_tag (argv[i]);
165 for (j = 1; j < i; j++)
166 if (strcmp (argv[j], argv[i]) == 0)
167 error (1, 0, "tag `%s' was specified more than once", argv[i]);
168 }
169
170 /* XXX - this should be a module, not just a pathname */
171 if (! isabsolute (argv[0])
172 && pathname_levels (argv[0]) == 0)
173 {
174 if (current_parsed_root == NULL((void*)0))
175 {
176 error (0, 0, "missing CVSROOT environment variable\n");
177 error (1, 0, "Set it or specify the '-d' option to %s.",
178 program_name);
179 }
180 repository = xmalloc (strlen (current_parsed_root->directory)
181 + strlen (argv[0])
182 + 2);
183 (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
184 repos_len = strlen (current_parsed_root->directory);
185 }
186 else
187 {
188 /* It is somewhere between a security hole and "unexpected" to
189 let the client start mucking around outside the cvsroot
190 (wouldn't get the right CVSROOT configuration, &c). */
191 error (1, 0, "directory %s not relative within the repository",
192 argv[0]);
193 }
194
195 /*
196 * Consistency checks on the specified vendor branch. It must be
197 * composed of only numbers and dots ('.'). Also, for now we only
198 * support branching to a single level, so the specified vendor branch
199 * must only have two dots in it (like "1.1.1").
200 */
201 for (cp = vbranch; *cp != '\0'; cp++)
202 if (!isdigit ((unsigned char) *cp) && *cp != '.')
203 error (1, 0, "%s is not a numeric branch", vbranch);
204 if (numdots (vbranch) != 2)
205 error (1, 0, "Only branches with two dots are supported: %s", vbranch);
206 vhead = xstrdup (vbranch);
207 cp = strrchr (vhead, '.');
208 *cp = '\0';
209
210#ifdef CLIENT_SUPPORT1
211 if (current_parsed_root->isremote)
212 {
213 /* For rationale behind calling start_server before do_editor, see
214 commit.c */
215 start_server ();
216 }
217#endif
218
219 if (use_editor)
220 {
221 do_editor ((char *) NULL((void*)0), &message, repository,
222 (List *) NULL((void*)0));
223 }
224 do_verify (message, repository);
225 msglen = message == NULL((void*)0) ? 0 : strlen (message);
226 if (msglen == 0 || message[msglen - 1] != '\n')
227 {
228 char *nm = xmalloc (msglen + 2);
229 *nm = '\0';
230 if (message != NULL((void*)0))
231 {
232 (void) strcpy (nm, message);
233 free (message);
234 }
235 (void) strcat (nm + msglen, "\n");
236 message = nm;
237 }
238
239#ifdef CLIENT_SUPPORT1
240 if (current_parsed_root->isremote)
241 {
242 int err;
243
244 if (vbranch[0] != '\0')
245 option_with_arg ("-b", vbranch);
246 if (message)
247 option_with_arg ("-m", message);
248 if (keyword_opt != NULL((void*)0))
249 option_with_arg ("-k", keyword_opt);
250 /* The only ignore processing which takes place on the server side
251 is the CVSROOT/cvsignore file. But if the user specified -I !,
252 the documented behavior is to not process said file. */
253 if (ign_inhibit_server)
254 {
255 send_arg ("-I");
256 send_arg ("!");
257 }
258 wrap_send ();
259
260 {
261 int i;
262 for (i = 0; i < argc; ++i)
263 send_arg (argv[i]);
264 }
265
266 logfp = stdin(&__sF[0]);
267 client_import_setup (repository);
268 err = import_descend (message, argv[1], argc - 2, argv + 2);
269 client_import_done ();
270 if (message)
271 free (message);
272 free (repository);
273 free (vbranch);
274 free (vhead);
275 send_to_server ("import\012", 0);
276 err += get_responses_and_close ();
277 return err;
278 }
279#endif
280
281 if (!safe_location ())
282 {
283 error (1, 0, "attempt to import the repository");
284 }
285
286 /*
287 * Make all newly created directories writable. Should really use a more
288 * sophisticated security mechanism here.
289 */
290 (void) umask (cvsumask);
291 make_directories (repository);
292
293 /* Create the logfile that will be logged upon completion */
294 if ((logfp = cvs_temp_file (&tmpfile)) == NULL((void*)0))
295 error (1, errno(*__errno()), "cannot create temporary file `%s'", tmpfile);
296 /* On systems where we can unlink an open file, do so, so it will go
297 away no matter how we exit. FIXME-maybe: Should be checking for
298 errors but I'm not sure which error(s) we get if we are on a system
299 where one can't unlink open files. */
300 (void) CVS_UNLINKunlink (tmpfile);
301 (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
302 (void) fprintf (logfp, "Release Tags:\t");
303 for (i = 2; i < argc; i++)
304 (void) fprintf (logfp, "%s\n\t\t", argv[i]);
305 (void) fprintf (logfp, "\n");
306
307 /* Just Do It. */
308 err = import_descend (message, argv[1], argc - 2, argv + 2);
309 if (conflicts)
310 {
311 if (!really_quiet)
312 {
313 char buf[20];
314 char *buf2;
315
316 cvs_output_tagged ("+importmergecmd", NULL((void*)0));
317 cvs_output_tagged ("newline", NULL((void*)0));
318 sprintf (buf, "%d", conflicts);
319 cvs_output_tagged ("conflicts", buf);
320 cvs_output_tagged ("text", " conflicts created by this import.");
321 cvs_output_tagged ("newline", NULL((void*)0));
322 cvs_output_tagged ("text",
323 "Use the following command to help the merge:");
324 cvs_output_tagged ("newline", NULL((void*)0));
325 cvs_output_tagged ("newline", NULL((void*)0));
326 cvs_output_tagged ("text", "\t");
327 cvs_output_tagged ("text", program_name);
328 if (CVSroot_cmdline != NULL((void*)0))
329 {
330 cvs_output_tagged ("text", " -d ");
331 cvs_output_tagged ("text", CVSroot_cmdline);
332 }
333 cvs_output_tagged ("text", " checkout -j");
334 buf2 = xmalloc (strlen (argv[1]) + 20);
335 sprintf (buf2, "%s:yesterday", argv[1]);
336 cvs_output_tagged ("mergetag1", buf2);
337 free (buf2);
338 cvs_output_tagged ("text", " -j");
339 cvs_output_tagged ("mergetag2", argv[1]);
340 cvs_output_tagged ("text", " ");
341 cvs_output_tagged ("repository", argv[0]);
342 cvs_output_tagged ("newline", NULL((void*)0));
343 cvs_output_tagged ("newline", NULL((void*)0));
344 cvs_output_tagged ("-importmergecmd", NULL((void*)0));
345 }
346
347 /* FIXME: I'm not sure whether we need to put this information
348 into the loginfo. If we do, then note that it does not
349 report any required -d option. There is no particularly
350 clean way to tell the server about the -d option used by
351 the client. */
352 (void) fprintf (logfp, "\n%d conflicts created by this import.\n",
353 conflicts);
354 (void) fprintf (logfp,
355 "Use the following command to help the merge:\n\n");
356 (void) fprintf (logfp, "\t%s checkout ", program_name);
357 (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
358 argv[1], argv[1], argv[0]);
359 }
360 else
361 {
362 if (!really_quiet)
363 cvs_output ("\nNo conflicts created by this import\n\n", 0);
364 (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
365 }
366
367 /*
368 * Write out the logfile and clean up.
369 */
370 ulist = getlist ();
371 p = getnode ();
372 p->type = UPDATE;
373 p->delproc = update_delproc;
374 p->key = xstrdup ("- Imported sources");
375 li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
376 li->type = T_TITLE;
377 li->tag = xstrdup (vbranch);
378 li->rev_old = li->rev_new = NULL((void*)0);
379 p->data = (char *) li;
380 (void) addnode (ulist, p);
381 Update_Logfile (repository, message, logfp, ulist);
382 dellist (&ulist);
383 if (fclose (logfp) < 0)
384 error (0, errno(*__errno()), "error closing %s", tmpfile);
385
386 /* Make sure the temporary file goes away, even on systems that don't let
387 you delete a file that's in use. */
388 if (CVS_UNLINKunlink (tmpfile) < 0 && !existence_error (errno)(((*__errno())) == 2))
389 error (0, errno(*__errno()), "cannot remove %s", tmpfile);
390 free (tmpfile);
391
392 if (message)
393 free (message);
394 free (repository);
395 free (vbranch);
396 free (vhead);
397
398 return (err);
399}
400
401/* Process all the files in ".", then descend into other directories.
402 Returns 0 for success, or >0 on error (in which case a message
403 will have been printed). */
404static int
405import_descend (message, vtag, targc, targv)
406 char *message;
407 char *vtag;
408 int targc;
409 char *targv[];
410{
411 DIR *dirp;
412 struct dirent *dp;
413 int err = 0;
414 List *dirlist = NULL((void*)0);
415
416 /* first, load up any per-directory ignore lists */
417 ign_add_file (CVSDOTIGNORE".cvsignore", 1);
418 wrap_add_file (CVSDOTWRAPPER".cvswrappers", 1);
419
420 if ((dirp = CVS_OPENDIRopendir (".")) == NULL((void*)0))
421 {
422 error (0, errno(*__errno()), "cannot open directory");
423 err++;
424 }
425 else
426 {
427 errno(*__errno()) = 0;
428 while ((dp = CVS_READDIRreaddir (dirp)) != NULL((void*)0))
429 {
430 if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
431 goto one_more_time_boys;
432#ifdef SERVER_SUPPORT1
433 /* CVS directories are created in the temp directory by
434 server.c because it doesn't special-case import. So
435 don't print a message about them, regardless of -I!. */
436 if (server_active && strcmp (dp->d_name, CVSADM"CVS") == 0)
437 goto one_more_time_boys;
438#endif
439 if (ign_name (dp->d_name))
440 {
441 add_log ('I', dp->d_name);
442 goto one_more_time_boys;
443 }
444
445 if (
446#ifdef DT_DIR4
447 (dp->d_type == DT_DIR4
448 || (dp->d_type == DT_UNKNOWN0 && isdir (dp->d_name)))
449#else
450 isdir (dp->d_name)
451#endif
452 && !wrap_name_has (dp->d_name, WRAP_TOCVS)
453 )
454 {
455 Node *n;
456
457 if (dirlist == NULL((void*)0))
458 dirlist = getlist();
459
460 n = getnode();
461 n->key = xstrdup (dp->d_name);
462 addnode(dirlist, n);
463 }
464 else if (
465#ifdef DT_DIR4
466 dp->d_type == DT_LNK10
467 || (dp->d_type == DT_UNKNOWN0 && islink (dp->d_name))
468#else
469 islink (dp->d_name)
470#endif
471 )
472 {
473 add_log ('L', dp->d_name);
474 err++;
475 }
476 else
477 {
478#ifdef CLIENT_SUPPORT1
479 if (current_parsed_root->isremote)
480 err += client_process_import_file (message, dp->d_name,
481 vtag, targc, targv,
482 repository,
483 keyword_opt != NULL((void*)0) &&
484 keyword_opt[0] == 'b',
485 use_file_modtime);
486 else
487#endif
488 err += process_import_file (message, dp->d_name,
489 vtag, targc, targv);
490 }
491 one_more_time_boys:
492 errno(*__errno()) = 0;
493 }
494 if (errno(*__errno()) != 0)
495 {
496 error (0, errno(*__errno()), "cannot read directory");
497 ++err;
498 }
499 (void) CVS_CLOSEDIRclosedir (dirp);
500 }
501
502 if (dirlist != NULL((void*)0))
503 {
504 Node *head, *p;
505
506 head = dirlist->list;
507 for (p = head->next; p != head; p = p->next)
508 {
509 err += import_descend_dir (message, p->key, vtag, targc, targv);
510 }
511
512 dellist(&dirlist);
513 }
514
515 return (err);
516}
517
518/*
519 * Process the argument import file.
520 */
521static int
522process_import_file (message, vfile, vtag, targc, targv)
523 char *message;
524 char *vfile;
525 char *vtag;
526 int targc;
527 char *targv[];
528{
529 char *rcs;
530 int inattic = 0;
531
532 rcs = xmalloc (strlen (repository) + strlen (vfile) + sizeof (RCSEXT",v")
533 + 5);
534 (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT",v");
535 if (!isfile (rcs))
536 {
537 char *attic_name;
538
539 attic_name = xmalloc (strlen (repository) + strlen (vfile) +
540 sizeof (CVSATTIC"Attic") + sizeof (RCSEXT",v") + 10);
541 (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC"Attic",
542 vfile, RCSEXT",v");
543 if (!isfile (attic_name))
544 {
545 int retval;
546 char *free_opt = NULL((void*)0);
547 char *our_opt = keyword_opt;
548
549 free (attic_name);
550 /*
551 * A new import source file; it doesn't exist as a ,v within the
552 * repository nor in the Attic -- create it anew.
553 */
554 add_log ('N', vfile);
555
556#ifdef SERVER_SUPPORT1
557 /* The most reliable information on whether the file is binary
558 is what the client told us. That is because if the client had
559 the wrong idea about binaryness, it corrupted the file, so
560 we might as well believe the client. */
561 if (server_active)
562 {
563 Node *node;
564 List *entries;
565
566 /* Reading all the entries for each file is fairly silly, and
567 probably slow. But I am too lazy at the moment to do
568 anything else. */
569 entries = Entries_Open (0, NULL((void*)0));
570 node = findnode_fn (entries, vfile);
571 if (node != NULL((void*)0))
572 {
573 Entnode *entdata = (Entnode *) node->data;
574 if (entdata->type == ENT_FILE)
575 {
576 assert (entdata->options[0] == '-'((entdata->options[0] == '-' && entdata->options
[1] == 'k') ? (void)0 : __assert2("/usr/src/gnu/usr.bin/cvs/src/import.c"
, 577, __func__, "entdata->options[0] == '-' && entdata->options[1] == 'k'"
))
577 && entdata->options[1] == 'k')((entdata->options[0] == '-' && entdata->options
[1] == 'k') ? (void)0 : __assert2("/usr/src/gnu/usr.bin/cvs/src/import.c"
, 577, __func__, "entdata->options[0] == '-' && entdata->options[1] == 'k'"
))
;
578 our_opt = xstrdup (entdata->options + 2);
579 free_opt = our_opt;
580 }
581 }
582 Entries_Close (entries);
583 }
584#endif
585
586 retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
587 vbranch, vtag, targc, targv,
588 NULL((void*)0), 0, logfp);
589 if (free_opt != NULL((void*)0))
590 free (free_opt);
591 free (rcs);
592 return retval;
593 }
594 free (attic_name);
595 inattic = 1;
596 }
597
598 free (rcs);
599 /*
600 * an rcs file exists. have to do things the official, slow, way.
601 */
602 return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
603}
604
605/*
606 * The RCS file exists; update it by adding the new import file to the
607 * (possibly already existing) vendor branch.
608 */
609static int
610update_rcs_file (message, vfile, vtag, targc, targv, inattic)
611 char *message;
612 char *vfile;
613 char *vtag;
614 int targc;
615 char *targv[];
616 int inattic;
617{
618 Vers_TS *vers;
619 int letter;
620 char *tocvsPath;
621 struct file_info finfo;
622
623 memset (&finfo, 0, sizeof finfo);
624 finfo.file = vfile;
625 /* Not used, so don't worry about it. */
626 finfo.update_dir = NULL((void*)0);
627 finfo.fullname = finfo.file;
628 finfo.repository = repository;
629 finfo.entries = NULL((void*)0);
630 finfo.rcs = NULL((void*)0);
631 vers = Version_TS (&finfo, (char *) NULL((void*)0), vbranch, (char *) NULL((void*)0),
632 1, 0);
633 if (vers->vn_rcs != NULL((void*)0)
634 && !RCS_isdead(vers->srcfile, vers->vn_rcs))
635 {
636 int different;
637
638 /*
639 * The rcs file does have a revision on the vendor branch. Compare
640 * this revision with the import file; if they match exactly, there
641 * is no need to install the new import file as a new revision to the
642 * branch. Just tag the revision with the new import tags.
643 *
644 * This is to try to cut down the number of "C" conflict messages for
645 * locally modified import source files.
646 */
647 tocvsPath = wrap_tocvs_process_file (vfile);
648 /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
649 not NULL? */
650 different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, "-ko", vfile);
651 if (tocvsPath)
652 if (unlink_file_dir (tocvsPath) < 0)
653 error (0, errno(*__errno()), "cannot remove %s", tocvsPath);
654
655 if (!different)
656 {
657 int retval = 0;
658
659 /*
660 * The two files are identical. Just update the tags, print the
661 * "U", signifying that the file has changed, but needs no
662 * attention, and we're done.
663 */
664 if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
665 retval = 1;
666 add_log ('U', vfile);
667 freevers_ts (&vers);
668 return (retval);
669 }
670 }
671
672 /* We may have failed to parse the RCS file; check just in case */
673 if (vers->srcfile == NULL((void*)0) ||
674 add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
675 add_tags (vers->srcfile, vfile, vtag, targc, targv))
676 {
677 freevers_ts (&vers);
678 return (1);
679 }
680
681 if (vers->srcfile->branch == NULL((void*)0) || inattic ||
682 strcmp (vers->srcfile->branch, vbranch) != 0)
683 {
684 conflicts++;
685 letter = 'C';
686 }
687 else
688 letter = 'U';
689 add_log (letter, vfile);
690
691 freevers_ts (&vers);
692 return (0);
693}
694
695/*
696 * Add the revision to the vendor branch
697 */
698static int
699add_rev (message, rcs, vfile, vers)
700 char *message;
701 RCSNode *rcs;
702 char *vfile;
703 char *vers;
704{
705 int locked, status, ierrno;
706 char *tocvsPath;
707
708 if (noexec)
709 return (0);
710
711 locked = 0;
712 if (vers != NULL((void*)0))
713 {
714 /* Before RCS_lock existed, we were directing stdout, as well as
715 stderr, from the RCS command, to DEVNULL. I wouldn't guess that
716 was necessary, but I don't know for sure. */
717 /* Earlier versions of this function printed a `fork failed' error
718 when RCS_lock returned an error code. That's not appropriate
719 now that RCS_lock is librarified, but should the error text be
720 preserved? */
721 if (RCS_lock (rcs, vbranch, 1) != 0)
722 return 1;
723 locked = 1;
724 RCS_rewrite (rcs, NULL((void*)0), NULL((void*)0));
725 }
726 tocvsPath = wrap_tocvs_process_file (vfile);
727
728 status = RCS_checkin (rcs, tocvsPath == NULL((void*)0) ? vfile : tocvsPath,
729 message, vbranch,
730 (RCS_FLAGS_QUIET4 | RCS_FLAGS_KEEPFILE16
731 | (use_file_modtime ? RCS_FLAGS_MODTIME8 : 0)));
732 ierrno = errno(*__errno());
733
734 if ((tocvsPath != NULL((void*)0)) && (unlink_file_dir (tocvsPath) < 0))
735 error (0, errno(*__errno()), "cannot remove %s", tocvsPath);
736
737 if (status)
738 {
739 if (!noexec)
740 {
741 fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
742 "ERROR: Check-in of %s failed", rcs->path);
743 error (0, status == -1 ? ierrno : 0,
744 "ERROR: Check-in of %s failed", rcs->path);
745 }
746 if (locked)
747 {
748 (void) RCS_unlock(rcs, vbranch, 0);
749 RCS_rewrite (rcs, NULL((void*)0), NULL((void*)0));
750 }
751 return (1);
752 }
753 return (0);
754}
755
756/*
757 * Add the vendor branch tag and all the specified import release tags to the
758 * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
759 * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
760 * 1.1.1.2, ...).
761 */
762static int
763add_tags (rcs, vfile, vtag, targc, targv)
764 RCSNode *rcs;
765 char *vfile;
766 char *vtag;
767 int targc;
768 char *targv[];
769{
770 int i, ierrno;
771 Vers_TS *vers;
772 int retcode = 0;
773 struct file_info finfo;
774
775 if (noexec)
776 return (0);
777
778 if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
779 {
780 ierrno = errno(*__errno());
781 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
782 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
783 error (0, retcode == -1 ? ierrno : 0,
784 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
785 return (1);
786 }
787 RCS_rewrite (rcs, NULL((void*)0), NULL((void*)0));
788
789 memset (&finfo, 0, sizeof finfo);
790 finfo.file = vfile;
791 /* Not used, so don't worry about it. */
792 finfo.update_dir = NULL((void*)0);
793 finfo.fullname = finfo.file;
794 finfo.repository = repository;
795 finfo.entries = NULL((void*)0);
796 finfo.rcs = NULL((void*)0);
797 vers = Version_TS (&finfo, NULL((void*)0), vtag, NULL((void*)0), 1, 0);
798 for (i = 0; i < targc; i++)
799 {
800 if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
801 RCS_rewrite (rcs, NULL((void*)0), NULL((void*)0));
802 else
803 {
804 ierrno = errno(*__errno());
805 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
806 "WARNING: Couldn't add tag %s to %s", targv[i],
807 rcs->path);
808 error (0, retcode == -1 ? ierrno : 0,
809 "WARNING: Couldn't add tag %s to %s", targv[i],
810 rcs->path);
811 }
812 }
813 freevers_ts (&vers);
814 return (0);
815}
816
817/*
818 * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
819 */
820struct compair
821{
822 char *suffix, *comlead;
823};
824
825static const struct compair comtable[] =
826{
827
828/*
829 * comtable pairs each filename suffix with a comment leader. The comment
830 * leader is placed before each line generated by the $Log keyword. This
831 * table is used to guess the proper comment leader from the working file's
832 * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
833 * languages without multiline comments; for others they are optional.
834 *
835 * I believe that the comment leader is unused if you are using RCS 5.7, which
836 * decides what leader to use based on the text surrounding the $Log keyword
837 * rather than a specified comment leader.
838 */
839 {"a", "-- "}, /* Ada */
840 {"ada", "-- "},
841 {"adb", "-- "},
842 {"asm", ";; "}, /* assembler (MS-DOS) */
843 {"ads", "-- "}, /* Ada */
844 {"bas", "' "}, /* Visual Basic code */
845 {"bat", ":: "}, /* batch (MS-DOS) */
846 {"body", "-- "}, /* Ada */
847 {"c", " * "}, /* C */
848 {"c++", "// "}, /* C++ in all its infinite guises */
849 {"cc", "// "},
850 {"cpp", "// "},
851 {"cxx", "// "},
852 {"m", "// "}, /* Objective-C */
853 {"cl", ";;; "}, /* Common Lisp */
854 {"cmd", ":: "}, /* command (OS/2) */
855 {"cmf", "c "}, /* CM Fortran */
856 {"cs", " * "}, /* C* */
857 {"csh", "# "}, /* shell */
858 {"dlg", " * "}, /* MS Windows dialog file */
859 {"e", "# "}, /* efl */
860 {"epsf", "% "}, /* encapsulated postscript */
861 {"epsi", "% "}, /* encapsulated postscript */
862 {"el", "; "}, /* Emacs Lisp */
863 {"f", "c "}, /* Fortran */
864 {"for", "c "},
865 {"frm", "' "}, /* Visual Basic form */
866 {"h", " * "}, /* C-header */
867 {"hh", "// "}, /* C++ header */
868 {"hpp", "// "},
869 {"hxx", "// "},
870 {"in", "# "}, /* for Makefile.in */
871 {"l", " * "}, /* lex (conflict between lex and
872 * franzlisp) */
873 {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
874 * VMS, etc) */
875 {"mak", "# "}, /* makefile, e.g. Visual C++ */
876 {"me", ".\\\" "}, /* me-macros t/nroff */
877 {"ml", "; "}, /* mocklisp */
878 {"mm", ".\\\" "}, /* mm-macros t/nroff */
879 {"ms", ".\\\" "}, /* ms-macros t/nroff */
880 {"man", ".\\\" "}, /* man-macros t/nroff */
881 {"1", ".\\\" "}, /* feeble attempt at man pages... */
882 {"2", ".\\\" "},
883 {"3", ".\\\" "},
884 {"4", ".\\\" "},
885 {"5", ".\\\" "},
886 {"6", ".\\\" "},
887 {"7", ".\\\" "},
888 {"8", ".\\\" "},
889 {"9", ".\\\" "},
890 {"p", " * "}, /* pascal */
891 {"pas", " * "},
892 {"pl", "# "}, /* perl (conflict with Prolog) */
893 {"ps", "% "}, /* postscript */
894 {"psw", "% "}, /* postscript wrap */
895 {"pswm", "% "}, /* postscript wrap */
896 {"r", "# "}, /* ratfor */
897 {"rc", " * "}, /* Microsoft Windows resource file */
898 {"red", "% "}, /* psl/rlisp */
899#ifdef __sparc__
900 {"s", "! "}, /* assembler */
901#endif
902#ifdef __sparc64__
903 {"s", "! "}, /* assembler */
904#endif
905#ifdef __mc68000__
906 {"s", "| "}, /* assembler */
907#endif
908#ifdef __pdp11__
909 {"s", "/ "}, /* assembler */
910#endif
911#ifdef __vax__
912 {"s", "# "}, /* assembler */
913#endif
914#ifdef __ksr__
915 {"s", "# "}, /* assembler */
916 {"S", "# "}, /* Macro assembler */
917#endif
918 {"sh", "# "}, /* shell */
919 {"sl", "% "}, /* psl */
920 {"spec", "-- "}, /* Ada */
921 {"tex", "% "}, /* tex */
922 {"y", " * "}, /* yacc */
923 {"ye", " * "}, /* yacc-efl */
924 {"yr", " * "}, /* yacc-ratfor */
925 {"", "# "}, /* default for empty suffix */
926 {NULL((void*)0), "# "} /* default for unknown suffix; */
927/* must always be last */
928};
929
930static char *
931get_comment (user)
932 char *user;
933{
934 char *cp, *suffix;
935 char *suffix_path;
936 int i;
937 char *retval;
938
939 suffix_path = xmalloc (strlen (user) + 5);
940 cp = strrchr (user, '.');
941 if (cp != NULL((void*)0))
942 {
943 cp++;
944
945 /*
946 * Convert to lower-case, since we are not concerned about the
947 * case-ness of the suffix.
948 */
949 (void) strcpy (suffix_path, cp);
950 for (cp = suffix_path; *cp; cp++)
951 if (isupper ((unsigned char) *cp))
952 *cp = tolower (*cp);
953 suffix = suffix_path;
954 }
955 else
956 suffix = ""; /* will use the default */
957 for (i = 0;; i++)
958 {
959 if (comtable[i].suffix == NULL((void*)0))
960 {
961 /* Default. Note we'll always hit this case before we
962 ever return NULL. */
963 retval = comtable[i].comlead;
964 break;
965 }
966 if (strcmp (suffix, comtable[i].suffix) == 0)
967 {
968 retval = comtable[i].comlead;
969 break;
970 }
971 }
972 free (suffix_path);
973 return retval;
974}
975
976/* Create a new RCS file from scratch.
977
978 This probably should be moved to rcs.c now that it is called from
979 places outside import.c.
980
981 Return value is 0 for success, or nonzero for failure (in which
982 case an error message will have already been printed). */
983int
984add_rcs_file (message, rcs, user, add_vhead, key_opt,
985 add_vbranch, vtag, targc, targv,
986 desctext, desclen, add_logfp)
987 /* Log message for the addition. Not used if add_vhead == NULL. */
988 char *message;
989 /* Filename of the RCS file to create. */
990 char *rcs;
991 /* Filename of the file to serve as the contents of the initial
992 revision. Even if add_vhead is NULL, we use this to determine
993 the modes to give the new RCS file. */
994 char *user;
995
996 /* Revision number of head that we are adding. Normally 1.1 but
997 could be another revision as long as ADD_VBRANCH is a branch
998 from it. If NULL, then just add an empty file without any
999 revisions (similar to the one created by "rcs -i"). */
1000 char *add_vhead;
1001
1002 /* Keyword expansion mode, e.g., "b" for binary. NULL means the
1003 default behavior. */
1004 char *key_opt;
1005
1006 /* Vendor branch to import to, or NULL if none. If non-NULL, then
1007 vtag should also be non-NULL. */
1008 char *add_vbranch;
1009 char *vtag;
1010 int targc;
1011 char *targv[];
1012
1013 /* If non-NULL, description for the file. If NULL, the description
1014 will be empty. */
1015 char *desctext;
1016 size_t desclen;
1017
1018 /* Write errors to here as well as via error (), or NULL if we should
1019 use only error (). */
1020 FILE *add_logfp;
1021{
1022 FILE *fprcs, *fpuser;
1023 struct stat sb;
1024 struct tm *ftm;
1025 time_t now;
1026 char altdate1[MAXDATELEN50];
1027 char *author;
1028 int i, ierrno, err = 0;
1029 mode_t mode;
1030 char *tocvsPath;
1031 char *userfile;
1032 char *local_opt = key_opt;
1033 char *free_opt = NULL((void*)0);
1034 mode_t file_type;
1035
1036 if (noexec)
1
Assuming 'noexec' is 0
2
Taking false branch
1037 return (0);
1038
1039 /* Note that as the code stands now, the -k option overrides any
1040 settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1041 whatever). Some have suggested this should be the other way
1042 around. As far as I know the documentation doesn't say one way
1043 or the other. Before making a change of this sort, should think
1044 about what is best, document it (in cvs.texinfo and NEWS), &c. */
1045
1046 if (local_opt == NULL((void*)0))
3
Assuming 'local_opt' is equal to NULL
4
Taking true branch
1047 {
1048 if (wrap_name_has (user, WRAP_RCSOPTION))
5
Assuming the condition is false
6
Taking false branch
1049 {
1050 local_opt = free_opt = wrap_rcsoption (user, 0);
1051 }
1052 }
1053
1054 tocvsPath = wrap_tocvs_process_file (user);
1055 userfile = (tocvsPath == NULL((void*)0) ? user : tocvsPath);
7
Assuming 'tocvsPath' is not equal to NULL
8
'?' condition is false
1056
1057 /* Opening in text mode is probably never the right thing for the
1058 server (because the protocol encodes text files in a fashion
1059 which does not depend on what the client or server OS is, as
1060 documented in cvsclient.texi), but as long as the server just
1061 runs on unix it is a moot point. */
1062
1063 /* If PreservePermissions is set, then make sure that the file
1064 is a plain file before trying to open it. Longstanding (although
1065 often unpopular) CVS behavior has been to follow symlinks, so we
1066 maintain that behavior if PreservePermissions is not on.
1067
1068 NOTE: this error message used to be `cannot fstat', but is now
1069 `cannot lstat'. I don't see a way around this, since we must
1070 stat the file before opening it. -twp */
1071
1072 if (CVS_LSTATlstat (userfile, &sb) < 0)
9
Assuming the condition is false
10
Taking false branch
1073 {
1074 /* not fatal, continue import */
1075 if (add_logfp != NULL((void*)0))
1076 fperrmsg (add_logfp, 0, errno(*__errno()),
1077 "ERROR: cannot lstat file %s", userfile);
1078 error (0, errno(*__errno()), "cannot lstat file %s", userfile);
1079 goto read_error;
1080 }
1081 file_type = sb.st_mode & S_IFMT0170000;
1082
1083 fpuser = NULL((void*)0);
11
Null pointer value stored to 'fpuser'
1084 if (!preserve_perms || file_type == S_IFREG0100000)
12
Assuming 'preserve_perms' is not equal to 0
13
Assuming 'file_type' is not equal to S_IFREG
14
Taking false branch
1085 {
1086 fpuser = CVS_FOPENfopen (userfile,
1087 ((local_opt != NULL((void*)0) && strcmp (local_opt, "b") == 0)
1088 ? "rb"
1089 : "r")
1090 );
1091 if (fpuser == NULL((void*)0))
1092 {
1093 /* not fatal, continue import */
1094 if (add_logfp != NULL((void*)0))
1095 fperrmsg (add_logfp, 0, errno(*__errno()),
1096 "ERROR: cannot read file %s", userfile);
1097 error (0, errno(*__errno()), "ERROR: cannot read file %s", userfile);
1098 goto read_error;
1099 }
1100 }
1101
1102 fprcs = CVS_FOPENfopen (rcs, "w+b");
1103 if (fprcs == NULL((void*)0))
15
Assuming 'fprcs' is not equal to NULL
16
Taking false branch
1104 {
1105 ierrno = errno(*__errno());
1106 goto write_error_noclose;
1107 }
1108
1109 /*
1110 * putadmin()
1111 */
1112 if (add_vhead != NULL((void*)0))
17
Assuming 'add_vhead' is not equal to NULL
18
Taking true branch
1113 {
1114 if (fprintf (fprcs, "head %s;\012", add_vhead) < 0)
19
Assuming the condition is false
20
Taking false branch
1115 goto write_error;
1116 }
1117 else
1118 {
1119 if (fprintf (fprcs, "head ;\012") < 0)
1120 goto write_error;
1121 }
1122
1123 if (add_vbranch != NULL((void*)0))
21
Assuming 'add_vbranch' is equal to NULL
22
Taking false branch
1124 {
1125 if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
1126 goto write_error;
1127 }
1128 if (fprintf (fprcs, "access ;\012") < 0 ||
23
Assuming the condition is false
25
Taking false branch
1129 fprintf (fprcs, "symbols ") < 0)
24
Assuming the condition is false
1130 {
1131 goto write_error;
1132 }
1133
1134 for (i = targc - 1; i >= 0; i--)
26
Assuming 'i' is < 0
27
Loop condition is false. Execution continues on line 1142
1135 {
1136 /* RCS writes the symbols backwards */
1137 assert (add_vbranch != NULL)((add_vbranch != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/cvs/src/import.c"
, 1137, __func__, "add_vbranch != NULL"))
;
1138 if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1139 goto write_error;
1140 }
1141
1142 if (add_vbranch
27.1
'add_vbranch' is equal to NULL
!= NULL((void*)0))
28
Taking false branch
1143 {
1144 if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1145 goto write_error;
1146 }
1147 if (fprintf (fprcs, ";\012") < 0)
29
Assuming the condition is false
30
Taking false branch
1148 goto write_error;
1149
1150 if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
31
Assuming the condition is false
33
Taking false branch
1151 /* XXX - make sure @@ processing works in the RCS file */
1152 fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
32
Assuming the condition is false
1153 {
1154 goto write_error;
1155 }
1156
1157 if (local_opt
33.1
'local_opt' is equal to NULL
!= NULL((void*)0))
34
Taking false branch
1158 {
1159 if (fprintf (fprcs, "expand @%s@;\012", local_opt) < 0)
1160 {
1161 goto write_error;
1162 }
1163 }
1164
1165 if (fprintf (fprcs, "\012") < 0)
35
Assuming the condition is false
36
Taking false branch
1166 goto write_error;
1167
1168 /* Write the revision(s), with the date and author and so on
1169 (that is "delta" rather than "deltatext" from rcsfile(5)). */
1170 if (add_vhead
36.1
'add_vhead' is not equal to NULL
!= NULL((void*)0))
37
Taking true branch
1171 {
1172 if (use_file_modtime)
38
Assuming 'use_file_modtime' is 0
39
Taking false branch
1173 now = sb.st_mtimest_mtim.tv_sec;
1174 else
1175 (void) time (&now);
1176 ftm = gmtime (&now);
1177 (void) sprintf (altdate1, DATEFORM"%02d.%02d.%02d.%02d.%02d.%02d",
1178 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
40
Assuming field 'tm_year' is >= 100
41
'?' condition is false
1179 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1180 ftm->tm_min, ftm->tm_sec);
1181 author = getcaller ();
1182
1183 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
42
Assuming the condition is false
44
Taking false branch
1184 fprintf (fprcs, "date %s; author %s; state Exp;\012",
43
Assuming the condition is false
1185 altdate1, author) < 0)
1186 goto write_error;
1187
1188 if (fprintf (fprcs, "branches") < 0)
45
Assuming the condition is false
46
Taking false branch
1189 goto write_error;
1190 if (add_vbranch
46.1
'add_vbranch' is equal to NULL
!= NULL((void*)0))
47
Taking false branch
1191 {
1192 if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1193 goto write_error;
1194 }
1195 if (fprintf (fprcs, ";\012") < 0)
48
Assuming the condition is false
49
Taking false branch
1196 goto write_error;
1197
1198 if (fprintf (fprcs, "next ;\012") < 0)
50
Assuming the condition is false
51
Taking false branch
1199 goto write_error;
1200
1201 if (fprintf (fprcs, "commitid %s;\012", global_session_id) < 0)
52
Assuming the condition is false
53
Taking false branch
1202 goto write_error;
1203
1204#ifdef PRESERVE_PERMISSIONS_SUPPORT
1205 /* Store initial permissions if necessary. */
1206 if (preserve_perms)
1207 {
1208 if (file_type == S_IFLNK0120000)
1209 {
1210 char *link = xreadlink (userfile);
1211 if (fprintf (fprcs, "symlink\t@") < 0 ||
1212 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1213 fprintf (fprcs, "@;\012") < 0)
1214 goto write_error;
1215 free (link);
1216 }
1217 else
1218 {
1219 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0)
1220 goto write_error;
1221 if (fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0)
1222 goto write_error;
1223 if (fprintf (fprcs, "permissions\t%o;\012",
1224 sb.st_mode & 07777) < 0)
1225 goto write_error;
1226 switch (file_type)
1227 {
1228 case S_IFREG0100000: break;
1229 case S_IFCHR0020000:
1230 case S_IFBLK0060000:
1231#ifdef HAVE_ST_RDEV1
1232 if (fprintf (fprcs, "special\t%s %lu;\012",
1233 (file_type == S_IFCHR0020000
1234 ? "character"
1235 : "block"),
1236 (unsigned long) sb.st_rdev) < 0)
1237 goto write_error;
1238#else
1239 error (0, 0,
1240"can't import %s: unable to import device files on this system",
1241userfile);
1242#endif
1243 break;
1244 default:
1245 error (0, 0,
1246 "can't import %s: unknown kind of special file",
1247 userfile);
1248 }
1249 }
1250 }
1251#endif
1252
1253 if (add_vbranch
53.1
'add_vbranch' is equal to NULL
!= NULL((void*)0))
54
Taking false branch
1254 {
1255 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1256 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1257 altdate1, author) < 0 ||
1258 fprintf (fprcs, "branches ;\012") < 0 ||
1259 fprintf (fprcs, "next ;\012") < 0 ||
1260 fprintf (fprcs, "commitid %s;\012", global_session_id) < 0
1261 )
1262 goto write_error;
1263
1264#ifdef PRESERVE_PERMISSIONS_SUPPORT
1265 /* Store initial permissions if necessary. */
1266 if (preserve_perms)
1267 {
1268 if (file_type == S_IFLNK0120000)
1269 {
1270 char *link = xreadlink (userfile);
1271 if (fprintf (fprcs, "symlink\t@") < 0 ||
1272 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1273 fprintf (fprcs, "@;\012") < 0)
1274 goto write_error;
1275 free (link);
1276 }
1277 else
1278 {
1279 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0 ||
1280 fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0 ||
1281 fprintf (fprcs, "permissions\t%o;\012",
1282 sb.st_mode & 07777) < 0)
1283 goto write_error;
1284
1285 switch (file_type)
1286 {
1287 case S_IFREG0100000: break;
1288 case S_IFCHR0020000:
1289 case S_IFBLK0060000:
1290#ifdef HAVE_ST_RDEV1
1291 if (fprintf (fprcs, "special\t%s %lu;\012",
1292 (file_type == S_IFCHR0020000
1293 ? "character"
1294 : "block"),
1295 (unsigned long) sb.st_rdev) < 0)
1296 goto write_error;
1297#else
1298 error (0, 0,
1299"can't import %s: unable to import device files on this system",
1300userfile);
1301#endif
1302 break;
1303 default:
1304 error (0, 0,
1305 "cannot import %s: special file of unknown type",
1306 userfile);
1307 }
1308 }
1309 }
1310#endif
1311
1312 if (fprintf (fprcs, "\012") < 0)
1313 goto write_error;
1314 }
1315 }
1316
1317 /* Now write the description (possibly empty). */
1318 if (fprintf (fprcs, "\012desc\012") < 0 ||
55
Assuming the condition is false
57
Taking false branch
1319 fprintf (fprcs, "@") < 0)
56
Assuming the condition is false
1320 goto write_error;
1321 if (desctext != NULL((void*)0))
58
Assuming 'desctext' is equal to NULL
59
Taking false branch
1322 {
1323 /* The use of off_t not size_t for the second argument is very
1324 strange, since we are dealing with something which definitely
1325 fits in memory. */
1326 if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1327 goto write_error;
1328 }
1329 if (fprintf (fprcs, "@\012\012\012") < 0)
60
Assuming the condition is false
61
Taking false branch
1330 goto write_error;
1331
1332 /* Now write the log messages and contents for the revision(s) (that
1333 is, "deltatext" rather than "delta" from rcsfile(5)). */
1334 if (add_vhead
61.1
'add_vhead' is not equal to NULL
!= NULL((void*)0))
62
Taking true branch
1335 {
1336 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
63
Assuming the condition is false
65
Taking false branch
1337 fprintf (fprcs, "log\012@") < 0)
64
Assuming the condition is false
1338 goto write_error;
1339 if (add_vbranch
65.1
'add_vbranch' is equal to NULL
!= NULL((void*)0))
66
Taking false branch
1340 {
1341 /* We are going to put the log message in the revision on the
1342 branch. So putting it here too seems kind of redundant, I
1343 guess (and that is what CVS has always done, anyway). */
1344 if (fprintf (fprcs, "Initial revision\012") < 0)
1345 goto write_error;
1346 }
1347 else
1348 {
1349 if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
67
Assuming the condition is false
68
Taking false branch
1350 goto write_error;
1351 }
1352 if (fprintf (fprcs, "@\012") < 0 ||
69
Assuming the condition is false
71
Taking false branch
1353 fprintf (fprcs, "text\012@") < 0)
70
Assuming the condition is false
1354 {
1355 goto write_error;
1356 }
1357
1358 /* Now copy over the contents of the file, expanding at signs.
1359 If preserve_perms is set, do this only for regular files. */
1360 if (!preserve_perms || file_type == S_IFREG0100000)
72
Assuming 'preserve_perms' is 0
1361 {
1362 char buf[8192];
1363 unsigned int len;
1364
1365 while (1)
73
Loop condition is true. Entering loop body
1366 {
1367 len = fread (buf, 1, sizeof buf, fpuser);
1368 if (len == 0)
74
Assuming 'len' is equal to 0
75
Taking true branch
1369 {
1370 if (ferror (fpuser)(!__isthreaded ? (((fpuser)->_flags & 0x0040) != 0) : (
ferror)(fpuser))
)
76
Assuming '__isthreaded' is 0
77
'?' condition is true
78
Access to field '_flags' results in a dereference of a null pointer (loaded from variable 'fpuser')
1371 error (1, errno(*__errno()), "cannot read file %s for copying",
1372 user);
1373 break;
1374 }
1375 if (expand_at_signs (buf, len, fprcs) < 0)
1376 goto write_error;
1377 }
1378 }
1379 if (fprintf (fprcs, "@\012\012") < 0)
1380 goto write_error;
1381 if (add_vbranch != NULL((void*)0))
1382 {
1383 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1384 fprintf (fprcs, "log\012@") < 0 ||
1385 expand_at_signs (message,
1386 (off_t) strlen (message), fprcs) < 0 ||
1387 fprintf (fprcs, "@\012text\012") < 0 ||
1388 fprintf (fprcs, "@@\012") < 0)
1389 goto write_error;
1390 }
1391 }
1392
1393 if (fclose (fprcs) == EOF(-1))
1394 {
1395 ierrno = errno(*__errno());
1396 goto write_error_noclose;
1397 }
1398 /* Close fpuser only if we opened it to begin with. */
1399 if (fpuser != NULL((void*)0))
1400 {
1401 if (fclose (fpuser) < 0)
1402 error (0, errno(*__errno()), "cannot close %s", user);
1403 }
1404
1405 /*
1406 * Fix the modes on the RCS files. The user modes of the original
1407 * user file are propagated to the group and other modes as allowed
1408 * by the repository umask, except that all write permissions are
1409 * turned off.
1410 */
1411 mode = (sb.st_mode |
1412 (sb.st_mode & S_IRWXU0000700) >> 3 |
1413 (sb.st_mode & S_IRWXU0000700) >> 6) &
1414 ~cvsumask &
1415 ~(S_IWRITE0000200 | S_IWGRP0000020 | S_IWOTH0000002);
1416 if (chmod (rcs, mode) < 0)
1417 {
1418 ierrno = errno(*__errno());
1419 if (add_logfp != NULL((void*)0))
1420 fperrmsg (add_logfp, 0, ierrno,
1421 "WARNING: cannot change mode of file %s", rcs);
1422 error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1423 err++;
1424 }
1425 if (tocvsPath)
1426 if (unlink_file_dir (tocvsPath) < 0)
1427 error (0, errno(*__errno()), "cannot remove %s", tocvsPath);
1428 if (free_opt != NULL((void*)0))
1429 free (free_opt);
1430 return (err);
1431
1432write_error:
1433 ierrno = errno(*__errno());
1434 if (fclose (fprcs) < 0)
1435 error (0, errno(*__errno()), "cannot close %s", rcs);
1436write_error_noclose:
1437 if (fclose (fpuser) < 0)
1438 error (0, errno(*__errno()), "cannot close %s", user);
1439 if (add_logfp != NULL((void*)0))
1440 fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1441 error (0, ierrno, "ERROR: cannot write file %s", rcs);
1442 if (ierrno == ENOSPC28)
1443 {
1444 if (CVS_UNLINKunlink (rcs) < 0)
1445 error (0, errno(*__errno()), "cannot remove %s", rcs);
1446 if (add_logfp != NULL((void*)0))
1447 fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1448 error (1, 0, "ERROR: out of space - aborting");
1449 }
1450read_error:
1451 if (tocvsPath)
1452 if (unlink_file_dir (tocvsPath) < 0)
1453 error (0, errno(*__errno()), "cannot remove %s", tocvsPath);
1454
1455 if (free_opt != NULL((void*)0))
1456 free (free_opt);
1457
1458 return (err + 1);
1459}
1460
1461/*
1462 * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1463 * signs. If an error occurs, return a negative value and set errno
1464 * to indicate the error. If not, return a nonnegative value.
1465 */
1466int
1467expand_at_signs (buf, size, fp)
1468 char *buf;
1469 off_t size;
1470 FILE *fp;
1471{
1472 register char *cp, *next;
1473
1474 cp = buf;
1475 while ((next = memchr (cp, '@', size)) != NULL((void*)0))
1476 {
1477 int len;
1478
1479 ++next;
1480 len = next - cp;
1481 if (fwrite (cp, 1, len, fp) != len)
1482 return EOF(-1);
1483 if (putc ('@', fp)(!__isthreaded ? __sputc('@', fp) : (putc)('@', fp)) == EOF(-1))
1484 return EOF(-1);
1485 cp = next;
1486 size -= len;
1487 }
1488
1489 if (fwrite (cp, 1, size, fp) != size)
1490 return EOF(-1);
1491
1492 return 1;
1493}
1494
1495/*
1496 * Write an update message to (potentially) the screen and the log file.
1497 */
1498static void
1499add_log (ch, fname)
1500 int ch;
1501 char *fname;
1502{
1503 if (!really_quiet) /* write to terminal */
1504 {
1505 char buf[2];
1506 buf[0] = ch;
1507 buf[1] = ' ';
1508 cvs_output (buf, 2);
1509 if (repos_len)
1510 {
1511 cvs_output (repository + repos_len + 1, 0);
1512 cvs_output ("/", 1);
1513 }
1514 else if (repository[0] != '\0')
1515 {
1516 cvs_output (repository, 0);
1517 cvs_output ("/", 1);
1518 }
1519 cvs_output (fname, 0);
1520 cvs_output ("\n", 1);
1521 }
1522
1523 if (repos_len) /* write to logfile */
1524 (void) fprintf (logfp, "%c %s/%s\n", ch,
1525 repository + repos_len + 1, fname);
1526 else if (repository[0])
1527 (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1528 else
1529 (void) fprintf (logfp, "%c %s\n", ch, fname);
1530}
1531
1532/*
1533 * This is the recursive function that walks the argument directory looking
1534 * for sub-directories that have CVS administration files in them and updates
1535 * them recursively.
1536 *
1537 * Note that we do not follow symbolic links here, which is a feature!
1538 */
1539static int
1540import_descend_dir (message, dir, vtag, targc, targv)
1541 char *message;
1542 char *dir;
1543 char *vtag;
1544 int targc;
1545 char *targv[];
1546{
1547 struct saved_cwd cwd;
1548 char *cp;
1549 int ierrno, err;
1550 char *rcs = NULL((void*)0);
1551
1552 if (islink (dir))
1553 return (0);
1554 if (save_cwd (&cwd))
1555 {
1556 fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
1557 return (1);
1558 }
1559
1560 /* Concatenate DIR to the end of REPOSITORY. */
1561 if (repository[0] == '\0')
1562 {
1563 char *new = xstrdup (dir);
1564 free (repository);
1565 repository = new;
1566 }
1567 else
1568 {
1569 char *new = xmalloc (strlen (repository) + strlen (dir) + 10);
1570 strcpy (new, repository);
1571 (void) strcat (new, "/");
1572 (void) strcat (new, dir);
1573 free (repository);
1574 repository = new;
1575 }
1576
1577#ifdef CLIENT_SUPPORT1
1578 if (!quiet && !current_parsed_root->isremote)
1579#else
1580 if (!quiet)
1581#endif
1582 error (0, 0, "Importing %s", repository);
1583
1584 if ( CVS_CHDIRchdir (dir) < 0)
1585 {
1586 ierrno = errno(*__errno());
1587 fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1588 error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1589 err = 1;
1590 goto out;
1591 }
1592#ifdef CLIENT_SUPPORT1
1593 if (!current_parsed_root->isremote && !isdir (repository))
1594#else
1595 if (!isdir (repository))
1596#endif
1597 {
1598 rcs = xmalloc (strlen (repository) + sizeof (RCSEXT",v") + 5);
1599 (void) sprintf (rcs, "%s%s", repository, RCSEXT",v");
1600 if (isfile (repository) || isfile(rcs))
1601 {
1602 fperrmsg (logfp, 0, 0,
1603 "ERROR: %s is a file, should be a directory!",
1604 repository);
1605 error (0, 0, "ERROR: %s is a file, should be a directory!",
1606 repository);
1607 err = 1;
1608 goto out;
1609 }
1610 if (noexec == 0 && CVS_MKDIRmkdir (repository, 0777) < 0)
1611 {
1612 ierrno = errno(*__errno());
1613 fperrmsg (logfp, 0, ierrno,
1614 "ERROR: cannot mkdir %s -- not added", repository);
1615 error (0, ierrno,
1616 "ERROR: cannot mkdir %s -- not added", repository);
1617 err = 1;
1618 goto out;
1619 }
1620 }
1621 err = import_descend (message, vtag, targc, targv);
1622 out:
1623 if (rcs != NULL((void*)0))
1624 free (rcs);
1625 if ((cp = strrchr (repository, '/')) != NULL((void*)0))
1626 *cp = '\0';
1627 else
1628 repository[0] = '\0';
1629 if (restore_cwd (&cwd, NULL((void*)0)))
1630 error_exit ();
1631 free_cwd (&cwd);
1632 return (err);
1633}