Upgrade to version 1.05
[unix-history] / gnu / libexec / uucp / libunix / indir.c
CommitLineData
41c799d4
C
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., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 The author of the program may be contacted at ian@airs.com or
3469b437 23 c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
41c799d4
C
24 */
25
26#include "uucp.h"
27
28#include "uudefs.h"
29#include "sysdep.h"
30#include "system.h"
31
32#include <errno.h>
33\f
34/* See whether a file is in a directory, and optionally check access. */
35
36boolean
37fsysdep_in_directory (zfile, zdir, fcheck, freadable, zuser)
38 const char *zfile;
39 const char *zdir;
40 boolean fcheck;
41 boolean freadable;
42 const char *zuser;
43{
44 size_t c;
45 char *zcopy, *zslash;
46 struct stat s;
47
48 if (*zfile != '/')
49 return FALSE;
50 c = strlen (zdir);
51 if (c > 0 && zdir[c - 1] == '/')
52 c--;
53 if (strncmp (zfile, zdir, c) != 0
54 || (zfile[c] != '/' && zfile[c] != '\0'))
55 return FALSE;
56 if (strstr (zfile + c, "/../") != NULL)
57 return FALSE;
58
59 /* If we're not checking access, get out now. */
60 if (! fcheck)
61 return TRUE;
62
63 zcopy = zbufcpy (zfile);
64
65 /* Start checking directories after zdir. Otherwise, we would
66 require that all directories down to /usr/spool/uucppublic be
67 publically searchable; they probably are but it should not be a
68 requirement. */
69 zslash = zcopy + c;
70 do
71 {
72 char b;
73 struct stat shold;
74
75 b = *zslash;
76 *zslash = '\0';
77
78 shold = s;
79 if (stat (zcopy, &s) != 0)
80 {
81 if (errno != ENOENT)
82 {
83 ulog (LOG_ERROR, "stat (%s): %s", zcopy, strerror (errno));
84 ubuffree (zcopy);
85 return FALSE;
86 }
87
88 /* If this is the top directory, any problems will be caught
89 later when we try to open it. */
90 if (zslash == zcopy + c)
91 {
92 ubuffree (zcopy);
93 return TRUE;
94 }
95
96 /* Go back and check the last directory for read or write
97 access. */
98 s = shold;
99 break;
100 }
101
102 /* If this is not a directory, get out of the loop. */
103 if (! S_ISDIR (s.st_mode))
104 break;
105
106 /* Make sure the directory is searchable. */
107 if (! fsuser_access (&s, X_OK, zuser))
108 {
109 ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
110 ubuffree (zcopy);
111 return FALSE;
112 }
113
114 /* If we've reached the end of the string, get out. */
115 if (b == '\0')
116 break;
117
118 *zslash = b;
119 }
120 while ((zslash = strchr (zslash + 1, '/')) != NULL);
121
122 /* At this point s holds a stat on the last component of the path.
123 We must check it for readability or writeability. */
124 if (! fsuser_access (&s, freadable ? R_OK : W_OK, zuser))
125 {
126 ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
127 ubuffree (zcopy);
128 return FALSE;
129 }
130
131 ubuffree (zcopy);
132 return TRUE;
133}