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 #include <sys/cdefs.h>
16 __RCSID("$NetBSD: filesubr.c,v 1.6 2017/09/15 21:03:26 christos Exp $");
17
18 /* These functions were moved out of subr.c because they need different
19 definitions under operating systems (like, say, Windows NT) with different
20 file system semantics. */
21
22 #include "cvs.h"
23 #include "lstat.h"
24 #include "save-cwd.h"
25 #include "xsize.h"
26
27 static int deep_remove_dir (const char *path);
28 #ifndef S_ISBLK
29 #define S_ISBLK(a) 0
30 #endif
31 #ifndef S_ISCHR
32 #define S_ISCHR(a) 0
33 #endif
34 #define IS_DEVICE(sbp) (S_ISBLK((sbp)->st_mode) || S_ISCHR((sbp)->st_mode))
35
36 /*
37 * Copies "from" to "to".
38 */
39 void
copy_file(const char * from,const char * to)40 copy_file (const char *from, const char *to)
41 {
42 struct stat sb;
43 struct utimbuf t;
44 int fdin, fdout;
45 ssize_t rsize;
46
47 TRACE (TRACE_FUNCTION, "copy(%s,%s)", from, to);
48
49 if (noexec)
50 return;
51
52 /* If the file to be copied is a link or a device, then just create
53 the new link or device appropriately. */
54 if ((rsize = islink (from, &sb)) > 0)
55 {
56 char *source = Xreadlink (from, rsize);
57 if (symlink (source, to) == -1)
58 error (1, errno, "cannot symlink %s to %s", source, to);
59 free (source);
60 return;
61 }
62
63 if (sb.st_ino != -1 && IS_DEVICE (&sb))
64 {
65 #if defined(HAVE_MKNOD) && defined(HAVE_STRUCT_STAT_ST_RDEV)
66 mknod (to, sb.st_mode, sb.st_rdev);
67 #else
68 error (1, 0, "cannot copy device files on this system (%s)", from);
69 #endif
70 }
71 else
72 {
73 /* Not a link or a device... probably a regular file. */
74 if ((fdin = open (from, O_RDONLY)) < 0)
75 error (1, errno, "cannot open %s for copying", from);
76 if (fstat (fdin, &sb) < 0)
77 error (1, errno, "cannot fstat %s", from);
78 if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
79 error (1, errno, "cannot create %s for copying", to);
80 if (sb.st_size > 0)
81 {
82 char buf[BUFSIZ];
83 int n;
84
85 for (;;)
86 {
87 n = read (fdin, buf, sizeof(buf));
88 if (n == -1)
89 {
90 #ifdef EINTR
91 if (errno == EINTR)
92 continue;
93 #endif
94 error (1, errno, "cannot read file %s for copying", from);
95 }
96 else if (n == 0)
97 break;
98
99 if (write(fdout, buf, n) != n) {
100 error (1, errno, "cannot write file %s for copying", to);
101 }
102 }
103 }
104
105 if (close (fdin) < 0)
106 error (0, errno, "cannot close %s", from);
107 if (close (fdout) < 0)
108 error (1, errno, "cannot close %s", to);
109 }
110
111 /* preserve last access & modification times */
112 memset ((char *) &t, 0, sizeof (t));
113 t.actime = sb.st_atime;
114 t.modtime = sb.st_mtime;
115 (void) utime (to, &t);
116 }
117
118
119
120 /* FIXME-krp: these functions would benefit from caching the char * &
121 stat buf. */
122
123 /*
124 * Returns true if the argument file is a directory, or is a symbolic
125 * link which points to a directory.
126 */
127 bool
isdir(const char * file)128 isdir (const char *file)
129 {
130 struct stat sb;
131
132 if (stat (file, &sb) < 0)
133 return false;
134 return S_ISDIR (sb.st_mode);
135 }
136
137
138
139 /*
140 * Returns 0 if the argument file is not a symbolic link.
141 * Returns size of the link if it is a symbolic link.
142 */
143 ssize_t
islink(const char * file,struct stat * sbp)144 islink (const char *file, struct stat *sbp)
145 {
146 ssize_t retsize = 0;
147 #ifdef S_ISLNK
148 struct stat sb;
149 if (sbp == NULL)
150 sbp = &sb;
151
152 if (lstat (file, sbp) < 0) {
153 sbp->st_ino = -1;
154 return 0;
155 }
156 if (S_ISLNK (sbp->st_mode))
157 retsize = sbp->st_size;
158 #else
159 sbp->st_ino = -1;
160 #endif
161 return retsize;
162 }
163
164
165
166 /*
167 * Returns true if the argument file is a block or
168 * character special device.
169 */
170 bool
isdevice(const char * file)171 isdevice (const char *file)
172 {
173 struct stat sb;
174
175 if (lstat (file, &sb) < 0)
176 return false;
177 return IS_DEVICE(&sb);
178 }
179
180
181
182 /*
183 * Returns true if the argument file exists.
184 */
185 bool
isfile(const char * file)186 isfile (const char *file)
187 {
188 return isaccessible (file, F_OK);
189 }
190
191 #ifdef SETXID_SUPPORT
192 int
ingroup(gid_t gid)193 ingroup(gid_t gid)
194 {
195 gid_t *gidp;
196 int i, ngroups;
197
198 if (gid == getegid())
199 return 1;
200
201 ngroups = getgroups(0, NULL);
202 if (ngroups == -1)
203 return 0;
204
205 if ((gidp = malloc(sizeof(gid_t) * ngroups)) == NULL)
206 return 0;
207
208 if (getgroups(ngroups, gidp) == -1) {
209 free(gidp);
210 return 0;
211 }
212
213 for (i = 0; i < ngroups; i++)
214 if (gid == gidp[i])
215 break;
216
217 free(gidp);
218 return i != ngroups;
219 }
220 #endif
221
222 /*
223 * Returns non-zero if the argument file is readable.
224 */
225 bool
isreadable(const char * file)226 isreadable (const char *file)
227 {
228 return isaccessible (file, R_OK);
229 }
230
231
232
233 /*
234 * Returns non-zero if the argument file is writable.
235 */
236 bool
iswritable(const char * file)237 iswritable (const char *file)
238 {
239 return isaccessible (file, W_OK);
240 }
241
242
243
244 /*
245 * Returns true if the argument file is accessable according to
246 * mode. If compiled with SETXID_SUPPORT also works if cvs has setxid
247 * bits set.
248 */
249 bool
isaccessible(const char * file,const int mode)250 isaccessible (const char *file, const int mode)
251 {
252 #ifdef SETXID_SUPPORT
253 struct stat sb;
254 int umask = 0;
255 int gmask = 0;
256 int omask = 0;
257 int uid, mask;
258
259 if (stat (file, &sb)== -1)
260 return false;
261 if (mode == F_OK)
262 return true;
263
264 uid = geteuid();
265 if (uid == 0) /* superuser */
266 {
267 if (!(mode & X_OK) || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
268 return true;
269
270 errno = EACCES;
271 return false;
272 }
273
274 if (mode & R_OK)
275 {
276 umask |= S_IRUSR;
277 gmask |= S_IRGRP;
278 omask |= S_IROTH;
279 }
280 if (mode & W_OK)
281 {
282 umask |= S_IWUSR;
283 gmask |= S_IWGRP;
284 omask |= S_IWOTH;
285 }
286 if (mode & X_OK)
287 {
288 umask |= S_IXUSR;
289 gmask |= S_IXGRP;
290 omask |= S_IXOTH;
291 }
292
293 mask = sb.st_uid == uid ? umask : ingroup(sb.st_gid) ? gmask : omask;
294 if ((sb.st_mode & mask) == mask)
295 return true;
296 errno = EACCES;
297 return false;
298 #else /* !SETXID_SUPPORT */
299 return access (file, mode) == 0;
300 #endif /* SETXID_SUPPORT */
301 }
302
303
304
305 /*
306 * Make a directory and die if it fails
307 */
308 void
make_directory(const char * name)309 make_directory (const char *name)
310 {
311 struct stat sb;
312
313 if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
314 error (0, 0, "%s already exists but is not a directory", name);
315 if (!noexec && mkdir (name, 0777) < 0)
316 error (1, errno, "cannot make directory %s", name);
317 }
318
319 /*
320 * Make a path to the argument directory, printing a message if something
321 * goes wrong.
322 */
323 void
make_directories(const char * name)324 make_directories (const char *name)
325 {
326 char *cp;
327
328 if (noexec)
329 return;
330
331 if (mkdir (name, 0777) == 0 || errno == EEXIST)
332 return;
333 if (! existence_error (errno))
334 {
335 error (0, errno, "cannot make path to %s", name);
336 return;
337 }
338 if ((cp = strrchr (name, '/')) == NULL)
339 return;
340 *cp = '\0';
341 make_directories (name);
342 *cp++ = '/';
343 if (*cp == '\0')
344 return;
345 (void) mkdir (name, 0777);
346 }
347
348 /* Create directory NAME if it does not already exist; fatal error for
349 other errors. Returns 0 if directory was created; 1 if it already
350 existed. */
351 int
mkdir_if_needed(const char * name)352 mkdir_if_needed (const char *name)
353 {
354 if (mkdir (name, 0777) < 0)
355 {
356 int save_errno = errno;
357 if (save_errno != EEXIST && !isdir (name))
358 error (1, save_errno, "cannot make directory %s", name);
359 return 1;
360 }
361 return 0;
362 }
363
364 /*
365 * Change the mode of a file, either adding write permissions, or removing
366 * all write permissions. Either change honors the current umask setting.
367 *
368 * Don't do anything if PreservePermissions is set to `yes'. This may
369 * have unexpected consequences for some uses of xchmod.
370 */
371 void
xchmod(const char * fname,int writable)372 xchmod (const char *fname, int writable)
373 {
374 struct stat sb;
375 mode_t mode, oumask;
376
377 #ifdef PRESERVE_PERMISSIONS_SUPPORT
378 if (config->preserve_perms)
379 return;
380 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
381
382 if (stat (fname, &sb) < 0)
383 {
384 if (!noexec)
385 error (0, errno, "cannot stat %s", fname);
386 return;
387 }
388 oumask = umask (0);
389 (void) umask (oumask);
390 if (writable)
391 {
392 mode = sb.st_mode | (~oumask
393 & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0)
394 | ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0)
395 | ((sb.st_mode & S_IROTH) ? S_IWOTH : 0)));
396 }
397 else
398 {
399 mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask;
400 }
401
402 TRACE (TRACE_FUNCTION, "chmod(%s,%o)", fname, (unsigned int) mode);
403
404 if (noexec)
405 return;
406
407 if (chmod (fname, mode) < 0)
408 error (0, errno, "cannot change mode of file %s", fname);
409 }
410
411 /*
412 * Rename a file and die if it fails
413 */
414 void
rename_file(const char * from,const char * to)415 rename_file (const char *from, const char *to)
416 {
417 TRACE (TRACE_FUNCTION, "rename(%s,%s)", from, to);
418
419 if (noexec)
420 return;
421
422 if (rename (from, to) < 0)
423 error (1, errno, "cannot rename file %s to %s", from, to);
424 }
425
426 /*
427 * unlink a file, if possible.
428 */
429 int
unlink_file(const char * f)430 unlink_file (const char *f)
431 {
432 TRACE (TRACE_FUNCTION, "unlink_file(%s)", f);
433
434 if (noexec)
435 return (0);
436
437 return (CVS_UNLINK (f));
438 }
439
440
441
442 /*
443 * Unlink a file or dir, if possible. If it is a directory do a deep
444 * removal of all of the files in the directory. Return -1 on error
445 * (in which case errno is set).
446 */
447 int
unlink_file_dir(const char * f)448 unlink_file_dir (const char *f)
449 {
450 struct stat sb;
451
452 /* This is called by the server parent process in contexts where
453 it is not OK to send output (e.g. after we sent "ok" to the
454 client). */
455 if (!server_active)
456 TRACE (TRACE_FUNCTION, "unlink_file_dir(%s)", f);
457
458 if (noexec)
459 return 0;
460
461 /* For at least some unices, if root tries to unlink() a directory,
462 instead of doing something rational like returning EISDIR,
463 the system will gleefully go ahead and corrupt the filesystem.
464 So we first call stat() to see if it is OK to call unlink(). This
465 doesn't quite work--if someone creates a directory between the
466 call to stat() and the call to unlink(), we'll still corrupt
467 the filesystem. Where is the Unix Haters Handbook when you need
468 it? */
469 if (stat (f, &sb) < 0)
470 {
471 if (existence_error (errno))
472 {
473 /* The file or directory doesn't exist anyhow. */
474 return -1;
475 }
476 }
477 else if (S_ISDIR (sb.st_mode))
478 return deep_remove_dir (f);
479
480 return CVS_UNLINK (f);
481 }
482
483
484
485 /* Remove a directory and everything it contains. Returns 0 for
486 * success, -1 for failure (in which case errno is set).
487 */
488
489 static int
deep_remove_dir(const char * path)490 deep_remove_dir (const char *path)
491 {
492 DIR *dirp;
493 struct dirent *dp;
494
495 if (rmdir (path) != 0)
496 {
497 if (errno == ENOTEMPTY
498 || errno == EEXIST
499 /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
500 (it defines ENOTEMPTY and EEXIST to 17 but actually
501 returns 87). */
502 || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
503 {
504 if ((dirp = CVS_OPENDIR (path)) == NULL)
505 /* If unable to open the directory return
506 * an error
507 */
508 return -1;
509
510 errno = 0;
511 while ((dp = CVS_READDIR (dirp)) != NULL)
512 {
513 char *buf;
514
515 if (strcmp (dp->d_name, ".") == 0 ||
516 strcmp (dp->d_name, "..") == 0)
517 continue;
518
519 buf = Xasprintf ("%s/%s", path, dp->d_name);
520
521 /* See comment in unlink_file_dir explanation of why we use
522 isdir instead of just calling unlink and checking the
523 status. */
524 if (isdir (buf))
525 {
526 if (deep_remove_dir (buf))
527 {
528 CVS_CLOSEDIR (dirp);
529 free (buf);
530 return -1;
531 }
532 }
533 else
534 {
535 if (CVS_UNLINK (buf) != 0)
536 {
537 CVS_CLOSEDIR (dirp);
538 free (buf);
539 return -1;
540 }
541 }
542 free (buf);
543
544 errno = 0;
545 }
546 if (errno != 0)
547 {
548 int save_errno = errno;
549 CVS_CLOSEDIR (dirp);
550 errno = save_errno;
551 return -1;
552 }
553 CVS_CLOSEDIR (dirp);
554 return rmdir (path);
555 }
556 else
557 return -1;
558 }
559
560 /* Was able to remove the directory return 0 */
561 return 0;
562 }
563
564
565
566 /* Read NCHARS bytes from descriptor FD into BUF.
567 Return the number of characters successfully read.
568 The number returned is always NCHARS unless end-of-file or error. */
569 static size_t
block_read(int fd,char * buf,size_t nchars)570 block_read (int fd, char *buf, size_t nchars)
571 {
572 char *bp = buf;
573 size_t nread;
574
575 do
576 {
577 nread = read (fd, bp, nchars);
578 if (nread == (size_t)-1)
579 {
580 #ifdef EINTR
581 if (errno == EINTR)
582 continue;
583 #endif
584 return (size_t)-1;
585 }
586
587 if (nread == 0)
588 break;
589
590 bp += nread;
591 nchars -= nread;
592 } while (nchars != 0);
593
594 return bp - buf;
595 }
596
597
598 /*
599 * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
600 * If FILE1 and FILE2 are special files, compare their salient characteristics
601 * (i.e. major/minor device numbers, links, etc.
602 */
603 int
xcmp(const char * file1,const char * file2)604 xcmp (const char *file1, const char *file2)
605 {
606 char *buf1, *buf2;
607 struct stat sb1, sb2;
608 int fd1, fd2;
609 int ret;
610
611 if (lstat (file1, &sb1) < 0)
612 error (1, errno, "cannot lstat %s", file1);
613 if (lstat (file2, &sb2) < 0)
614 error (1, errno, "cannot lstat %s", file2);
615
616 /* If FILE1 and FILE2 are not the same file type, they are unequal. */
617 if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
618 return 1;
619
620 /* If FILE1 and FILE2 are symlinks, they are equal if they point to
621 the same thing. */
622 #ifdef S_ISLNK
623 if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
624 {
625 int result;
626 buf1 = Xreadlink (file1, sb1.st_size);
627 buf2 = Xreadlink (file2, sb2.st_size);
628 result = (strcmp (buf1, buf2) == 0);
629 free (buf1);
630 free (buf2);
631 return result;
632 }
633 #endif
634
635 /* If FILE1 and FILE2 are devices, they are equal if their device
636 numbers match. */
637 if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
638 {
639 #ifdef HAVE_STRUCT_STAT_ST_RDEV
640 if (sb1.st_rdev == sb2.st_rdev)
641 return 0;
642 else
643 return 1;
644 #else
645 error (1, 0, "cannot compare device files on this system (%s and %s)",
646 file1, file2);
647 #endif
648 }
649
650 if ((fd1 = open (file1, O_RDONLY)) < 0)
651 error (1, errno, "cannot open file %s for comparing", file1);
652 if ((fd2 = open (file2, O_RDONLY)) < 0)
653 error (1, errno, "cannot open file %s for comparing", file2);
654
655 /* A generic file compare routine might compare st_dev & st_ino here
656 to see if the two files being compared are actually the same file.
657 But that won't happen in CVS, so we won't bother. */
658
659 if (sb1.st_size != sb2.st_size)
660 ret = 1;
661 else if (sb1.st_size == 0)
662 ret = 0;
663 else
664 {
665 /* FIXME: compute the optimal buffer size by computing the least
666 common multiple of the files st_blocks field */
667 size_t buf_size = 8 * 1024;
668 size_t read1;
669 size_t read2;
670
671 buf1 = xmalloc (buf_size);
672 buf2 = xmalloc (buf_size);
673
674 do
675 {
676 read1 = block_read (fd1, buf1, buf_size);
677 if (read1 == (size_t)-1)
678 error (1, errno, "cannot read file %s for comparing", file1);
679
680 read2 = block_read (fd2, buf2, buf_size);
681 if (read2 == (size_t)-1)
682 error (1, errno, "cannot read file %s for comparing", file2);
683
684 /* assert (read1 == read2); */
685
686 ret = memcmp(buf1, buf2, read1);
687 } while (ret == 0 && read1 == buf_size);
688
689 free (buf1);
690 free (buf2);
691 }
692
693 (void) close (fd1);
694 (void) close (fd2);
695 return (ret);
696 }
697
698 /* Generate a unique temporary filename. Returns a pointer to a newly
699 * malloc'd string containing the name. Returns successfully or not at
700 * all.
701 *
702 * THIS FUNCTION IS DEPRECATED!!! USE cvs_temp_file INSTEAD!!!
703 *
704 * and yes, I know about the way the rcs commands use temp files. I think
705 * they should be converted too but I don't have time to look into it right
706 * now.
707 */
708 char *
cvs_temp_name(void)709 cvs_temp_name (void)
710 {
711 char *fn;
712 FILE *fp;
713
714 fp = cvs_temp_file (&fn);
715 if (fp == NULL)
716 error (1, errno, "Failed to create temporary file");
717 if (fclose (fp) == EOF)
718 error (0, errno, "Failed to close temporary file %s", fn);
719 return fn;
720 }
721
722 /* Generate a unique temporary filename and return an open file stream
723 * to the truncated file by that name
724 *
725 * INPUTS
726 * filename where to place the pointer to the newly allocated file
727 * name string
728 *
729 * OUTPUTS
730 * filename dereferenced, will point to the newly allocated file
731 * name string. This value is undefined if the function
732 * returns an error.
733 *
734 * RETURNS
735 * An open file pointer to a read/write mode empty temporary file with the
736 * unique file name or NULL on failure.
737 *
738 * ERRORS
739 * On error, errno will be set to some value either by CVS_FOPEN or
740 * whatever system function is called to generate the temporary file name.
741 * The value of filename is undefined on error.
742 */
743 FILE *
cvs_temp_file(char ** filename)744 cvs_temp_file (char **filename)
745 {
746 char *fn;
747 FILE *fp;
748 int fd;
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 fn = Xasprintf ("%s/%s", get_cvs_tmp_dir (), "cvsXXXXXX");
758 fd = mkstemp (fn);
759
760 /* a NULL return will be interpreted by callers as an error and
761 * errno should still be set
762 */
763 if (fd == -1)
764 fp = NULL;
765 else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL)
766 {
767 /* Attempt to close and unlink the file since mkstemp returned
768 * sucessfully and we believe it's been created and opened.
769 */
770 int save_errno = errno;
771 if (close (fd))
772 error (0, errno, "Failed to close temporary file %s", fn);
773 if (CVS_UNLINK (fn))
774 error (0, errno, "Failed to unlink temporary file %s", fn);
775 errno = save_errno;
776 }
777
778 if (fp == NULL)
779 free (fn);
780
781 /* mkstemp is defined to open mode 0600 using glibc 2.0.7+. There used
782 * to be a complicated #ifdef checking the library versions here and then
783 * a chmod 0600 on the temp file for versions of glibc less than 2.1. This
784 * is rather a special case, leaves a race condition open regardless, and
785 * one could hope that sysadmins have read the relevant security
786 * announcements and upgraded by now to a version with a fix committed in
787 * January of 1999.
788 *
789 * If it is decided at some point that old, buggy versions of glibc should
790 * still be catered to, a umask of 0600 should be set before file creation
791 * instead then reset after file creation since this would avoid the race
792 * condition that the chmod left open to exploitation.
793 */
794
795 *filename = fn;
796 return fp;
797 }
798
799
800
801 /* Return a pointer into PATH's last component. */
802 const char *
last_component(const char * path)803 last_component (const char *path)
804 {
805 const char *last = strrchr (path, '/');
806
807 if (last && (last != path))
808 return last + 1;
809 else
810 return path;
811 }
812
813
814
815 /* Return the home directory. Returns a pointer to storage
816 managed by this function or its callees (currently getenv).
817 This function will return the same thing every time it is
818 called. Returns NULL if there is no home directory.
819
820 Note that for a pserver server, this may return root's home
821 directory. What typically happens is that upon being started from
822 inetd, before switching users, the code in cvsrc.c calls
823 get_homedir which remembers root's home directory in the static
824 variable. Then the switch happens and get_homedir might return a
825 directory that we don't even have read or execute permissions for
826 (which is bad, when various parts of CVS try to read there). One
827 fix would be to make the value returned by get_homedir only good
828 until the next call (which would free the old value). Another fix
829 would be to just always malloc our answer, and let the caller free
830 it (that is best, because some day we may need to be reentrant).
831
832 The workaround is to put -f in inetd.conf which means that
833 get_homedir won't get called until after the switch in user ID.
834
835 The whole concept of a "home directory" on the server is pretty
836 iffy, although I suppose some people probably are relying on it for
837 .cvsrc and such, in the cases where it works. */
838 char *
get_homedir(void)839 get_homedir (void)
840 {
841 static char *home = NULL;
842 char *env;
843 struct passwd *pw;
844
845 if (home != NULL)
846 return home;
847
848 if (!server_active && (env = getenv ("HOME")) != NULL)
849 home = env;
850 else if ((pw = (struct passwd *) getpwuid (getuid ()))
851 && pw->pw_dir)
852 home = xstrdup (pw->pw_dir);
853 else
854 return 0;
855
856 return home;
857 }
858
859 /* Compose a path to a file in the home directory. This is necessary because
860 * of different behavior on UNIX and VMS. See the notes in vms/filesubr.c.
861 *
862 * A more clean solution would be something more along the lines of a
863 * "join a directory to a filename" kind of thing which was not specific to
864 * the homedir. This should aid portability between UNIX, Mac, Windows, VMS,
865 * and possibly others. This is already handled by Perl - it might be
866 * interesting to see how much of the code was written in C since Perl is under
867 * the GPL and the Artistic license - we might be able to use it.
868 */
869 char *
strcat_filename_onto_homedir(const char * dir,const char * file)870 strcat_filename_onto_homedir (const char *dir, const char *file)
871 {
872 char *path = Xasprintf ("%s/%s", dir, file);
873 return path;
874 }
875
876 /* See cvs.h for description. On unix this does nothing, because the
877 shell expands the wildcards. */
878 void
expand_wild(int argc,char ** argv,int * pargc,char *** pargv)879 expand_wild (int argc, char **argv, int *pargc, char ***pargv)
880 {
881 int i;
882 if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
883 *pargc = 0;
884 *pargv = NULL;
885 error (0, 0, "expand_wild: too many arguments");
886 return;
887 }
888 *pargc = argc;
889 *pargv = xnmalloc (argc, sizeof (char *));
890 for (i = 0; i < argc; ++i)
891 (*pargv)[i] = xstrdup (argv[i]);
892 }
893
894
895
896 static char *tmpdir_env;
897
898 /* Return path to temp directory.
899 */
900 const char *
get_system_temp_dir(void)901 get_system_temp_dir (void)
902 {
903 if (!tmpdir_env) tmpdir_env = getenv (TMPDIR_ENV);
904 return tmpdir_env;
905 }
906
907
908
909 void
push_env_temp_dir(void)910 push_env_temp_dir (void)
911 {
912 const char *tmpdir = get_cvs_tmp_dir ();
913 if (tmpdir_env && strcmp (tmpdir_env, tmpdir))
914 setenv (TMPDIR_ENV, tmpdir, 1);
915 }
916