1 /* filesubr.c --- subroutines for dealing with files
2 Jim Blandy <jimb@cyclic.com>
3
4 This file is part of GNU CVS.
5
6 GNU CVS is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details. */
15
16 /* These functions were moved out of subr.c because they need different
17 definitions under operating systems (like, say, Windows NT) with different
18 file system semantics. */
19
20 #include <assert.h>
21 #include "cvs.h"
22
23 #include "xsize.h"
24
25 static int deep_remove_dir PROTO((const char *path));
26
27 /*
28 * Copies "from" to "to".
29 */
30 void
copy_file(from,to)31 copy_file (from, to)
32 const char *from;
33 const char *to;
34 {
35 struct stat sb;
36 struct utimbuf t;
37 int fdin, fdout;
38
39 if (trace)
40 (void) fprintf (stderr, "%s-> copy(%s,%s)\n",
41 CLIENT_SERVER_STR, from, to);
42 if (noexec)
43 return;
44
45 /* If the file to be copied is a link or a device, then just create
46 the new link or device appropriately. */
47 if (islink (from))
48 {
49 char *source = xreadlink (from);
50 symlink (source, to);
51 free (source);
52 return;
53 }
54
55 if (isdevice (from))
56 {
57 #if defined(HAVE_MKNOD) && defined(HAVE_STRUCT_STAT_ST_RDEV)
58 if (stat (from, &sb) < 0)
59 error (1, errno, "cannot stat %s", from);
60 mknod (to, sb.st_mode, sb.st_rdev);
61 #else
62 error (1, 0, "cannot copy device files on this system (%s)", from);
63 #endif
64 }
65 else
66 {
67 /* Not a link or a device... probably a regular file. */
68 if ((fdin = open (from, O_RDONLY)) < 0)
69 error (1, errno, "cannot open %s for copying", from);
70 if (fstat (fdin, &sb) < 0)
71 error (1, errno, "cannot fstat %s", from);
72 if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
73 error (1, errno, "cannot create %s for copying", to);
74 if (sb.st_size > 0)
75 {
76 char buf[BUFSIZ];
77 int n;
78
79 for (;;)
80 {
81 n = read (fdin, buf, sizeof(buf));
82 if (n == -1)
83 {
84 #ifdef EINTR
85 if (errno == EINTR)
86 continue;
87 #endif
88 error (1, errno, "cannot read file %s for copying", from);
89 }
90 else if (n == 0)
91 break;
92
93 if (write(fdout, buf, n) != n) {
94 error (1, errno, "cannot write file %s for copying", to);
95 }
96 }
97
98 #ifdef HAVE_FSYNC
99 if (fsync (fdout))
100 error (1, errno, "cannot fsync file %s after copying", to);
101 #endif
102 }
103
104 if (close (fdin) < 0)
105 error (0, errno, "cannot close %s", from);
106 if (close (fdout) < 0)
107 error (1, errno, "cannot close %s", to);
108 }
109
110 /* preserve last access & modification times */
111 memset ((char *) &t, 0, sizeof (t));
112 t.actime = sb.st_atime;
113 t.modtime = sb.st_mtime;
114 (void) utime (to, &t);
115 }
116
117 /* FIXME-krp: these functions would benefit from caching the char * &
118 stat buf. */
119
120 /*
121 * Returns non-zero if the argument file is a directory, or is a symbolic
122 * link which points to a directory.
123 */
124 int
isdir(file)125 isdir (file)
126 const char *file;
127 {
128 struct stat sb;
129
130 if (stat (file, &sb) < 0)
131 return (0);
132 return (S_ISDIR (sb.st_mode));
133 }
134
135 /*
136 * Returns non-zero if the argument file is a symbolic link.
137 */
138 int
islink(file)139 islink (file)
140 const char *file;
141 {
142 #ifdef S_ISLNK
143 struct stat sb;
144
145 if (CVS_LSTAT (file, &sb) < 0)
146 return (0);
147 return (S_ISLNK (sb.st_mode));
148 #else
149 return (0);
150 #endif
151 }
152
153 /*
154 * Returns non-zero if the argument file is a block or
155 * character special device.
156 */
157 int
isdevice(file)158 isdevice (file)
159 const char *file;
160 {
161 struct stat sb;
162
163 if (CVS_LSTAT (file, &sb) < 0)
164 return (0);
165 #ifdef S_ISBLK
166 if (S_ISBLK (sb.st_mode))
167 return 1;
168 #endif
169 #ifdef S_ISCHR
170 if (S_ISCHR (sb.st_mode))
171 return 1;
172 #endif
173 return 0;
174 }
175
176 /*
177 * Returns non-zero if the argument file exists.
178 */
179 int
isfile(file)180 isfile (file)
181 const char *file;
182 {
183 return isaccessible(file, F_OK);
184 }
185
186 /*
187 * Returns non-zero if the argument file is readable.
188 */
189 int
isreadable(file)190 isreadable (file)
191 const char *file;
192 {
193 return isaccessible(file, R_OK);
194 }
195
196 /*
197 * Returns non-zero if the argument file is writable.
198 */
199 int
iswritable(file)200 iswritable (file)
201 const char *file;
202 {
203 return isaccessible(file, W_OK);
204 }
205
206 /*
207 * Returns non-zero if the argument file is accessable according to
208 * mode. If compiled with SETXID_SUPPORT also works if cvs has setxid
209 * bits set.
210 */
211 int
isaccessible(file,mode)212 isaccessible (file, mode)
213 const char *file;
214 const int mode;
215 {
216 #ifdef SETXID_SUPPORT
217 struct stat sb;
218 int umask = 0;
219 int gmask = 0;
220 int omask = 0;
221 int uid, mask;
222
223 if (stat(file, &sb) == -1)
224 return 0;
225 if (mode == F_OK)
226 return 1;
227
228 uid = geteuid();
229 if (uid == 0) /* superuser */
230 {
231 if (!(mode & X_OK) || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
232 return 1;
233
234 errno = EACCES;
235 return 0;
236 }
237
238 if (mode & R_OK)
239 {
240 umask |= S_IRUSR;
241 gmask |= S_IRGRP;
242 omask |= S_IROTH;
243 }
244 if (mode & W_OK)
245 {
246 umask |= S_IWUSR;
247 gmask |= S_IWGRP;
248 omask |= S_IWOTH;
249 }
250 if (mode & X_OK)
251 {
252 umask |= S_IXUSR;
253 gmask |= S_IXGRP;
254 omask |= S_IXOTH;
255 }
256
257 mask = sb.st_uid == uid ? umask : sb.st_gid == getegid() ? gmask : omask;
258 if ((sb.st_mode & mask) == mask)
259 return 1;
260 errno = EACCES;
261 return 0;
262 #else
263 return access(file, mode) == 0;
264 #endif
265 }
266
267 /*
268 * Open a file and die if it fails
269 */
270 FILE *
open_file(name,mode)271 open_file (name, mode)
272 const char *name;
273 const char *mode;
274 {
275 FILE *fp;
276
277 if ((fp = fopen (name, mode)) == NULL)
278 error (1, errno, "cannot open %s", name);
279 return (fp);
280 }
281
282 /*
283 * Make a directory and die if it fails
284 */
285 void
make_directory(name)286 make_directory (name)
287 const char *name;
288 {
289 struct stat sb;
290
291 if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
292 error (0, 0, "%s already exists but is not a directory", name);
293 if (!noexec && mkdir (name, 0777) < 0)
294 error (1, errno, "cannot make directory %s", name);
295 }
296
297 /*
298 * Make a path to the argument directory, printing a message if something
299 * goes wrong.
300 */
301 void
make_directories(name)302 make_directories (name)
303 const char *name;
304 {
305 char *cp;
306
307 if (noexec)
308 return;
309
310 if (mkdir (name, 0777) == 0 || errno == EEXIST)
311 return;
312 if (! existence_error (errno))
313 {
314 error (0, errno, "cannot make path to %s", name);
315 return;
316 }
317 if ((cp = strrchr (name, '/')) == NULL)
318 return;
319 *cp = '\0';
320 make_directories (name);
321 *cp++ = '/';
322 if (*cp == '\0')
323 return;
324 (void) mkdir (name, 0777);
325 }
326
327 /* Create directory NAME if it does not already exist; fatal error for
328 other errors. Returns 0 if directory was created; 1 if it already
329 existed. */
330 int
mkdir_if_needed(name)331 mkdir_if_needed (name)
332 const char *name;
333 {
334 if (mkdir (name, 0777) < 0)
335 {
336 int save_errno = errno;
337 if (save_errno != EEXIST && !isdir (name))
338 error (1, save_errno, "cannot make directory %s", name);
339 return 1;
340 }
341 return 0;
342 }
343
344 /*
345 * Change the mode of a file, either adding write permissions, or removing
346 * all write permissions. Either change honors the current umask setting.
347 *
348 * Don't do anything if PreservePermissions is set to `yes'. This may
349 * have unexpected consequences for some uses of xchmod.
350 */
351 void
xchmod(fname,writable)352 xchmod (fname, writable)
353 const char *fname;
354 int writable;
355 {
356 struct stat sb;
357 mode_t mode, oumask;
358
359 if (preserve_perms)
360 return;
361
362 if (stat (fname, &sb) < 0)
363 {
364 if (!noexec)
365 error (0, errno, "cannot stat %s", fname);
366 return;
367 }
368 oumask = umask (0);
369 (void) umask (oumask);
370 if (writable)
371 {
372 mode = sb.st_mode | (~oumask
373 & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0)
374 | ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0)
375 | ((sb.st_mode & S_IROTH) ? S_IWOTH : 0)));
376 }
377 else
378 {
379 mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask;
380 }
381
382 if (trace)
383 (void) fprintf (stderr, "%s-> chmod(%s,%o)\n",
384 CLIENT_SERVER_STR, fname,
385 (unsigned int) mode);
386 if (noexec)
387 return;
388
389 if (chmod (fname, mode) < 0)
390 error (0, errno, "cannot change mode of file %s", fname);
391 }
392
393 /*
394 * Rename a file and die if it fails
395 */
396 void
rename_file(from,to)397 rename_file (from, to)
398 const char *from;
399 const char *to;
400 {
401 if (trace)
402 (void) fprintf (stderr, "%s-> rename(%s,%s)\n",
403 CLIENT_SERVER_STR, from, to);
404 if (noexec)
405 return;
406
407 if (rename (from, to) < 0)
408 error (1, errno, "cannot rename file %s to %s", from, to);
409 }
410
411 /*
412 * unlink a file, if possible.
413 */
414 int
unlink_file(f)415 unlink_file (f)
416 const char *f;
417 {
418 if (trace)
419 (void) fprintf (stderr, "%s-> unlink_file(%s)\n",
420 CLIENT_SERVER_STR, f);
421 if (noexec)
422 return (0);
423
424 return (CVS_UNLINK (f));
425 }
426
427 /*
428 * Unlink a file or dir, if possible. If it is a directory do a deep
429 * removal of all of the files in the directory. Return -1 on error
430 * (in which case errno is set).
431 */
432 int
unlink_file_dir(f)433 unlink_file_dir (f)
434 const char *f;
435 {
436 struct stat sb;
437
438 /* This is called by the server parent process in contexts where
439 it is not OK to send output (e.g. after we sent "ok" to the
440 client). */
441 if (trace && !server_active)
442 (void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f);
443
444 if (noexec)
445 return (0);
446
447 /* For at least some unices, if root tries to unlink() a directory,
448 instead of doing something rational like returning EISDIR,
449 the system will gleefully go ahead and corrupt the filesystem.
450 So we first call stat() to see if it is OK to call unlink(). This
451 doesn't quite work--if someone creates a directory between the
452 call to stat() and the call to unlink(), we'll still corrupt
453 the filesystem. Where is the Unix Haters Handbook when you need
454 it? */
455 if (stat (f, &sb) < 0)
456 {
457 if (existence_error (errno))
458 {
459 /* The file or directory doesn't exist anyhow. */
460 return -1;
461 }
462 }
463 else if (S_ISDIR (sb.st_mode))
464 return deep_remove_dir (f);
465
466 return CVS_UNLINK (f);
467 }
468
469 /* Remove a directory and everything it contains. Returns 0 for
470 * success, -1 for failure (in which case errno is set).
471 */
472
473 static int
deep_remove_dir(path)474 deep_remove_dir (path)
475 const char *path;
476 {
477 DIR *dirp;
478 struct dirent *dp;
479
480 if (rmdir (path) != 0)
481 {
482 if (errno == ENOTEMPTY
483 || errno == EEXIST
484 /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
485 (it defines ENOTEMPTY and EEXIST to 17 but actually
486 returns 87). */
487 || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
488 {
489 if ((dirp = CVS_OPENDIR (path)) == NULL)
490 /* If unable to open the directory return
491 * an error
492 */
493 return -1;
494
495 errno = 0;
496 while ((dp = CVS_READDIR (dirp)) != NULL)
497 {
498 char *buf;
499
500 if (strcmp (dp->d_name, ".") == 0 ||
501 strcmp (dp->d_name, "..") == 0)
502 continue;
503
504 buf = xmalloc (strlen (path) + strlen (dp->d_name) + 5);
505 sprintf (buf, "%s/%s", path, dp->d_name);
506
507 /* See comment in unlink_file_dir explanation of why we use
508 isdir instead of just calling unlink and checking the
509 status. */
510 if (isdir(buf))
511 {
512 if (deep_remove_dir(buf))
513 {
514 CVS_CLOSEDIR(dirp);
515 free (buf);
516 return -1;
517 }
518 }
519 else
520 {
521 if (CVS_UNLINK (buf) != 0)
522 {
523 CVS_CLOSEDIR(dirp);
524 free (buf);
525 return -1;
526 }
527 }
528 free (buf);
529
530 errno = 0;
531 }
532 if (errno != 0)
533 {
534 int save_errno = errno;
535 CVS_CLOSEDIR (dirp);
536 errno = save_errno;
537 return -1;
538 }
539 CVS_CLOSEDIR (dirp);
540 return rmdir (path);
541 }
542 else
543 return -1;
544 }
545
546 /* Was able to remove the directory return 0 */
547 return 0;
548 }
549
550 /* Read NCHARS bytes from descriptor FD into BUF.
551 Return the number of characters successfully read.
552 The number returned is always NCHARS unless end-of-file or error. */
553 static size_t
block_read(fd,buf,nchars)554 block_read (fd, buf, nchars)
555 int fd;
556 char *buf;
557 size_t nchars;
558 {
559 char *bp = buf;
560 size_t nread;
561
562 do
563 {
564 nread = read (fd, bp, nchars);
565 if (nread == (size_t)-1)
566 {
567 #ifdef EINTR
568 if (errno == EINTR)
569 continue;
570 #endif
571 return (size_t)-1;
572 }
573
574 if (nread == 0)
575 break;
576
577 bp += nread;
578 nchars -= nread;
579 } while (nchars != 0);
580
581 return bp - buf;
582 }
583
584
585 /*
586 * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
587 * If FILE1 and FILE2 are special files, compare their salient characteristics
588 * (i.e. major/minor device numbers, links, etc.
589 */
590 int
xcmp(file1,file2)591 xcmp (file1, file2)
592 const char *file1;
593 const char *file2;
594 {
595 char *buf1, *buf2;
596 struct stat sb1, sb2;
597 int fd1, fd2;
598 int ret;
599
600 if (CVS_LSTAT (file1, &sb1) < 0)
601 error (1, errno, "cannot lstat %s", file1);
602 if (CVS_LSTAT (file2, &sb2) < 0)
603 error (1, errno, "cannot lstat %s", file2);
604
605 /* If FILE1 and FILE2 are not the same file type, they are unequal. */
606 if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
607 return 1;
608
609 /* If FILE1 and FILE2 are symlinks, they are equal if they point to
610 the same thing. */
611 #ifdef S_ISLNK
612 if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
613 {
614 int result;
615 buf1 = xreadlink (file1);
616 buf2 = xreadlink (file2);
617 result = (strcmp (buf1, buf2) == 0);
618 free (buf1);
619 free (buf2);
620 return result;
621 }
622 #endif
623
624 /* If FILE1 and FILE2 are devices, they are equal if their device
625 numbers match. */
626 if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
627 {
628 #ifdef HAVE_STRUCT_STAT_ST_RDEV
629 if (sb1.st_rdev == sb2.st_rdev)
630 return 0;
631 else
632 return 1;
633 #else
634 error (1, 0, "cannot compare device files on this system (%s and %s)",
635 file1, file2);
636 #endif
637 }
638
639 if ((fd1 = open (file1, O_RDONLY)) < 0)
640 error (1, errno, "cannot open file %s for comparing", file1);
641 if ((fd2 = open (file2, O_RDONLY)) < 0)
642 error (1, errno, "cannot open file %s for comparing", file2);
643
644 /* A generic file compare routine might compare st_dev & st_ino here
645 to see if the two files being compared are actually the same file.
646 But that won't happen in CVS, so we won't bother. */
647
648 if (sb1.st_size != sb2.st_size)
649 ret = 1;
650 else if (sb1.st_size == 0)
651 ret = 0;
652 else
653 {
654 /* FIXME: compute the optimal buffer size by computing the least
655 common multiple of the files st_blocks field */
656 size_t buf_size = 8 * 1024;
657 size_t read1;
658 size_t read2;
659
660 buf1 = xmalloc (buf_size);
661 buf2 = xmalloc (buf_size);
662
663 do
664 {
665 read1 = block_read (fd1, buf1, buf_size);
666 if (read1 == (size_t)-1)
667 error (1, errno, "cannot read file %s for comparing", file1);
668
669 read2 = block_read (fd2, buf2, buf_size);
670 if (read2 == (size_t)-1)
671 error (1, errno, "cannot read file %s for comparing", file2);
672
673 /* assert (read1 == read2); */
674
675 ret = memcmp(buf1, buf2, read1);
676 } while (ret == 0 && read1 == buf_size);
677
678 free (buf1);
679 free (buf2);
680 }
681
682 (void) close (fd1);
683 (void) close (fd2);
684 return (ret);
685 }
686
687 /* Generate a unique temporary filename. Returns a pointer to a newly
688 * malloc'd string containing the name. Returns successfully or not at
689 * all.
690 *
691 * THIS FUNCTION IS DEPRECATED!!! USE cvs_temp_file INSTEAD!!!
692 *
693 * and yes, I know about the way the rcs commands use temp files. I think
694 * they should be converted too but I don't have time to look into it right
695 * now.
696 */
697 char *
cvs_temp_name()698 cvs_temp_name ()
699 {
700 char *fn;
701 FILE *fp;
702
703 fp = cvs_temp_file (&fn);
704 if (fp == NULL)
705 error (1, errno, "Failed to create temporary file %s",
706 fn ? fn : "(null)");
707 if (fclose (fp) == EOF)
708 error (0, errno, "Failed to close temporary file %s", fn);
709 return fn;
710 }
711
712 /* Generate a unique temporary filename and return an open file stream
713 * to the truncated file by that name
714 *
715 * INPUTS
716 * filename where to place the pointer to the newly allocated file
717 * name string
718 *
719 * OUTPUTS
720 * filename dereferenced, will point to the newly allocated file
721 * name string. This value is undefined if the function
722 * returns an error.
723 *
724 * RETURNS
725 * An open file pointer to a read/write mode empty temporary file with the
726 * unique file name or NULL on failure.
727 *
728 * ERRORS
729 * on error, errno will be set to some value either by CVS_FOPEN or
730 * whatever system function is called to generate the temporary file name
731 */
732 /* There are at least four functions for generating temporary
733 * filenames. We use mkstemp (BSD 4.3) if possible, else tempnam (SVID 3),
734 * else mktemp (BSD 4.3), and as last resort tmpnam (POSIX). Reason is that
735 * mkstemp, tempnam, and mktemp both allow to specify the directory in which
736 * the temporary file will be created.
737 *
738 * And the _correct_ way to use the deprecated functions probably involves
739 * opening file descriptors using O_EXCL & O_CREAT and even doing the annoying
740 * NFS locking thing, but until I hear of more problems, I'm not going to
741 * bother.
742 */
743 FILE *
cvs_temp_file(filename)744 cvs_temp_file (filename)
745 char **filename;
746 {
747 char *fn;
748 FILE *fp;
749
750 /* FIXME - I'd like to be returning NULL here in noexec mode, but I think
751 * some of the rcs & diff functions which rely on a temp file run in
752 * noexec mode too.
753 */
754
755 assert (filename != NULL);
756
757 #ifdef HAVE_MKSTEMP
758
759 {
760 int fd;
761
762 fn = xmalloc (strlen (Tmpdir) + 11);
763 sprintf (fn, "%s/%s", Tmpdir, "cvsXXXXXX" );
764 fd = mkstemp (fn);
765
766 /* a NULL return will be interpreted by callers as an error and
767 * errno should still be set
768 */
769 if (fd == -1) fp = NULL;
770 else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL)
771 {
772 /* Attempt to close and unlink the file since mkstemp returned
773 * sucessfully and we believe it's been created and opened.
774 */
775 int save_errno = errno;
776 if (close (fd))
777 error (0, errno, "Failed to close temporary file %s", fn);
778 if (CVS_UNLINK (fn))
779 error (0, errno, "Failed to unlink temporary file %s", fn);
780 errno = save_errno;
781 }
782
783 if (fp == NULL)
784 {
785 free (fn);
786 fn = NULL;
787 }
788 /* mkstemp is defined to open mode 0600 using glibc 2.0.7+ */
789 /* FIXME - configure can probably tell us which version of glibc we are
790 * linking to and not chmod for 2.0.7+
791 */
792 else chmod (fn, 0600);
793
794 }
795
796 #elif HAVE_TEMPNAM
797
798 /* tempnam has been deprecated due to under-specification */
799
800 fn = tempnam (Tmpdir, "cvs");
801 if (fn == NULL) fp = NULL;
802 else if ((fp = CVS_FOPEN (fn, "w+")) == NULL)
803 {
804 free (fn);
805 fn = NULL;
806 }
807 else chmod (fn, 0600);
808
809 /* tempnam returns a pointer to a newly malloc'd string, so there's
810 * no need for a xstrdup
811 */
812
813 #elif HAVE_MKTEMP
814
815 /* mktemp has been deprecated due to the BSD 4.3 specification specifying
816 * that XXXXXX will be replaced by a PID and a letter, creating only 26
817 * possibilities, a security risk, and a race condition.
818 */
819
820 {
821 char *ifn;
822
823 ifn = xmalloc (strlen (Tmpdir) + 11);
824 sprintf (ifn, "%s/%s", Tmpdir, "cvsXXXXXX" );
825 fn = mktemp (ifn);
826
827 if (fn == NULL) fp = NULL;
828 else fp = CVS_FOPEN (fn, "w+");
829
830 if (fp == NULL) free (ifn);
831 else chmod (fn, 0600);
832
833 }
834
835 #else /* use tmpnam if all else fails */
836
837 /* tmpnam is deprecated */
838
839 {
840 char ifn[L_tmpnam + 1];
841
842 fn = tmpnam (ifn);
843
844 if (fn == NULL) fp = NULL;
845 else if ((fp = CVS_FOPEN (ifn, "w+")) != NULL)
846 {
847 fn = xstrdup (ifn);
848 chmod (fn, 0600);
849 }
850
851 }
852
853 #endif
854
855 *filename = fn;
856 if (fn == NULL && fp != NULL)
857 {
858 fclose (fp);
859 fp = NULL;
860 }
861 return fp;
862 }
863
864
865
866 #ifdef HAVE_READLINK
867 /* char *
868 * xreadlink ( const char *link )
869 *
870 * Like the X/OPEN and 4.4BSD readlink() function, but allocates and returns
871 * its own buf.
872 *
873 * INPUTS
874 * link The original path.
875 *
876 * RETURNS
877 * The resolution of the final symbolic link in the path.
878 *
879 * ERRORS
880 * This function exits with a fatal error if it fails to read the link for
881 * any reason.
882 */
883 #define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX)
884
885 char *
xreadlink(link)886 xreadlink (link)
887 const char *link;
888 {
889 char *file = NULL;
890 size_t buflen = BUFSIZ;
891
892 /* Get the name of the file to which `from' is linked. */
893 while (1)
894 {
895 ssize_t r;
896 size_t link_name_len;
897
898 file = xrealloc (file, buflen);
899 r = readlink (link, file, buflen);
900 link_name_len = r;
901
902 if (r < 0
903 #ifdef ERANGE
904 /* AIX 4 and HP-UX report ERANGE if the buffer is too small. */
905 && errno != ERANGE
906 #endif
907 )
908 error (1, errno, "cannot readlink %s", link);
909
910 /* If there is space for the NUL byte, set it and return. */
911 if (r >= 0 && link_name_len < buflen)
912 {
913 file[link_name_len] = '\0';
914 return file;
915 }
916
917 if (buflen <= MAXSIZE / 2)
918 buflen *= 2;
919 else if (buflen < MAXSIZE)
920 buflen = MAXSIZE;
921 else
922 /* Our buffer cannot grow any bigger. */
923 error (1, ENAMETOOLONG, "cannot readlink %s", link);
924 }
925 }
926 #endif /* HAVE_READLINK */
927
928
929
930 /* char *
931 * xresolvepath ( const char *path )
932 *
933 * Like xreadlink(), but resolve all links in a path.
934 *
935 * INPUTS
936 * path The original path.
937 *
938 * RETURNS
939 * The path with any symbolic links expanded.
940 *
941 * ERRORS
942 * This function exits with a fatal error if it fails to read the link for
943 * any reason.
944 */
945 char *
xresolvepath(path)946 xresolvepath ( path )
947 const char *path;
948 {
949 char *hardpath;
950 char *owd;
951
952 assert ( isdir ( path ) );
953
954 /* FIXME - If HAVE_READLINK is defined, we should probably walk the path
955 * bit by bit calling xreadlink().
956 */
957
958 owd = xgetwd();
959 if ( CVS_CHDIR ( path ) < 0)
960 error ( 1, errno, "cannot chdir to %s", path );
961 if ( ( hardpath = xgetwd() ) == NULL )
962 error (1, errno, "cannot getwd in %s", path);
963 if ( CVS_CHDIR ( owd ) < 0)
964 error ( 1, errno, "cannot chdir to %s", owd );
965 free (owd);
966 return hardpath;
967 }
968
969
970
971 /* Return a pointer into PATH's last component. */
972 const char *
last_component(path)973 last_component (path)
974 const char *path;
975 {
976 const char *last = strrchr (path, '/');
977
978 assert (path);
979 if (last && (last != path))
980 return last + 1;
981 else
982 return path;
983 }
984
985 /* Return the home directory. Returns a pointer to storage
986 managed by this function or its callees (currently getenv).
987 This function will return the same thing every time it is
988 called. Returns NULL if there is no home directory.
989
990 Note that for a pserver server, this may return root's home
991 directory. What typically happens is that upon being started from
992 inetd, before switching users, the code in cvsrc.c calls
993 get_homedir which remembers root's home directory in the static
994 variable. Then the switch happens and get_homedir might return a
995 directory that we don't even have read or execute permissions for
996 (which is bad, when various parts of CVS try to read there). One
997 fix would be to make the value returned by get_homedir only good
998 until the next call (which would free the old value). Another fix
999 would be to just always malloc our answer, and let the caller free
1000 it (that is best, because some day we may need to be reentrant).
1001
1002 The workaround is to put -f in inetd.conf which means that
1003 get_homedir won't get called until after the switch in user ID.
1004
1005 The whole concept of a "home directory" on the server is pretty
1006 iffy, although I suppose some people probably are relying on it for
1007 .cvsrc and such, in the cases where it works. */
1008 char *
get_homedir()1009 get_homedir ()
1010 {
1011 static char *home = NULL;
1012 char *env;
1013 struct passwd *pw;
1014
1015 if (home != NULL)
1016 return home;
1017
1018 if (!server_active && (env = getenv ("HOME")) != NULL)
1019 home = env;
1020 else if ((pw = (struct passwd *) getpwuid (getuid ()))
1021 && pw->pw_dir)
1022 home = xstrdup (pw->pw_dir);
1023 else
1024 return 0;
1025
1026 return home;
1027 }
1028
1029 /* Compose a path to a file in the home directory. This is necessary because
1030 * of different behavior on UNIX and VMS. See the notes in vms/filesubr.c.
1031 *
1032 * A more clean solution would be something more along the lines of a
1033 * "join a directory to a filename" kind of thing which was not specific to
1034 * the homedir. This should aid portability between UNIX, Mac, Windows, VMS,
1035 * and possibly others. This is already handled by Perl - it might be
1036 * interesting to see how much of the code was written in C since Perl is under
1037 * the GPL and the Artistic license - we might be able to use it.
1038 */
1039 char *
strcat_filename_onto_homedir(dir,file)1040 strcat_filename_onto_homedir (dir, file)
1041 const char *dir;
1042 const char *file;
1043 {
1044 char *path = xmalloc (strlen (dir) + 1 + strlen(file) + 1);
1045 sprintf (path, "%s/%s", dir, file);
1046 return path;
1047 }
1048
1049 /* See cvs.h for description. On unix this does nothing, because the
1050 shell expands the wildcards. */
1051 void
expand_wild(argc,argv,pargc,pargv)1052 expand_wild (argc, argv, pargc, pargv)
1053 int argc;
1054 char **argv;
1055 int *pargc;
1056 char ***pargv;
1057 {
1058 int i;
1059 assert (argv || !argc);
1060 if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
1061 *pargc = 0;
1062 *pargv = NULL;
1063 error (0, 0, "expand_wild: too many arguments");
1064 return;
1065 }
1066 *pargc = argc;
1067 *pargv = xmalloc (xtimes (argc, sizeof (char *)));
1068 for (i = 0; i < argc; ++i)
1069 (*pargv)[i] = xstrdup (argv[i]);
1070 }
1071
1072
1073
1074 #ifdef SERVER_SUPPORT
1075 /* Case-insensitive string compare. I know that some systems
1076 have such a routine, but I'm not sure I see any reasons for
1077 dealing with the hair of figuring out whether they do (I haven't
1078 looked into whether this is a performance bottleneck; I would guess
1079 not). */
1080 int
cvs_casecmp(str1,str2)1081 cvs_casecmp (str1, str2)
1082 const char *str1;
1083 const char *str2;
1084 {
1085 const char *p;
1086 const char *q;
1087 int pqdiff;
1088
1089 p = str1;
1090 q = str2;
1091 while ((pqdiff = tolower (*p) - tolower (*q)) == 0)
1092 {
1093 if (*p == '\0')
1094 return 0;
1095 ++p;
1096 ++q;
1097 }
1098 return pqdiff;
1099 }
1100 #endif /* SERVER_SUPPORT */
1101