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