Bug Summary

File:src/usr.bin/rdistd/filesys.c
Warning:line 73, column 4
Value stored to 'statbuf' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name filesys.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/rdistd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/rdistd/../rdist -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/rdistd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/rdistd/filesys.c
1/* $OpenBSD: filesys.c,v 1.19 2015/01/21 04:08:37 guenther Exp $ */
2
3/*
4 * Copyright (c) 1983 Regents of the University of California.
5 * All rights reserved.
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 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/types.h>
33#include <sys/mount.h>
34#include <errno(*__errno()).h>
35#include <string.h>
36#include <unistd.h>
37
38#include "server.h"
39
40/*
41 * This file contains functions dealing with getting info
42 * about mounted filesystems.
43 */
44
45
46jmp_buf env;
47
48/*
49 * Given a pathname, find the fullest component that exists.
50 * If statbuf is not NULL, set it to point at our stat buffer.
51 */
52char *
53find_file(char *pathname, struct stat *statbuf, int *isvalid)
54{
55 static char last_pathname[PATH_MAX1024];
56 static char file[PATH_MAX1024 + 3];
57 static struct stat filestat;
58 char *p;
59
60 /*
61 * Mark the statbuf as invalid to start with.
62 */
63 *isvalid = 0;
64
65 /*
66 * If this is the same pathname as the last time, and
67 * the file buffer is valid and we're doing the same stat()
68 * or lstat(), then set statbuf to the last filestat and
69 * return the last file we found.
70 */
71 if (strcmp(pathname, last_pathname) == 0 && file[0]) {
72 if (statbuf)
73 statbuf = &filestat;
Value stored to 'statbuf' is never read
74 if (strcmp(pathname, file) == 0)
75 *isvalid = 1;
76 return(file);
77 }
78
79 if (strlen(pathname) > sizeof(file) + 3) {
80 error("%s: Name to large for buffer.", pathname);
81 return(NULL((void *)0));
82 }
83
84 /*
85 * Save for next time
86 */
87 (void) strlcpy(last_pathname, pathname, sizeof(last_pathname));
88
89 if (*pathname == '/')
90 (void) strlcpy(file, pathname, sizeof(file));
91 else {
92 /*
93 * Ensure we have a directory (".") in our path
94 * so we have something to stat in case the file
95 * does not exist.
96 */
97 (void) strlcpy(file, "./", sizeof(file));
98 (void) strlcat(file, pathname, sizeof(file));
99 }
100
101 while (lstat(file, &filestat) != 0) {
102 /*
103 * Trim the last part of the pathname to try next level up
104 */
105 if (errno(*__errno()) == ENOENT2) {
106 /*
107 * Trim file name to get directory name.
108 * Normally we want to change /dir1/dir2/file
109 * into "/dir1/dir2/."
110 */
111 if ((p = strrchr(file, '/')) != NULL((void *)0)) {
112 if (strcmp(p, "/.") == 0) {
113 *p = CNULL'\0';
114 } else {
115 *++p = '.';
116 *++p = CNULL'\0';
117 }
118 } else {
119 /*
120 * Couldn't find anything, so give up.
121 */
122 debugmsg(DM_MISC0x10, "Cannot find dir of `%s'",
123 pathname);
124 return(NULL((void *)0));
125 }
126 continue;
127 } else {
128 error("%s: lstat failed: %s", pathname, SYSERRstrerror((*__errno())));
129 return(NULL((void *)0));
130 }
131 }
132
133 if (statbuf)
134 bcopy(&filestat, statbuf, sizeof(filestat));
135
136 /*
137 * Trim the "/." that we added.
138 */
139 p = &file[strlen(file) - 1];
140 if (*p == '.')
141 *p-- = CNULL'\0';
142 for ( ; p && *p && *p == '/' && p != file; --p)
143 *p = CNULL'\0';
144
145 /*
146 * If this file is a symlink we really want the parent directory
147 * name in case the symlink points to another filesystem.
148 */
149 if (S_ISLNK(filestat.st_mode)((filestat.st_mode & 0170000) == 0120000))
150 if ((p = strrchr(file, '/')) && *p+1) {
151 /* Is this / (root)? */
152 if (p == file)
153 file[1] = CNULL'\0';
154 else
155 *p = CNULL'\0';
156 }
157
158 if (strcmp(pathname, file) == 0)
159 *isvalid = 1;
160
161 return(*file ? file : NULL((void *)0));
162}
163
164
165/*
166 * Find the device that "filest" is on in the "mntinfo" linked list.
167 */
168mntent_t *
169findmnt(struct stat *filest, struct mntinfo *mntinfo)
170{
171 struct mntinfo *mi;
172
173 for (mi = mntinfo; mi; mi = mi->mi_nxt) {
174 if (mi->mi_mnt->me_flags & MEFLAG_IGNORE0x02)
175 continue;
176 if (filest->st_dev == mi->mi_dev)
177 return(mi->mi_mnt);
178 }
179
180 return(NULL((void *)0));
181}
182
183/*
184 * Is "mnt" a duplicate of any of the mntinfo->mi_mnt elements?
185 */
186int
187isdupmnt(mntent_t *mnt, struct mntinfo *mntinfo)
188{
189 struct mntinfo *m;
190
191 for (m = mntinfo; m; m = m->mi_nxt)
192 if (strcmp(m->mi_mnt->me_path, mnt->me_path) == 0)
193 return(1);
194
195 return(0);
196}
197
198/*
199 * Alarm clock
200 */
201void
202wakeup(int dummy)
203{
204 debugmsg(DM_CALL0x01, "wakeup() in filesys.c called");
205 longjmp(env, 1);
206}
207
208/*
209 * Make a linked list of mntinfo structures.
210 * Use "mi" as the base of the list if it's non NULL.
211 */
212struct mntinfo *
213makemntinfo(struct mntinfo *mi)
214{
215 static struct mntinfo *mntinfo;
216 struct mntinfo *newmi, *m;
217 struct stat mntstat;
218 mntent_t *mnt;
219 int timeo = 310;
220
221 if (!setmountent()) {
222 message(MT_NERROR0x0002, "setmntent failed: %s", SYSERRstrerror((*__errno())));
223 return(NULL((void *)0));
224 }
225
226 (void) signal(SIGALRM14, wakeup);
227 (void) alarm(timeo);
228 if (setjmp(env)) {
229 message(MT_NERROR0x0002, "Timeout getting mount info");
230 return(NULL((void *)0));
231 }
232
233 mntinfo = mi;
234 while ((mnt = getmountent()) != NULL((void *)0)) {
235 debugmsg(DM_MISC0x10, "mountent = '%s'", mnt->me_path);
236
237 /*
238 * Make sure we don't already have it for some reason
239 */
240 if (isdupmnt(mnt, mntinfo))
241 continue;
242
243 /*
244 * Get stat info
245 */
246 if (stat(mnt->me_path, &mntstat) != 0) {
247 message(MT_WARNING0x0010, "%s: Cannot stat filesystem: %s",
248 mnt->me_path, SYSERRstrerror((*__errno())));
249 continue;
250 }
251
252 /*
253 * Create new entry
254 */
255 newmi = xcalloc(1, sizeof(*newmi));
256 newmi->mi_mnt = newmountent(mnt);
257 newmi->mi_dev = mntstat.st_dev;
258
259 /*
260 * Add entry to list
261 */
262 if (mntinfo) {
263 for (m = mntinfo; m->mi_nxt; m = m->mi_nxt)
264 continue;
265 m->mi_nxt = newmi;
266 } else
267 mntinfo = newmi;
268 }
269
270 alarm(0);
271 endmountent();
272
273 return(mntinfo);
274}
275
276/*
277 * Given a name like /usr/src/etc/foo.c returns the mntent
278 * structure for the file system it lives in.
279 *
280 * If "statbuf" is not NULL it is used as the stat buffer too avoid
281 * stat()'ing the file again back in server.c.
282 */
283mntent_t *
284getmntpt(char *pathname, struct stat *statbuf, int *isvalid)
285{
286 static struct mntinfo *mntinfo = NULL((void *)0);
287 static struct stat filestat;
288 struct stat *pstat;
289 struct mntinfo *tmpmi;
290 mntent_t *mnt;
291
292 /*
293 * Use the supplied stat buffer if not NULL or our own.
294 */
295 if (statbuf)
296 pstat = statbuf;
297 else
298 pstat = &filestat;
299
300 if (!find_file(pathname, pstat, isvalid))
301 return(NULL((void *)0));
302
303 /*
304 * Make mntinfo if it doesn't exist.
305 */
306 if (!mntinfo)
307 mntinfo = makemntinfo(NULL((void *)0));
308
309 /*
310 * Find the mnt that pathname is on.
311 */
312 if ((mnt = findmnt(pstat, mntinfo)) != NULL((void *)0))
313 return(mnt);
314
315 /*
316 * We failed to find correct mnt, so maybe it's a newly
317 * mounted filesystem. We rebuild mntinfo and try again.
318 */
319 if ((tmpmi = makemntinfo(mntinfo)) != NULL((void *)0)) {
320 mntinfo = tmpmi;
321 if ((mnt = findmnt(pstat, mntinfo)) != NULL((void *)0))
322 return(mnt);
323 }
324
325 error("%s: Could not find mount point", pathname);
326 return(NULL((void *)0));
327}
328
329
330/*
331 * Is "path" NFS mounted? Return 1 if it is, 0 if not, or -1 on error.
332 */
333int
334is_nfs_mounted(char *path, struct stat *statbuf, int *isvalid)
335{
336 mntent_t *mnt;
337
338 if ((mnt = getmntpt(path, statbuf, isvalid)) == NULL((void *)0))
339 return(-1);
340
341 if (mnt->me_flags & MEFLAG_NFS0x04)
342 return(1);
343
344 return(0);
345}
346
347/*
348 * Is "path" on a read-only mounted filesystem?
349 * Return 1 if it is, 0 if not, or -1 on error.
350 */
351int
352is_ro_mounted(char *path, struct stat *statbuf, int *isvalid)
353{
354 mntent_t *mnt;
355
356 if ((mnt = getmntpt(path, statbuf, isvalid)) == NULL((void *)0))
357 return(-1);
358
359 if (mnt->me_flags & MEFLAG_READONLY0x01)
360 return(1);
361
362 return(0);
363}
364
365/*
366 * Is "path" a symlink?
367 * Return 1 if it is, 0 if not, or -1 on error.
368 */
369int
370is_symlinked(char *path, struct stat *statbuf, int *isvalid)
371{
372 static struct stat stb;
373
374 if (!(*isvalid)) {
375 if (lstat(path, &stb) != 0)
376 return(-1);
377 statbuf = &stb;
378 }
379
380 if (S_ISLNK(statbuf->st_mode)((statbuf->st_mode & 0170000) == 0120000))
381 return(1);
382
383 return(0);
384}
385
386/*
387 * Get filesystem information for "file". Set freespace
388 * to the amount of free (available) space and number of free
389 * files (inodes) on the filesystem "file" resides on.
390 * Returns 0 on success or -1 on failure.
391 * Filesystem values < 0 indicate unsupported or unavailable
392 * information.
393 */
394int
395getfilesysinfo(char *file, int64_t *freespace, int64_t *freefiles)
396{
397 struct statfs statfsbuf;
398 char *mntpt;
399 int64_t val;
400 int t, r;
401
402 /*
403 * Get the mount point of the file.
404 */
405 mntpt = find_file(file, NULL((void *)0), &t);
406 if (!mntpt) {
407 debugmsg(DM_MISC0x10, "unknown mount point for `%s'", file);
408 return(-1);
409 }
410
411 r = statfs(mntpt, &statfsbuf);
412 if (r < 0) {
413 error("%s: Cannot statfs filesystem: %s.", mntpt, SYSERRstrerror((*__errno())));
414 return(-1);
415 }
416
417 /*
418 * If values are < 0, then assume the value is unsupported
419 * or unavailable for that filesystem type.
420 */
421 val = -1;
422 if (statfsbuf.f_bavail >= 0)
423 val = (statfsbuf.f_bavail * (statfsbuf.f_bsize / 512)) / 2;
424 *freespace = val;
425
426 val = -1;
427 if (statfsbuf.f_favail >= 0)
428 val = statfsbuf.f_favail;
429 *freefiles = val;
430
431 return(0);
432}