HAMMER Utilities: Sync with 59A
[dragonfly.git] / contrib / cvs-1.12 / src / filesubr.c
blob64e9f4be7a2770bee7fdefb03515ade3bab1d327
1 /* filesubr.c --- subroutines for dealing with files
2 Jim Blandy <jimb@cyclic.com>
4 This file is part of GNU CVS.
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.
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. */
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. */
20 #include "cvs.h"
21 #include "lstat.h"
22 #include "save-cwd.h"
23 #include "xsize.h"
25 static int deep_remove_dir (const char *path);
28 * Copies "from" to "to".
30 void
31 copy_file (const char *from, const char *to)
33 struct stat sb;
34 struct utimbuf t;
35 int fdin, fdout;
36 ssize_t rsize;
38 TRACE (TRACE_FUNCTION, "copy(%s,%s)", from, to);
40 if (noexec)
41 return;
43 /* If the file to be copied is a link or a device, then just create
44 the new link or device appropriately. */
45 if ((rsize = islink (from)) > 0)
47 char *source = Xreadlink (from, rsize);
48 symlink (source, to);
49 free (source);
50 return;
53 if (isdevice (from))
55 #if defined(HAVE_MKNOD) && defined(HAVE_STRUCT_STAT_ST_RDEV)
56 if (stat (from, &sb) < 0)
57 error (1, errno, "cannot stat %s", from);
58 mknod (to, sb.st_mode, sb.st_rdev);
59 #else
60 error (1, 0, "cannot copy device files on this system (%s)", from);
61 #endif
63 else
65 /* Not a link or a device... probably a regular file. */
66 if ((fdin = open (from, O_RDONLY)) < 0)
67 error (1, errno, "cannot open %s for copying", from);
68 if (fstat (fdin, &sb) < 0)
69 error (1, errno, "cannot fstat %s", from);
70 if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
71 error (1, errno, "cannot create %s for copying", to);
72 if (sb.st_size > 0)
74 char buf[BUFSIZ];
75 int n;
77 for (;;)
79 n = read (fdin, buf, sizeof(buf));
80 if (n == -1)
82 #ifdef EINTR
83 if (errno == EINTR)
84 continue;
85 #endif
86 error (1, errno, "cannot read file %s for copying", from);
88 else if (n == 0)
89 break;
91 if (write(fdout, buf, n) != n) {
92 error (1, errno, "cannot write file %s for copying", to);
97 if (close (fdin) < 0)
98 error (0, errno, "cannot close %s", from);
99 if (close (fdout) < 0)
100 error (1, errno, "cannot close %s", to);
103 /* preserve last access & modification times */
104 memset ((char *) &t, 0, sizeof (t));
105 t.actime = sb.st_atime;
106 t.modtime = sb.st_mtime;
107 (void) utime (to, &t);
112 /* FIXME-krp: these functions would benefit from caching the char * &
113 stat buf. */
116 * Returns true if the argument file is a directory, or is a symbolic
117 * link which points to a directory.
119 bool
120 isdir (const char *file)
122 struct stat sb;
124 if (stat (file, &sb) < 0)
125 return false;
126 return S_ISDIR (sb.st_mode);
132 * Returns 0 if the argument file is not a symbolic link.
133 * Returns size of the link if it is a symbolic link.
135 ssize_t
136 islink (const char *file)
138 ssize_t retsize = 0;
139 #ifdef S_ISLNK
140 struct stat sb;
142 if ((lstat (file, &sb) >= 0) && S_ISLNK (sb.st_mode))
143 retsize = sb.st_size;
144 #endif
145 return retsize;
151 * Returns true if the argument file is a block or
152 * character special device.
154 bool
155 isdevice (const char *file)
157 struct stat sb;
159 if (lstat (file, &sb) < 0)
160 return false;
161 #ifdef S_ISBLK
162 if (S_ISBLK (sb.st_mode))
163 return true;
164 #endif
165 #ifdef S_ISCHR
166 if (S_ISCHR (sb.st_mode))
167 return true;
168 #endif
169 return false;
175 * Returns true if the argument file exists.
177 bool
178 isfile (const char *file)
180 return isaccessible (file, F_OK);
186 * Returns non-zero if the argument file is readable.
188 bool
189 isreadable (const char *file)
191 return isaccessible (file, R_OK);
197 * Returns non-zero if the argument file is writable.
199 bool
200 iswritable (const char *file)
202 return isaccessible (file, W_OK);
208 * Returns true if the argument file is accessable according to
209 * mode. If compiled with SETXID_SUPPORT also works if cvs has setxid
210 * bits set.
212 bool
213 isaccessible (const char *file, const int mode)
215 #ifdef SETXID_SUPPORT
216 struct stat sb;
217 int umask = 0;
218 int gmask = 0;
219 int omask = 0;
220 int uid, mask;
222 if (stat (file, &sb)== -1)
223 return false;
224 if (mode == F_OK)
225 return true;
227 uid = geteuid();
228 if (uid == 0) /* superuser */
230 if (!(mode & X_OK) || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
231 return true;
233 errno = EACCES;
234 return false;
237 if (mode & R_OK)
239 umask |= S_IRUSR;
240 gmask |= S_IRGRP;
241 omask |= S_IROTH;
243 if (mode & W_OK)
245 umask |= S_IWUSR;
246 gmask |= S_IWGRP;
247 omask |= S_IWOTH;
249 if (mode & X_OK)
251 umask |= S_IXUSR;
252 gmask |= S_IXGRP;
253 omask |= S_IXOTH;
256 mask = sb.st_uid == uid ? umask : sb.st_gid == getegid() ? gmask : omask;
257 if ((sb.st_mode & mask) == mask)
258 return true;
259 errno = EACCES;
260 return false;
261 #else /* !SETXID_SUPPORT */
262 return access (file, mode) == 0;
263 #endif /* SETXID_SUPPORT */
269 * Make a directory and die if it fails
271 void
272 make_directory (const char *name)
274 struct stat sb;
276 if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
277 error (0, 0, "%s already exists but is not a directory", name);
278 if (!noexec && mkdir (name, 0777) < 0)
279 error (1, errno, "cannot make directory %s", name);
283 * Make a path to the argument directory, printing a message if something
284 * goes wrong.
286 void
287 make_directories (const char *name)
289 char *cp;
291 if (noexec)
292 return;
294 if (mkdir (name, 0777) == 0 || errno == EEXIST)
295 return;
296 if (! existence_error (errno))
298 error (0, errno, "cannot make path to %s", name);
299 return;
301 if ((cp = strrchr (name, '/')) == NULL)
302 return;
303 *cp = '\0';
304 make_directories (name);
305 *cp++ = '/';
306 if (*cp == '\0')
307 return;
308 (void) mkdir (name, 0777);
311 /* Create directory NAME if it does not already exist; fatal error for
312 other errors. Returns 0 if directory was created; 1 if it already
313 existed. */
315 mkdir_if_needed (const char *name)
317 if (mkdir (name, 0777) < 0)
319 int save_errno = errno;
320 if (save_errno != EEXIST && !isdir (name))
321 error (1, save_errno, "cannot make directory %s", name);
322 return 1;
324 return 0;
328 * Change the mode of a file, either adding write permissions, or removing
329 * all write permissions. Either change honors the current umask setting.
331 * Don't do anything if PreservePermissions is set to `yes'. This may
332 * have unexpected consequences for some uses of xchmod.
334 void
335 xchmod (const char *fname, int writable)
337 struct stat sb;
338 mode_t mode, oumask;
340 #ifdef PRESERVE_PERMISSIONS_SUPPORT
341 if (config->preserve_perms)
342 return;
343 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
345 if (stat (fname, &sb) < 0)
347 if (!noexec)
348 error (0, errno, "cannot stat %s", fname);
349 return;
351 oumask = umask (0);
352 (void) umask (oumask);
353 if (writable)
355 mode = sb.st_mode | (~oumask
356 & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0)
357 | ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0)
358 | ((sb.st_mode & S_IROTH) ? S_IWOTH : 0)));
360 else
362 mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask;
365 TRACE (TRACE_FUNCTION, "chmod(%s,%o)", fname, (unsigned int) mode);
367 if (noexec)
368 return;
370 if (chmod (fname, mode) < 0)
371 error (0, errno, "cannot change mode of file %s", fname);
375 * Rename a file and die if it fails
377 void
378 rename_file (const char *from, const char *to)
380 TRACE (TRACE_FUNCTION, "rename(%s,%s)", from, to);
382 if (noexec)
383 return;
385 if (rename (from, to) < 0)
386 error (1, errno, "cannot rename file %s to %s", from, to);
390 * unlink a file, if possible.
393 unlink_file (const char *f)
395 TRACE (TRACE_FUNCTION, "unlink_file(%s)", f);
397 if (noexec)
398 return (0);
400 return (CVS_UNLINK (f));
406 * Unlink a file or dir, if possible. If it is a directory do a deep
407 * removal of all of the files in the directory. Return -1 on error
408 * (in which case errno is set).
411 unlink_file_dir (const char *f)
413 struct stat sb;
415 /* This is called by the server parent process in contexts where
416 it is not OK to send output (e.g. after we sent "ok" to the
417 client). */
418 if (!server_active)
419 TRACE (TRACE_FUNCTION, "unlink_file_dir(%s)", f);
421 if (noexec)
422 return 0;
424 /* For at least some unices, if root tries to unlink() a directory,
425 instead of doing something rational like returning EISDIR,
426 the system will gleefully go ahead and corrupt the filesystem.
427 So we first call stat() to see if it is OK to call unlink(). This
428 doesn't quite work--if someone creates a directory between the
429 call to stat() and the call to unlink(), we'll still corrupt
430 the filesystem. Where is the Unix Haters Handbook when you need
431 it? */
432 if (stat (f, &sb) < 0)
434 if (existence_error (errno))
436 /* The file or directory doesn't exist anyhow. */
437 return -1;
440 else if (S_ISDIR (sb.st_mode))
441 return deep_remove_dir (f);
443 return CVS_UNLINK (f);
448 /* Remove a directory and everything it contains. Returns 0 for
449 * success, -1 for failure (in which case errno is set).
452 static int
453 deep_remove_dir (const char *path)
455 DIR *dirp;
456 struct dirent *dp;
458 if (rmdir (path) != 0)
460 if (errno == ENOTEMPTY
461 || errno == EEXIST
462 /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
463 (it defines ENOTEMPTY and EEXIST to 17 but actually
464 returns 87). */
465 || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
467 if ((dirp = CVS_OPENDIR (path)) == NULL)
468 /* If unable to open the directory return
469 * an error
471 return -1;
473 errno = 0;
474 while ((dp = CVS_READDIR (dirp)) != NULL)
476 char *buf;
478 if (strcmp (dp->d_name, ".") == 0 ||
479 strcmp (dp->d_name, "..") == 0)
480 continue;
482 buf = Xasprintf ("%s/%s", path, dp->d_name);
484 /* See comment in unlink_file_dir explanation of why we use
485 isdir instead of just calling unlink and checking the
486 status. */
487 if (isdir (buf))
489 if (deep_remove_dir (buf))
491 CVS_CLOSEDIR (dirp);
492 free (buf);
493 return -1;
496 else
498 if (CVS_UNLINK (buf) != 0)
500 CVS_CLOSEDIR (dirp);
501 free (buf);
502 return -1;
505 free (buf);
507 errno = 0;
509 if (errno != 0)
511 int save_errno = errno;
512 CVS_CLOSEDIR (dirp);
513 errno = save_errno;
514 return -1;
516 CVS_CLOSEDIR (dirp);
517 return rmdir (path);
519 else
520 return -1;
523 /* Was able to remove the directory return 0 */
524 return 0;
529 /* Read NCHARS bytes from descriptor FD into BUF.
530 Return the number of characters successfully read.
531 The number returned is always NCHARS unless end-of-file or error. */
532 static size_t
533 block_read (int fd, char *buf, size_t nchars)
535 char *bp = buf;
536 size_t nread;
540 nread = read (fd, bp, nchars);
541 if (nread == (size_t)-1)
543 #ifdef EINTR
544 if (errno == EINTR)
545 continue;
546 #endif
547 return (size_t)-1;
550 if (nread == 0)
551 break;
553 bp += nread;
554 nchars -= nread;
555 } while (nchars != 0);
557 return bp - buf;
562 * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
563 * If FILE1 and FILE2 are special files, compare their salient characteristics
564 * (i.e. major/minor device numbers, links, etc.
567 xcmp (const char *file1, const char *file2)
569 char *buf1, *buf2;
570 struct stat sb1, sb2;
571 int fd1, fd2;
572 int ret;
574 if (lstat (file1, &sb1) < 0)
575 error (1, errno, "cannot lstat %s", file1);
576 if (lstat (file2, &sb2) < 0)
577 error (1, errno, "cannot lstat %s", file2);
579 /* If FILE1 and FILE2 are not the same file type, they are unequal. */
580 if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
581 return 1;
583 /* If FILE1 and FILE2 are symlinks, they are equal if they point to
584 the same thing. */
585 #ifdef S_ISLNK
586 if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
588 int result;
589 buf1 = Xreadlink (file1, sb1.st_size);
590 buf2 = Xreadlink (file2, sb2.st_size);
591 result = (strcmp (buf1, buf2) == 0);
592 free (buf1);
593 free (buf2);
594 return result;
596 #endif
598 /* If FILE1 and FILE2 are devices, they are equal if their device
599 numbers match. */
600 if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
602 #ifdef HAVE_STRUCT_STAT_ST_RDEV
603 if (sb1.st_rdev == sb2.st_rdev)
604 return 0;
605 else
606 return 1;
607 #else
608 error (1, 0, "cannot compare device files on this system (%s and %s)",
609 file1, file2);
610 #endif
613 if ((fd1 = open (file1, O_RDONLY)) < 0)
614 error (1, errno, "cannot open file %s for comparing", file1);
615 if ((fd2 = open (file2, O_RDONLY)) < 0)
616 error (1, errno, "cannot open file %s for comparing", file2);
618 /* A generic file compare routine might compare st_dev & st_ino here
619 to see if the two files being compared are actually the same file.
620 But that won't happen in CVS, so we won't bother. */
622 if (sb1.st_size != sb2.st_size)
623 ret = 1;
624 else if (sb1.st_size == 0)
625 ret = 0;
626 else
628 /* FIXME: compute the optimal buffer size by computing the least
629 common multiple of the files st_blocks field */
630 size_t buf_size = 8 * 1024;
631 size_t read1;
632 size_t read2;
634 buf1 = xmalloc (buf_size);
635 buf2 = xmalloc (buf_size);
639 read1 = block_read (fd1, buf1, buf_size);
640 if (read1 == (size_t)-1)
641 error (1, errno, "cannot read file %s for comparing", file1);
643 read2 = block_read (fd2, buf2, buf_size);
644 if (read2 == (size_t)-1)
645 error (1, errno, "cannot read file %s for comparing", file2);
647 /* assert (read1 == read2); */
649 ret = memcmp(buf1, buf2, read1);
650 } while (ret == 0 && read1 == buf_size);
652 free (buf1);
653 free (buf2);
656 (void) close (fd1);
657 (void) close (fd2);
658 return (ret);
661 /* Generate a unique temporary filename. Returns a pointer to a newly
662 * malloc'd string containing the name. Returns successfully or not at
663 * all.
665 * THIS FUNCTION IS DEPRECATED!!! USE cvs_temp_file INSTEAD!!!
667 * and yes, I know about the way the rcs commands use temp files. I think
668 * they should be converted too but I don't have time to look into it right
669 * now.
671 char *
672 cvs_temp_name (void)
674 char *fn;
675 FILE *fp;
677 fp = cvs_temp_file (&fn);
678 if (fp == NULL)
679 error (1, errno, "Failed to create temporary file");
680 if (fclose (fp) == EOF)
681 error (0, errno, "Failed to close temporary file %s", fn);
682 return fn;
685 /* Generate a unique temporary filename and return an open file stream
686 * to the truncated file by that name
688 * INPUTS
689 * filename where to place the pointer to the newly allocated file
690 * name string
692 * OUTPUTS
693 * filename dereferenced, will point to the newly allocated file
694 * name string. This value is undefined if the function
695 * returns an error.
697 * RETURNS
698 * An open file pointer to a read/write mode empty temporary file with the
699 * unique file name or NULL on failure.
701 * ERRORS
702 * On error, errno will be set to some value either by CVS_FOPEN or
703 * whatever system function is called to generate the temporary file name.
704 * The value of filename is undefined on error.
706 FILE *
707 cvs_temp_file (char **filename)
709 char *fn;
710 FILE *fp;
711 int fd;
713 /* FIXME - I'd like to be returning NULL here in noexec mode, but I think
714 * some of the rcs & diff functions which rely on a temp file run in
715 * noexec mode too.
718 assert (filename != NULL);
720 fn = Xasprintf ("%s/%s", get_cvs_tmp_dir (), "cvsXXXXXX");
721 fd = mkstemp (fn);
723 /* a NULL return will be interpreted by callers as an error and
724 * errno should still be set
726 if (fd == -1)
727 fp = NULL;
728 else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL)
730 /* Attempt to close and unlink the file since mkstemp returned
731 * sucessfully and we believe it's been created and opened.
733 int save_errno = errno;
734 if (close (fd))
735 error (0, errno, "Failed to close temporary file %s", fn);
736 if (CVS_UNLINK (fn))
737 error (0, errno, "Failed to unlink temporary file %s", fn);
738 errno = save_errno;
741 if (fp == NULL)
742 free (fn);
744 /* mkstemp is defined to open mode 0600 using glibc 2.0.7+. There used
745 * to be a complicated #ifdef checking the library versions here and then
746 * a chmod 0600 on the temp file for versions of glibc less than 2.1. This
747 * is rather a special case, leaves a race condition open regardless, and
748 * one could hope that sysadmins have read the relevant security
749 * announcements and upgraded by now to a version with a fix committed in
750 * January of 1999.
752 * If it is decided at some point that old, buggy versions of glibc should
753 * still be catered to, a umask of 0600 should be set before file creation
754 * instead then reset after file creation since this would avoid the race
755 * condition that the chmod left open to exploitation.
758 *filename = fn;
759 return fp;
764 /* Return a pointer into PATH's last component. */
765 const char *
766 last_component (const char *path)
768 const char *last = strrchr (path, '/');
770 if (last && (last != path))
771 return last + 1;
772 else
773 return path;
778 /* Return the home directory. Returns a pointer to storage
779 managed by this function or its callees (currently getenv).
780 This function will return the same thing every time it is
781 called. Returns NULL if there is no home directory.
783 Note that for a pserver server, this may return root's home
784 directory. What typically happens is that upon being started from
785 inetd, before switching users, the code in cvsrc.c calls
786 get_homedir which remembers root's home directory in the static
787 variable. Then the switch happens and get_homedir might return a
788 directory that we don't even have read or execute permissions for
789 (which is bad, when various parts of CVS try to read there). One
790 fix would be to make the value returned by get_homedir only good
791 until the next call (which would free the old value). Another fix
792 would be to just always malloc our answer, and let the caller free
793 it (that is best, because some day we may need to be reentrant).
795 The workaround is to put -f in inetd.conf which means that
796 get_homedir won't get called until after the switch in user ID.
798 The whole concept of a "home directory" on the server is pretty
799 iffy, although I suppose some people probably are relying on it for
800 .cvsrc and such, in the cases where it works. */
801 char *
802 get_homedir (void)
804 static char *home = NULL;
805 char *env;
806 struct passwd *pw;
808 if (home != NULL)
809 return home;
811 if (!server_active && (env = getenv ("HOME")) != NULL)
812 home = env;
813 else if ((pw = (struct passwd *) getpwuid (getuid ()))
814 && pw->pw_dir)
815 home = xstrdup (pw->pw_dir);
816 else
817 return 0;
819 return home;
822 /* Compose a path to a file in the home directory. This is necessary because
823 * of different behavior on UNIX and VMS. See the notes in vms/filesubr.c.
825 * A more clean solution would be something more along the lines of a
826 * "join a directory to a filename" kind of thing which was not specific to
827 * the homedir. This should aid portability between UNIX, Mac, Windows, VMS,
828 * and possibly others. This is already handled by Perl - it might be
829 * interesting to see how much of the code was written in C since Perl is under
830 * the GPL and the Artistic license - we might be able to use it.
832 char *
833 strcat_filename_onto_homedir (const char *dir, const char *file)
835 char *path = Xasprintf ("%s/%s", dir, file);
836 return path;
839 /* See cvs.h for description. On unix this does nothing, because the
840 shell expands the wildcards. */
841 void
842 expand_wild (int argc, char **argv, int *pargc, char ***pargv)
844 int i;
845 if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
846 *pargc = 0;
847 *pargv = NULL;
848 error (0, 0, "expand_wild: too many arguments");
849 return;
851 *pargc = argc;
852 *pargv = xnmalloc (argc, sizeof (char *));
853 for (i = 0; i < argc; ++i)
854 (*pargv)[i] = xstrdup (argv[i]);
859 static char *tmpdir_env;
861 /* Return path to temp directory.
863 const char *
864 get_system_temp_dir (void)
866 if (!tmpdir_env) tmpdir_env = getenv (TMPDIR_ENV);
867 return tmpdir_env;
872 void
873 push_env_temp_dir (void)
875 const char *tmpdir = get_cvs_tmp_dir ();
876 if (tmpdir_env && strcmp (tmpdir_env, tmpdir))
877 setenv (TMPDIR_ENV, tmpdir, 1);