diff options
Diffstat (limited to 'contrib/cvs/src/filesubr.c')
-rw-r--r-- | contrib/cvs/src/filesubr.c | 241 |
1 files changed, 171 insertions, 70 deletions
diff --git a/contrib/cvs/src/filesubr.c b/contrib/cvs/src/filesubr.c index 2cccbcd..0282005 100644 --- a/contrib/cvs/src/filesubr.c +++ b/contrib/cvs/src/filesubr.c @@ -21,6 +21,7 @@ * $FreeBSD$ */ +#include <assert.h> #include "cvs.h" static int deep_remove_dir PROTO((const char *path)); @@ -417,12 +418,12 @@ unlink_file (f) const char *f; { if (trace) - (void) fprintf (stderr, "%s-> unlink(%s)\n", + (void) fprintf (stderr, "%s-> unlink_file(%s)\n", CLIENT_SERVER_STR, f); if (noexec) return (0); - return (unlink (f)); + return (CVS_UNLINK (f)); } /* @@ -468,7 +469,7 @@ unlink_file_dir (f) else if (S_ISDIR (sb.st_mode)) return deep_remove_dir (f); - return unlink (f); + return CVS_UNLINK (f); } /* Remove a directory and everything it contains. Returns 0 for @@ -491,14 +492,14 @@ deep_remove_dir (path) returns 87). */ || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87)) { - if ((dirp = opendir (path)) == NULL) + if ((dirp = CVS_OPENDIR (path)) == NULL) /* If unable to open the directory return * an error */ return -1; errno = 0; - while ((dp = readdir (dirp)) != NULL) + while ((dp = CVS_READDIR (dirp)) != NULL) { char *buf; @@ -516,16 +517,16 @@ deep_remove_dir (path) { if (deep_remove_dir(buf)) { - closedir(dirp); + CVS_CLOSEDIR(dirp); free (buf); return -1; } } else { - if (unlink (buf) != 0) + if (CVS_UNLINK (buf) != 0) { - closedir(dirp); + CVS_CLOSEDIR(dirp); free (buf); return -1; } @@ -537,11 +538,11 @@ deep_remove_dir (path) if (errno != 0) { int save_errno = errno; - closedir (dirp); + CVS_CLOSEDIR (dirp); errno = save_errno; return -1; } - closedir (dirp); + CVS_CLOSEDIR (dirp); return rmdir (path); } else @@ -688,71 +689,167 @@ xcmp (file1, file2) } /* Generate a unique temporary filename. Returns a pointer to a newly - malloc'd string containing the name. Returns successfully or not at - all. */ -/* There are at least three functions for generating temporary - filenames. We use tempnam (SVID 3) if possible, else mktemp (BSD - 4.3), and as last resort tmpnam (POSIX). Reason is that tempnam and - mktemp both allow to specify the directory in which the temporary - file will be created. */ -#if 1 + * malloc'd string containing the name. Returns successfully or not at + * all. + * + * THIS FUNCTION IS DEPRECATED!!! USE cvs_temp_file INSTEAD!!! + * + * and yes, I know about the way the rcs commands use temp files. I think + * they should be converted too but I don't have time to look into it right + * now. + */ char * cvs_temp_name () { - char *value; - int retval; - - value = xmalloc (strlen (Tmpdir) + 40); - sprintf (value, "%s/%s", Tmpdir, "cvsXXXXXXXXXX"); - retval = mkstemp (value); + char *fn; + FILE *fp; - if (retval == -1) - error (1, errno, "cannot generate temporary filename"); - close (retval); - return value; + fp = cvs_temp_file (&fn); + if (fp == NULL) + error (1, errno, "Failed to create temporary file"); + if (fclose (fp) == EOF) + error (0, errno, "Failed to close temporary file %s", fn); + return fn; } -#else -#ifdef HAVE_TEMPNAM -char * -cvs_temp_name () + +/* Generate a unique temporary filename and return an open file stream + * to the truncated file by that name + * + * INPUTS + * filename where to place the pointer to the newly allocated file + * name string + * + * OUTPUTS + * filename dereferenced, will point to the newly allocated file + * name string. This value is undefined if the function + * returns an error. + * + * RETURNS + * An open file pointer to a read/write mode empty temporary file with the + * unique file name or NULL on failure. + * + * ERRORS + * on error, errno will be set to some value either by CVS_FOPEN or + * whatever system function is called to generate the temporary file name + */ +/* There are at least four functions for generating temporary + * filenames. We use mkstemp (BSD 4.3) if possible, else tempnam (SVID 3), + * else mktemp (BSD 4.3), and as last resort tmpnam (POSIX). Reason is that + * mkstemp, tempnam, and mktemp both allow to specify the directory in which + * the temporary file will be created. + * + * And the _correct_ way to use the deprecated functions probably involves + * opening file descriptors using O_EXCL & O_CREAT and even doing the annoying + * NFS locking thing, but until I hear of more problems, I'm not going to + * bother. + */ +FILE *cvs_temp_file (filename) + char **filename; { - char *retval; + char *fn; + FILE *fp; + + /* FIXME - I'd like to be returning NULL here in noexec mode, but I think + * some of the rcs & diff functions which rely on a temp file run in + * noexec mode too. + */ + + assert (filename != NULL); + +#ifdef HAVE_MKSTEMP + + { + int fd; + + fn = xmalloc (strlen (Tmpdir) + 11); + sprintf (fn, "%s/%s", Tmpdir, "cvsXXXXXX" ); + fd = mkstemp (fn); + + /* a NULL return will be interpreted by callers as an error and + * errno should still be set + */ + if (fd == -1) fp = NULL; + else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL) + { + /* attempt to close and unlink the file since mkstemp returned sucessfully and + * we believe it's been created and opened + */ + int save_errno = errno; + if (close (fd)) + error (0, errno, "Failed to close temporary file %s", fn); + if (CVS_UNLINK (fn)) + error (0, errno, "Failed to unlink temporary file %s", fn); + errno = save_errno; + } + + if (fp == NULL) free (fn); + /* mkstemp is defined to open mode 0600 using glibc 2.0.7+ */ + /* FIXME - configure can probably tell us which version of glibc we are + * linking to and not chmod for 2.0.7+ + */ + else chmod (fn, 0600); + + } + +#elif HAVE_TEMPNAM + + /* tempnam has been deprecated due to under-specification */ + + fn = tempnam (Tmpdir, "cvs"); + if (fn == NULL) fp = NULL; + else if ((fp = CVS_FOPEN (fn, "w+")) == NULL) free (fn); + else chmod (fn, 0600); - retval = tempnam (Tmpdir, "cvs"); - if (retval == NULL) - error (1, errno, "cannot generate temporary filename"); /* tempnam returns a pointer to a newly malloc'd string, so there's - no need for a xstrdup */ - return retval; -} -#else -char * -cvs_temp_name () -{ -# ifdef HAVE_MKTEMP - char *value; - char *retval; - - value = xmalloc (strlen (Tmpdir) + 40); - sprintf (value, "%s/%s", Tmpdir, "cvsXXXXXX" ); - retval = mktemp (value); - - if (retval == NULL) - error (1, errno, "cannot generate temporary filename"); - return value; -# else - char value[L_tmpnam + 1]; - char *retval; - - retval = tmpnam (value); - if (retval == NULL) - error (1, errno, "cannot generate temporary filename"); - return xstrdup (value); -# endif -} -#endif + * no need for a xstrdup + */ + +#elif HAVE_MKTEMP + + /* mktemp has been deprecated due to the BSD 4.3 specification specifying + * that XXXXXX will be replaced by a PID and a letter, creating only 26 + * possibilities, a security risk, and a race condition. + */ + + { + char *ifn; + + ifn = xmalloc (strlen (Tmpdir) + 11); + sprintf (ifn, "%s/%s", Tmpdir, "cvsXXXXXX" ); + fn = mktemp (ifn); + + if (fn == NULL) fp = NULL; + else fp = CVS_FOPEN (fn, "w+"); + + if (fp == NULL) free (ifn); + else chmod (fn, 0600); + + } + +#else /* use tmpnam if all else fails */ + + /* tmpnam is deprecated */ + + { + char ifn[L_tmpnam + 1]; + + fn = tmpnam (ifn); + + if (fn == NULL) fp = NULL; + else if ((fp = CVS_FOPEN (ifn, "w+")) != NULL) + { + fn = xstrdup (ifn); + chmod (fn, 0600); + } + + } + #endif - + + *filename = fn; + return fp; +} + /* Return non-zero iff FILENAME is absolute. Trivial under Unix, but more complicated under other systems. */ int @@ -841,13 +938,17 @@ char * get_homedir () { static char *home = NULL; - char *env = getenv ("HOME"); + char *env; struct passwd *pw; if (home != NULL) return home; - if (env) + if ( +#ifdef SERVER_SUPPORT + !server_active && +#endif + (env = getenv ("HOME")) != NULL) home = env; else if ((pw = (struct passwd *) getpwuid (getuid ())) && pw->pw_dir) @@ -954,7 +1055,7 @@ fopen_case (name, mode, fp, pathp) } } errno = 0; - while ((dp = readdir (dirp)) != NULL) + while ((dp = CVS_READDIR (dirp)) != NULL) { if (cvs_casecmp (dp->d_name, fname) == 0) { @@ -966,7 +1067,7 @@ fopen_case (name, mode, fp, pathp) } if (errno != 0) error (1, errno, "cannot read directory %s", dir); - closedir (dirp); + CVS_CLOSEDIR (dirp); if (found_name == NULL) { |