134 lines
3.4 KiB
C
134 lines
3.4 KiB
C
/* 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;
|
||
}
|