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 "cvs.h"
21#include <sys/param.h>
22
23/*
24 * I don't know of a convenient way to test this at configure time, or else
25 * I'd certainly do it there.
26 */
27#if defined(NeXT)
28#define LOSING_TMPNAM_FUNCTION
29#endif
30
31static int deep_remove_dir PROTO((const char *path));
32
33/*
34 * Copies "from" to "to".
35 */
36void
37copy_file (from, to)
38    const char *from;
39    const char *to;
40{
41    struct stat sb;
42    struct utimbuf t;
43    int fdin, fdout;
44
45    if (trace)
46#ifdef SERVER_SUPPORT
47	(void) fprintf (stderr, "%c-> copy(%s,%s)\n",
48			(server_active) ? 'S' : ' ', from, to);
49#else
50	(void) fprintf (stderr, "-> copy(%s,%s)\n", from, to);
51#endif
52    if (noexec)
53	return;
54
55    if ((fdin = open (from, O_RDONLY | O_BINARY)) < 0)
56	error (1, errno, "cannot open %s for copying", from);
57    if (fstat (fdin, &sb) < 0)
58	error (1, errno, "cannot fstat %s", from);
59    if ((fdout = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
60					   (int) sb.st_mode & 07777)) < 0)
61	error (1, errno, "cannot create %s for copying", to);
62    if (sb.st_size > 0)
63    {
64	char buf[BUFSIZ];
65	int n;
66
67	for (;;)
68	{
69	    n = read (fdin, buf, sizeof(buf));
70	    if (n == -1)
71	    {
72#ifdef EINTR
73		if (errno == EINTR)
74		    continue;
75#endif
76		error (1, errno, "cannot read file %s for copying", from);
77	    }
78            else if (n == 0)
79		break;
80
81	    if (write(fdout, buf, n) != n) {
82		error (1, errno, "cannot write file %s for copying", to);
83	    }
84	}
85
86#ifdef HAVE_FSYNC
87	if (fsync (fdout))
88	    error (1, errno, "cannot fsync file %s after copying", to);
89#endif
90    }
91
92    if (close (fdin) < 0)
93	error (0, errno, "cannot close %s", from);
94    if (close (fdout) < 0)
95	error (1, errno, "cannot close %s", to);
96
97    /* now, set the times for the copied file to match those of the original */
98    memset ((char *) &t, 0, sizeof (t));
99    t.actime = sb.st_atime;
100    t.modtime = sb.st_mtime;
101    (void) utime (to, &t);
102}
103
104/* FIXME-krp: these functions would benefit from caching the char * &
105   stat buf.  */
106
107/*
108 * Returns non-zero if the argument file is a directory, or is a symbolic
109 * link which points to a directory.
110 */
111int
112isdir (file)
113    const char *file;
114{
115    struct stat sb;
116
117    if (stat (file, &sb) < 0)
118	return (0);
119    return (S_ISDIR (sb.st_mode));
120}
121
122/*
123 * Returns non-zero if the argument file is a symbolic link.
124 */
125int
126islink (file)
127    const char *file;
128{
129#ifdef S_ISLNK
130    struct stat sb;
131
132    if (lstat (file, &sb) < 0)
133	return (0);
134    return (S_ISLNK (sb.st_mode));
135#else
136    return (0);
137#endif
138}
139
140/*
141 * Returns non-zero if the argument file exists.
142 */
143int
144isfile (file)
145    const char *file;
146{
147    return isaccessible(file, F_OK);
148}
149
150/*
151 * Returns non-zero if the argument file is readable.
152 */
153int
154isreadable (file)
155    const char *file;
156{
157    return isaccessible(file, R_OK);
158}
159
160/*
161 * Returns non-zero if the argument file is writable.
162 */
163int
164iswritable (file)
165    const char *file;
166{
167    return isaccessible(file, W_OK);
168}
169
170/*
171 * Returns non-zero if the argument file is accessable according to
172 * mode.  If compiled with SETXID_SUPPORT also works if cvs has setxid
173 * bits set.
174 */
175int
176isaccessible (file, mode)
177    const char *file;
178    const int mode;
179{
180#ifdef SETXID_SUPPORT
181    struct stat sb;
182    int umask = 0;
183    int gmask = 0;
184    int omask = 0;
185    int uid;
186
187    if (stat(file, &sb) == -1)
188	return 0;
189    if (mode == F_OK)
190	return 1;
191
192    uid = geteuid();
193    if (uid == 0)		/* superuser */
194    {
195	if (mode & X_OK)
196	    return sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH);
197	else
198	    return 1;
199    }
200
201    if (mode & R_OK)
202    {
203	umask |= S_IRUSR;
204	gmask |= S_IRGRP;
205	omask |= S_IROTH;
206    }
207    if (mode & W_OK)
208    {
209	umask |= S_IWUSR;
210	gmask |= S_IWGRP;
211	omask |= S_IWOTH;
212    }
213    if (mode & X_OK)
214    {
215	umask |= S_IXUSR;
216	gmask |= S_IXGRP;
217	omask |= S_IXOTH;
218    }
219
220    if (sb.st_uid == uid)
221	return (sb.st_mode & umask) == umask;
222    else if (sb.st_gid == getegid())
223	return (sb.st_mode & gmask) == gmask;
224    else
225	return (sb.st_mode & omask) == omask;
226#else
227    return access(file, mode) == 0;
228#endif
229}
230
231/*
232 * Open a file and die if it fails
233 */
234FILE *
235open_file (name, mode)
236    const char *name;
237    const char *mode;
238{
239    FILE *fp;
240
241    if ((fp = fopen (name, mode)) == NULL)
242	error (1, errno, "cannot open %s", name);
243    return (fp);
244}
245
246/*
247 * Make a directory and die if it fails
248 */
249void
250make_directory (name)
251    const char *name;
252{
253    struct stat sb;
254
255    if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
256	    error (0, 0, "%s already exists but is not a directory", name);
257    if (!noexec && mkdir (name, 0777) < 0)
258	error (1, errno, "cannot make directory %s", name);
259}
260
261/*
262 * Make a path to the argument directory, printing a message if something
263 * goes wrong.
264 */
265void
266make_directories (name)
267    const char *name;
268{
269    char *cp;
270
271    if (noexec)
272	return;
273
274    if (mkdir (name, 0777) == 0 || errno == EEXIST)
275	return;
276    if (! existence_error (errno))
277    {
278	error (0, errno, "cannot make path to %s", name);
279	return;
280    }
281    if ((cp = strrchr (name, '/')) == NULL)
282	return;
283    *cp = '\0';
284    make_directories (name);
285    *cp++ = '/';
286    if (*cp == '\0')
287	return;
288    (void) mkdir (name, 0777);
289}
290
291/* Create directory NAME if it does not already exist; fatal error for
292   other errors.  Returns 0 if directory was created; 1 if it already
293   existed.  */
294int
295mkdir_if_needed (name)
296    char *name;
297{
298    if (mkdir (name, 0777) < 0)
299    {
300	if (errno != EEXIST)
301	    error (1, errno, "cannot make directory %s", name);
302	return 1;
303    }
304    return 0;
305}
306
307/*
308 * Change the mode of a file, either adding write permissions, or removing
309 * all write permissions.  Either change honors the current umask setting.
310 * The EMX doc (0.9c, emxlib.doc) says that chmod sets/clears the readonly
311 * bit.  But it always seemed to be a noop when I tried it.  Therefore,
312 * I've copied over the "attrib" code from os2/filesubr.c.
313 */
314void
315xchmod (fname, writable)
316    char *fname;
317    int writable;
318{
319    char *attrib_cmd;
320    char *attrib_option;
321    char *whole_cmd;
322    char *p;
323    char *q;
324
325    if (!isfile (fname))
326    {
327	error (0, 0, "cannot change mode of file %s; it does not exist",
328	       fname);
329	return;
330    }
331
332    attrib_cmd = "attrib "; /* No, really? */
333
334    if (writable)
335        attrib_option = "-r ";  /* make writeable */
336    else
337        attrib_option = "+r ";  /* make read-only */
338
339    whole_cmd = xmalloc (strlen (attrib_cmd)
340                         + strlen (attrib_option)
341                         + strlen (fname)
342                         + 1);
343
344    strcpy (whole_cmd, attrib_cmd);
345    strcat (whole_cmd, attrib_option);
346
347    /* Copy fname to the end of whole_cmd, translating / to \.
348	   Attrib doesn't take / but many parts of CVS rely
349       on being able to use it.  */
350    p = whole_cmd + strlen (whole_cmd);
351    q = fname;
352    while (*q)
353    {
354	if (*q == '/')
355	    *p++ = '\\';
356	else
357	    *p++ = *q;
358	++q;
359    }
360    *p = '\0';
361
362    system (whole_cmd);
363    free (whole_cmd);
364}
365
366/*
367 * Rename a file and die if it fails
368 */
369void
370rename_file (from, to)
371    const char *from;
372    const char *to;
373{
374    if (trace)
375#ifdef SERVER_SUPPORT
376	(void) fprintf (stderr, "%c-> rename(%s,%s)\n",
377			(server_active) ? 'S' : ' ', from, to);
378#else
379	(void) fprintf (stderr, "-> rename(%s,%s)\n", from, to);
380#endif
381    if (noexec)
382	return;
383
384    unlink_file (to);
385    if (rename (from, to) != 0)
386	error (1, errno, "cannot rename file %s to %s", from, to);
387}
388
389/*
390 * unlink a file, if possible.
391 */
392int
393unlink_file (f)
394    const char *f;
395{
396    if (trace)
397#ifdef SERVER_SUPPORT
398	(void) fprintf (stderr, "%c-> unlink(%s)\n",
399			(server_active) ? 'S' : ' ', f);
400#else
401	(void) fprintf (stderr, "-> unlink(%s)\n", f);
402#endif
403    if (noexec)
404	return (0);
405
406    if (isfile (f))
407	xchmod ((char *)f, 1);
408    return (unlink (f));
409}
410
411/*
412 * Unlink a file or dir, if possible.  If it is a directory do a deep
413 * removal of all of the files in the directory.  Return -1 on error
414 * (in which case errno is set).
415 */
416int
417unlink_file_dir (f)
418    const char *f;
419{
420    if (trace)
421#ifdef SERVER_SUPPORT
422	(void) fprintf (stderr, "%c-> unlink_file_dir(%s)\n",
423			(server_active) ? 'S' : ' ', f);
424#else
425	(void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f);
426#endif
427    if (noexec)
428	return (0);
429
430    /* For at least some unices, if root tries to unlink() a directory,
431       instead of doing something rational like returning EISDIR,
432       the system will gleefully go ahead and corrupt the filesystem.
433       So we first call isdir() to see if it is OK to call unlink().  This
434       doesn't quite work--if someone creates a directory between the
435       call to isdir() and the call to unlink(), we'll still corrupt
436       the filesystem.  Where is the Unix Haters Handbook when you need
437       it?  */
438    if (isdir(f))
439	return deep_remove_dir(f);
440    else
441    {
442	if (unlink (f) != 0)
443	    return -1;
444    }
445    /* We were able to remove the file from the disk */
446    return 0;
447}
448
449/* Remove a directory and everything it contains.  Returns 0 for
450 * success, -1 for failure (in which case errno is set).
451 */
452
453static int
454deep_remove_dir (path)
455    const char *path;
456{
457    DIR		  *dirp;
458    struct dirent *dp;
459    char	   buf[PATH_MAX];
460
461    if (rmdir (path) != 0)
462    {
463	if (errno == ENOTEMPTY
464	    || errno == EEXIST
465	    /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
466	       (it defines ENOTEMPTY and EEXIST to 17 but actually
467	       returns 87).  */
468	    || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
469	{
470	    if ((dirp = opendir (path)) == NULL)
471		/* If unable to open the directory return
472		 * an error
473		 */
474		return -1;
475
476	    while ((dp = readdir (dirp)) != NULL)
477	    {
478		if (strcmp (dp->d_name, ".") == 0 ||
479			    strcmp (dp->d_name, "..") == 0)
480		    continue;
481
482		sprintf (buf, "%s/%s", path, dp->d_name);
483
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))
488		{
489		    if (deep_remove_dir(buf))
490		    {
491			closedir(dirp);
492			return -1;
493		    }
494		}
495		else
496		{
497		    if (unlink (buf) != 0)
498		    {
499			closedir(dirp);
500			return -1;
501		    }
502		}
503	    }
504	    closedir (dirp);
505	    return rmdir (path);
506	}
507	else
508	    return -1;
509    }
510
511    /* Was able to remove the directory return 0 */
512    return 0;
513}
514
515/* Read NCHARS bytes from descriptor FD into BUF.
516   Return the number of characters successfully read.
517   The number returned is always NCHARS unless end-of-file or error.  */
518static size_t
519block_read (fd, buf, nchars)
520    int fd;
521    char *buf;
522    size_t nchars;
523{
524    char *bp = buf;
525    size_t nread;
526
527    do
528    {
529	nread = read (fd, bp, nchars);
530	if (nread == (size_t)-1)
531	{
532#ifdef EINTR
533	    if (errno == EINTR)
534		continue;
535#endif
536	    return (size_t)-1;
537	}
538
539	if (nread == 0)
540	    break;
541
542	bp += nread;
543	nchars -= nread;
544    } while (nchars != 0);
545
546    return bp - buf;
547}
548
549
550/*
551 * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
552 */
553int
554xcmp (file1, file2)
555    const char *file1;
556    const char *file2;
557{
558    char *buf1, *buf2;
559    struct stat sb1, sb2;
560    int fd1, fd2;
561    int ret;
562
563    if ((fd1 = open (file1, O_RDONLY | O_BINARY)) < 0)
564	error (1, errno, "cannot open file %s for comparing", file1);
565    if ((fd2 = open (file2, O_RDONLY | O_BINARY)) < 0)
566	error (1, errno, "cannot open file %s for comparing", file2);
567    if (fstat (fd1, &sb1) < 0)
568	error (1, errno, "cannot fstat %s", file1);
569    if (fstat (fd2, &sb2) < 0)
570	error (1, errno, "cannot fstat %s", file2);
571
572    /* A generic file compare routine might compare st_dev & st_ino here
573       to see if the two files being compared are actually the same file.
574       But that won't happen in CVS, so we won't bother. */
575
576    if (sb1.st_size != sb2.st_size)
577	ret = 1;
578    else if (sb1.st_size == 0)
579	ret = 0;
580    else
581    {
582	/* FIXME: compute the optimal buffer size by computing the least
583	   common multiple of the files st_blocks field */
584	size_t buf_size = 8 * 1024;
585	size_t read1;
586	size_t read2;
587
588	buf1 = xmalloc (buf_size);
589	buf2 = xmalloc (buf_size);
590
591	do
592	{
593	    read1 = block_read (fd1, buf1, buf_size);
594	    if (read1 == (size_t)-1)
595		error (1, errno, "cannot read file %s for comparing", file1);
596
597	    read2 = block_read (fd2, buf2, buf_size);
598	    if (read2 == (size_t)-1)
599		error (1, errno, "cannot read file %s for comparing", file2);
600
601	    /* assert (read1 == read2); */
602
603	    ret = memcmp(buf1, buf2, read1);
604	} while (ret == 0 && read1 == buf_size);
605
606	free (buf1);
607	free (buf2);
608    }
609
610    (void) close (fd1);
611    (void) close (fd2);
612    return (ret);
613}
614
615
616/* Just in case this implementation does not define this.  */
617#ifndef L_tmpnam
618#define	L_tmpnam 50
619#endif
620
621
622#ifdef LOSING_TMPNAM_FUNCTION
623char *
624cvs_temp_name ()
625{
626    char value[L_tmpnam + 1];
627
628    /* FIXME: Should be using TMPDIR.  */
629    strcpy (value, "/tmp/cvsXXXXXX");
630    mktemp (value);
631    return xstrdup (value);
632}
633#else
634/* Generate a unique temporary filename.  Returns a pointer to a newly
635   malloc'd string containing the name.  Returns successfully or not at
636   all.  */
637char *
638cvs_temp_name ()
639{
640    char value[L_tmpnam + 1];
641    char *retval;
642
643    /* FIXME: should be using TMPDIR, perhaps by using tempnam on systems
644       which have it.  */
645    retval = tmpnam (value);
646    if (retval == NULL)
647	error (1, errno, "cannot generate temporary filename");
648    return xstrdup (retval);
649}
650#endif
651
652
653/* Return non-zero iff FILENAME is absolute.
654   Trivial under Unix, but more complicated under other systems.
655   Under EMX let _fnisabs do all this work. */
656int
657isabsolute (filename)
658    const char *filename;
659{
660    return _fnisabs(filename);
661}
662
663
664/* Return a pointer into PATH's last component.  */
665char *
666last_component (path)
667    char *path;
668{
669    char *last;
670
671    /* We can't be sure here if 'path' is already slashified. */
672    _fnslashify (path);
673
674    last = strrchr (path, '/');
675
676    if (last && (last != path))
677        return last + 1;
678    else
679        return path;
680}
681
682/* Return the home directory.  Returns a pointer to storage
683   managed by this function or its callees (currently getenv).
684   This function will return the same thing every time it is
685   called.  */
686char *
687get_homedir ()
688{
689    static char *home = NULL;
690    char *env = getenv ("HOME");
691    struct passwd *pw;
692
693    if (home != NULL)
694	return home;
695
696    if (env)
697	home = env;
698    else if ((pw = (struct passwd *) getpwuid (getuid ()))
699	     && pw->pw_dir)
700	home = xstrdup (pw->pw_dir);
701    else
702	return 0;
703
704    return home;
705}
706
707/* See cvs.h for description.  On unix this does nothing, because the
708   shell expands the wildcards.  Under EMX, use _fnexplode to get the
709   expanded filenames */
710void
711expand_wild (argc, argv, pargc, pargv)
712    int argc;
713    char **argv;
714    int *pargc;
715    char ***pargv;
716{
717    int i;
718    *pargc = argc;
719    *pargv = (char **) xmalloc (argc * sizeof (char *));
720    for (i = 0; i < argc; ++i)
721	(*pargv)[i] = xstrdup (argv[i]);
722}
723
724unsigned char
725OS2_filename_classes[] =
726{
727    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
728    0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
729    0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
730    0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
731    0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
732    0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
733    0x30,0x31,0x32,0x33, 0x34,0x35,0x36,0x37,
734    0x38,0x39,0x3a,0x3b, 0x3c,0x3d,0x3e,0x3f,
735    0x40,0x61,0x62,0x63, 0x64,0x65,0x66,0x67,
736    0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
737    0x70,0x71,0x72,0x73, 0x74,0x75,0x76,0x77,
738    0x78,0x79,0x7a,0x5b, 0x2f,0x5d,0x5e,0x5f,
739    0x60,0x61,0x62,0x63, 0x64,0x65,0x66,0x67,
740    0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
741    0x70,0x71,0x72,0x73, 0x74,0x75,0x76,0x77,
742    0x78,0x79,0x7a,0x7b, 0x7c,0x7d,0x7e,0x7f,
743    0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87,
744    0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f,
745    0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97,
746    0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f,
747    0xa0,0xa1,0xa2,0xa3, 0xa4,0xa5,0xa6,0xa7,
748    0xa8,0xa9,0xaa,0xab, 0xac,0xad,0xae,0xaf,
749    0xb0,0xb1,0xb2,0xb3, 0xb4,0xb5,0xb6,0xb7,
750    0xb8,0xb9,0xba,0xbb, 0xbc,0xbd,0xbe,0xbf,
751    0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
752    0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
753    0xd0,0xd1,0xd2,0xd3, 0xd4,0xd5,0xd6,0xd7,
754    0xd8,0xd9,0xda,0xdb, 0xdc,0xdd,0xde,0xdf,
755    0xe0,0xe1,0xe2,0xe3, 0xe4,0xe5,0xe6,0xe7,
756    0xe8,0xe9,0xea,0xeb, 0xec,0xed,0xee,0xef,
757    0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7,
758    0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
759};
760
761
762/* Like strcmp, but with the appropriate tweaks for file names.
763   Under OS/2, filenames are case-insensitive but case-preserving, and
764   both \ and / are path element separators.  */
765int
766fncmp (const char *n1, const char *n2)
767{
768    char fn1[MAXNAMLEN], fn2[MAXNAMLEN];
769
770    strcpy (fn1, n1); _fnslashify(fn1);
771    strcpy (fn2, n2); _fnslashify(fn2);
772
773    return _fncmp ((unsigned char *) fn1, (unsigned char *) fn2);
774}
775
776
777/* Fold characters in FILENAME to their canonical forms.
778   If FOLD_FN_CHAR is not #defined, the system provides a default
779   definition for this.  */
780void
781fnfold (char *filename)
782{
783    while (*filename)
784    {
785        *filename = FOLD_FN_CHAR (*filename);
786	filename++;
787    }
788}
789