1/* indir.c 2 See if a file is in a directory. 3 4 Copyright (C) 1992 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#include "uudefs.h" 28#include "sysdep.h" 29#include "system.h" 30 31#include <errno.h> 32 33/* See whether a file is in a directory, and optionally check access. */ 34 35boolean 36fsysdep_in_directory (zfile, zdir, fcheck, freadable, zuser) 37 const char *zfile; 38 const char *zdir; 39 boolean fcheck; 40 boolean freadable; 41 const char *zuser; 42{ 43 size_t c; 44 char *zcopy, *zslash; 45 struct stat s; 46 47 if (*zfile != '/') 48 return FALSE; 49 c = strlen (zdir); 50 if (c > 0 && zdir[c - 1] == '/') 51 c--; 52 if (strncmp (zfile, zdir, c) != 0 53 || (zfile[c] != '/' && zfile[c] != '\0')) 54 return FALSE; 55 if (strstr (zfile + c, "/../") != NULL) 56 return FALSE; 57 58 /* If we're not checking access, get out now. */ 59 if (! fcheck) 60 return TRUE; 61 62 zcopy = zbufcpy (zfile); 63 64 /* Start checking directories after zdir. Otherwise, we would 65 require that all directories down to /usr/spool/uucppublic be 66 publically searchable; they probably are but it should not be a 67 requirement. */ 68 zslash = zcopy + c; 69 do 70 { 71 char b; 72 struct stat shold; 73 74 b = *zslash; 75 *zslash = '\0'; 76 77 shold = s; 78 if (stat (zcopy, &s) != 0) 79 { 80 if (errno != ENOENT) 81 { 82 ulog (LOG_ERROR, "stat (%s): %s", zcopy, strerror (errno)); 83 ubuffree (zcopy); 84 return FALSE; 85 } 86 87 /* If this is the top directory, any problems will be caught 88 later when we try to open it. */ 89 if (zslash == zcopy + c) 90 { 91 ubuffree (zcopy); 92 return TRUE; 93 } 94 95 /* Go back and check the last directory for read or write 96 access. */ 97 s = shold; 98 break; 99 } 100 101 /* If this is not a directory, get out of the loop. */ 102 if (! S_ISDIR (s.st_mode)) 103 break; 104 105 /* Make sure the directory is searchable. */ 106 if (! fsuser_access (&s, X_OK, zuser)) 107 { 108 ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES)); 109 ubuffree (zcopy); 110 return FALSE; 111 } 112 113 /* If we've reached the end of the string, get out. */ 114 if (b == '\0') 115 break; 116 117 *zslash = b; 118 } 119 while ((zslash = strchr (zslash + 1, '/')) != NULL); 120 121 /* At this point s holds a stat on the last component of the path. 122 We must check it for readability or writeability. */ 123 if (! fsuser_access (&s, freadable ? R_OK : W_OK, zuser)) 124 { 125 ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES)); 126 ubuffree (zcopy); 127 return FALSE; 128 } 129 130 ubuffree (zcopy); 131 return TRUE; 132} 133