summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/filesubr.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/filesubr.c')
-rw-r--r--contrib/cvs/src/filesubr.c241
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)
{
OpenPOWER on IntegriCloud