1 /*
2 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Chris Pressey <cpressey@catseye.mine.nu>.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35
36 /*
37 * fspred.c
38 * Filesystem predicates.
39 * $Id: fspred.c,v 1.3 2005/02/10 03:33:49 cpressey Exp $
40 */
41
42 #include <sys/stat.h>
43 #include <sys/param.h>
44 #include <sys/ucred.h>
45 #include <sys/mount.h>
46
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52
53 #include "fspred.h"
54
55 /** PREDICATES **/
56
57 static void
vstatmod(mode_t * m,int * error,const char * fmt,va_list args)58 vstatmod(mode_t *m, int *error, const char *fmt, va_list args)
59 {
60 char *filename;
61 struct stat sb;
62
63 memset(&sb, 0, sizeof(sb));
64
65 vasprintf(&filename, fmt, args);
66
67 *error = stat(filename, &sb);
68 free(filename);
69
70 if (*error)
71 *m = 0; /* Do not leak fake mode */
72 else
73 *m = sb.st_mode;
74 }
75
76 int
is_dir(const char * fmt,...)77 is_dir(const char *fmt, ...)
78 {
79 va_list args;
80 int error;
81 mode_t m;
82
83 va_start(args, fmt);
84 vstatmod(&m, &error, fmt, args);
85 va_end(args);
86
87 if (error == 0)
88 return(S_ISDIR(m));
89 else
90 return(0);
91 }
92
93 int
is_file(const char * fmt,...)94 is_file(const char *fmt, ...)
95 {
96 va_list args;
97 int error;
98 mode_t m;
99
100 va_start(args, fmt);
101 vstatmod(&m, &error, fmt, args);
102 va_end(args);
103
104 if (error == 0)
105 return(S_ISREG(m) );
106 else
107 return(0);
108
109 }
110
111 int
is_program(const char * fmt,...)112 is_program(const char *fmt, ...)
113 {
114 char *filename;
115 struct stat sb;
116 va_list args;
117 int error;
118 uid_t uid;
119 gid_t gid;
120
121 va_start(args, fmt);
122 vasprintf(&filename, fmt, args);
123 va_end(args);
124
125 error = stat(filename, &sb);
126 free(filename);
127
128 uid = getuid();
129 gid = getgid();
130
131 if (error == 0) {
132 /* Try to be more precise when identifying executable programs.
133 * Still this is subject to race conditions where the regular file
134 * might have its permissions/ownership changed during the test and
135 * thus provide inaccurate results.
136 * Also, effective uid/gid is not being checked.
137 */
138 if ((S_ISREG(sb.st_mode)) &&
139 ((sb.st_uid == uid && sb.st_mode & S_IXUSR) ||
140 (sb.st_gid == gid && sb.st_mode & S_IXGRP) ||
141 (sb.st_mode & S_IXOTH))) {
142 return 1;
143 }
144 }
145
146 return 0;
147 }
148
149 int
is_device(const char * fmt,...)150 is_device(const char *fmt, ...)
151 {
152 va_list args;
153 int error;
154 mode_t m;
155
156 va_start(args, fmt);
157 vstatmod(&m, &error, fmt, args);
158 va_end(args);
159
160 if (error == 0)
161 return(S_ISBLK(m) || S_ISCHR(m));
162 else
163 return(0);
164 }
165
166 int
is_named_pipe(const char * fmt,...)167 is_named_pipe(const char *fmt, ...)
168 {
169 va_list args;
170 int error;
171 mode_t m;
172
173 va_start(args, fmt);
174 vstatmod(&m, &error, fmt, args);
175 va_end(args);
176
177 if (error == 0)
178 return(S_ISFIFO(m));
179 else
180 return(0);
181 }
182
183 int
is_mountpoint_mounted(const char * mtpt)184 is_mountpoint_mounted(const char *mtpt)
185 {
186 struct statfs *mt_array, *mt_ptr;
187 int count;
188
189 count = getmntinfo(&mt_array, MNT_WAIT);
190 for (mt_ptr = mt_array; count > 0; mt_ptr++, count--) {
191 if (strncmp(mt_ptr->f_mntonname, mtpt, PATH_MAX) == 0)
192 return(1);
193 }
194 return(0);
195 }
196
197 int
is_device_mounted(const char * device)198 is_device_mounted(const char *device)
199 {
200 struct statfs *mt_array, *mt_ptr;
201 int count;
202
203 count = getmntinfo(&mt_array, MNT_WAIT);
204 for (mt_ptr = mt_array; count > 0; mt_ptr++, count--) {
205 if (strncmp(mt_ptr->f_mntfromname, device, PATH_MAX) == 0)
206 return(1);
207 }
208 return(0);
209 }
210
211 int
is_any_slice_mounted(const char * diskdev)212 is_any_slice_mounted(const char *diskdev)
213 {
214 struct statfs *mt_array, *mt_ptr;
215 int count;
216
217 count = getmntinfo(&mt_array, MNT_WAIT);
218 for (mt_ptr = mt_array; count > 0; mt_ptr++, count--) {
219 if (strstr(mt_ptr->f_mntfromname, diskdev) ==
220 mt_ptr->f_mntfromname)
221 return(1);
222 }
223 return(0);
224 }
225