aboutsummaryrefslogtreecommitdiff
path: root/gnu/libexec/uucp/libunix/indir.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/libexec/uucp/libunix/indir.c')
-rw-r--r--gnu/libexec/uucp/libunix/indir.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/indir.c b/gnu/libexec/uucp/libunix/indir.c
new file mode 100644
index 000000000000..2484ec23f85d
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/indir.c
@@ -0,0 +1,133 @@
+/* indir.c
+ See if a file is in a directory.
+
+ Copyright (C) 1992 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ */
+
+#include "uucp.h"
+
+#include "uudefs.h"
+#include "sysdep.h"
+#include "system.h"
+
+#include <errno.h>
+
+/* See whether a file is in a directory, and optionally check access. */
+
+boolean
+fsysdep_in_directory (zfile, zdir, fcheck, freadable, zuser)
+ const char *zfile;
+ const char *zdir;
+ boolean fcheck;
+ boolean freadable;
+ const char *zuser;
+{
+ size_t c;
+ char *zcopy, *zslash;
+ struct stat s;
+
+ if (*zfile != '/')
+ return FALSE;
+ c = strlen (zdir);
+ if (c > 0 && zdir[c - 1] == '/')
+ c--;
+ if (strncmp (zfile, zdir, c) != 0
+ || (zfile[c] != '/' && zfile[c] != '\0'))
+ return FALSE;
+ if (strstr (zfile + c, "/../") != NULL)
+ return FALSE;
+
+ /* If we're not checking access, get out now. */
+ if (! fcheck)
+ return TRUE;
+
+ zcopy = zbufcpy (zfile);
+
+ /* Start checking directories after zdir. Otherwise, we would
+ require that all directories down to /usr/spool/uucppublic be
+ publically searchable; they probably are but it should not be a
+ requirement. */
+ zslash = zcopy + c;
+ do
+ {
+ char b;
+ struct stat shold;
+
+ b = *zslash;
+ *zslash = '\0';
+
+ shold = s;
+ if (stat (zcopy, &s) != 0)
+ {
+ if (errno != ENOENT)
+ {
+ ulog (LOG_ERROR, "stat (%s): %s", zcopy, strerror (errno));
+ ubuffree (zcopy);
+ return FALSE;
+ }
+
+ /* If this is the top directory, any problems will be caught
+ later when we try to open it. */
+ if (zslash == zcopy + c)
+ {
+ ubuffree (zcopy);
+ return TRUE;
+ }
+
+ /* Go back and check the last directory for read or write
+ access. */
+ s = shold;
+ break;
+ }
+
+ /* If this is not a directory, get out of the loop. */
+ if (! S_ISDIR (s.st_mode))
+ break;
+
+ /* Make sure the directory is searchable. */
+ if (! fsuser_access (&s, X_OK, zuser))
+ {
+ ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
+ ubuffree (zcopy);
+ return FALSE;
+ }
+
+ /* If we've reached the end of the string, get out. */
+ if (b == '\0')
+ break;
+
+ *zslash = b;
+ }
+ while ((zslash = strchr (zslash + 1, '/')) != NULL);
+
+ /* At this point s holds a stat on the last component of the path.
+ We must check it for readability or writeability. */
+ if (! fsuser_access (&s, freadable ? R_OK : W_OK, zuser))
+ {
+ ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
+ ubuffree (zcopy);
+ return FALSE;
+ }
+
+ ubuffree (zcopy);
+ return TRUE;
+}