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
25static int deep_remove_dir PROTO((const char *path));
26
27/*
28 * Copies "from" to "to".
29 */
30void
31copy_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 */
124int
125isdir (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 */
138int
139islink (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 */
157int
158isdevice (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 */
179int
180isfile (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 */
189int
190isreadable (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 */
199int
200iswritable (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 */
211int
212isaccessible (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 */
270FILE *
271open_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 */
285void
286make_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 */
301void
302make_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.  */
330int
331mkdir_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 */
351void
352xchmod (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 */
396void
397rename_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 */
414int
415unlink_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 */
432int
433unlink_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
473static int
474deep_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.  */
553static size_t
554block_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 */
590int
591xcmp (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 */
697char *
698cvs_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 */
743FILE *
744cvs_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
885char *
886xreadlink (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 */
945char *
946xresolvepath ( 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.  */
972const char *
973last_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.  */
1008char *
1009get_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 */
1039char *
1040strcat_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.  */
1051void
1052expand_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).  */
1080int
1081cvs_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