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