freebsd-nq/gnu/libexec/uucp/libunix/indir.c

134 lines
3.4 KiB
C
Raw Normal View History

1993-08-05 18:28:27 +00:00
/* 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;
}