Bug Summary

File:src/usr.sbin/makefs/msdos/msdosfs_denode.c
Warning:line 178, column 5
Value stored to 'error' 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 msdosfs_denode.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.sbin/makefs/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/makefs -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/makefs/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.sbin/makefs/msdos/msdosfs_denode.c
1/* $OpenBSD: msdosfs_denode.c,v 1.7 2021/10/06 00:40:41 deraadt Exp $ */
2/* $NetBSD: msdosfs_denode.c,v 1.7 2015/03/29 05:52:59 agc Exp $ */
3
4/*-
5 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
6 * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
7 * All rights reserved.
8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by TooLs GmbH.
21 * 4. The name of TooLs GmbH may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35/*
36 * Written by Paul Popelka (paulp@uts.amdahl.com)
37 *
38 * You can do anything you want with this software, just don't say you wrote
39 * it, and don't remove this notice.
40 *
41 * This software is provided "as is".
42 *
43 * The author supplies this software to be publicly redistributed on the
44 * understanding that the author is not responsible for the correct
45 * functioning of this software in any circumstances and is not liable for
46 * any damages caused by this software.
47 *
48 * October 1992
49 */
50
51
52#include "ffs/buf.h"
53
54#include <msdosfs/bpb.h>
55#include "msdos/msdosfsmount.h"
56#include "msdos/direntry.h"
57#include "msdos/denode.h"
58#include "msdos/fat.h"
59
60#include <util.h>
61
62#include "makefs.h"
63
64/*
65 * If deget() succeeds it returns with the gotten denode locked().
66 *
67 * pmp - address of msdosfsmount structure of the filesystem containing
68 * the denode of interest. The pm_dev field and the address of
69 * the msdosfsmount structure are used.
70 * dirclust - which cluster bp contains, if dirclust is 0 (root directory)
71 * diroffset is relative to the beginning of the root directory,
72 * otherwise it is cluster relative.
73 * diroffset - offset past begin of cluster of denode we want
74 * depp - returns the address of the gotten denode.
75 */
76int
77deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
78 struct denode **depp)
79 /* pmp: so we know the maj/min number */
80 /* dirclust: cluster this dir entry came from */
81 /* diroffset: index of entry within the cluster */
82 /* depp: returns the addr of the gotten denode */
83{
84 int error;
85 struct direntry *direntptr;
86 struct denode *ldep;
87 struct mkfsbuf *bp;
88
89#ifdef MSDOSFS_DEBUG
90 printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n",
91 pmp, dirclust, diroffset, depp);
92#endif
93
94 /*
95 * On FAT32 filesystems, root is a (more or less) normal
96 * directory
97 */
98 if (FAT32(pmp)(pmp->pm_fatmask == 0x0fffffff) && dirclust == MSDOSFSROOT0)
99 dirclust = pmp->pm_rootdirblk;
100
101 ldep = ecalloc(1, sizeof(*ldep));
102 ldep->de_mkfsvnode = NULL((void*)0);
103 ldep->de_flag = 0;
104 ldep->de_devvp = 0;
105 ldep->de_lockf = 0;
106 ldep->de_dev = pmp->pm_dev;
107 ldep->de_dirclustde_key.dk_dirclust = dirclust;
108 ldep->de_diroffsetde_key.dk_diroffset = diroffset;
109 ldep->de_pmp = pmp;
110 ldep->de_devvp = pmp->pm_devvp;
111 ldep->de_refcnt = 1;
112 fc_purge(ldep, 0);
113 /*
114 * Copy the directory entry into the denode area of the mkfsvnode.
115 */
116 if ((dirclust == MSDOSFSROOT0
117 || (FAT32(pmp)(pmp->pm_fatmask == 0x0fffffff) && dirclust == pmp->pm_rootdirblk))
118 && diroffset == MSDOSFSROOT_OFS0x1fffffff) {
119 /*
120 * Directory entry for the root directory. There isn't one,
121 * so we manufacture one. We should probably rummage
122 * through the root directory and find a label entry (if it
123 * exists), and then use the time and date from that entry
124 * as the time and date for the root denode.
125 */
126 ldep->de_mkfsvnode = (struct mkfsvnode *)-1;
127
128 ldep->de_Attributes = ATTR_DIRECTORY0x10;
129 if (FAT32(pmp)(pmp->pm_fatmask == 0x0fffffff))
130 ldep->de_StartCluster = pmp->pm_rootdirblk;
131 /* de_FileSize will be filled in further down */
132 else {
133 ldep->de_StartCluster = MSDOSFSROOT0;
134 ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec;
135 }
136 /*
137 * fill in time and date so that dos2unixtime() doesn't
138 * spit up when called from msdosfs_getattr() with root
139 * denode
140 */
141 ldep->de_CHun = 0;
142 ldep->de_CTime = 0x0000; /* 00:00:00 */
143 ldep->de_CDate = (0 << DD_YEAR_SHIFT9) | (1 << DD_MONTH_SHIFT5)
144 | (1 << DD_DAY_SHIFT0);
145 /* Jan 1, 1980 */
146 ldep->de_ADate = ldep->de_CDate;
147 ldep->de_MTime = ldep->de_CTime;
148 ldep->de_MDate = ldep->de_CDate;
149 /* leave the other fields as garbage */
150 } else {
151 error = readep(pmp, dirclust, diroffset, &bp, &direntptr);
152 if (error) {
153 ldep->de_devvp = NULL((void*)0);
154 ldep->de_Name[0] = SLOT_DELETED0xe5;
155 return (error);
156 }
157 DE_INTERNALIZE(ldep, direntptr)(memcpy((ldep)->de_Name, (direntptr)->deName, 11), (ldep
)->de_Attributes = (direntptr)->deAttributes, (ldep)->
de_CHun = (direntptr)->deCTimeHundredth, (ldep)->de_CTime
= *((u_int16_t *)((direntptr)->deCTime)), (ldep)->de_CDate
= *((u_int16_t *)((direntptr)->deCDate)), (ldep)->de_ADate
= *((u_int16_t *)((direntptr)->deADate)), (ldep)->de_MTime
= *((u_int16_t *)((direntptr)->deMTime)), (ldep)->de_MDate
= *((u_int16_t *)((direntptr)->deMDate)), (ldep)->de_StartCluster
= *((u_int16_t *)((direntptr)->deStartCluster)), (ldep)->
de_FileSize = *((u_int32_t *)((direntptr)->deFileSize)), (
((ldep)->de_pmp->pm_fatmask == 0x0fffffff) ? (((ldep))->
de_StartCluster |= *((u_int16_t *)(((direntptr))->deHighClust
)) << 16) : 0))
;
158 brelse(bp, 0);
159 }
160
161 /*
162 * Fill in a few fields of the mkfsvnode and finish filling in the
163 * denode. Then return the address of the found denode.
164 */
165 if (ldep->de_Attributes & ATTR_DIRECTORY0x10) {
166 /*
167 * Since DOS directory entries that describe directories
168 * have 0 in the filesize field, we take this opportunity
169 * to find out the length of the directory and plug it into
170 * the denode structure.
171 */
172 u_long size;
173
174 if (ldep->de_StartCluster != MSDOSFSROOT0) {
175 error = pcbmap(ldep, CLUST_END0xffffffff, 0, &size, 0);
176 if (error == E2BIG7) {
177 ldep->de_FileSize = de_cn2off(pmp, size)((size) << (pmp)->pm_cnshift);
178 error = 0;
Value stored to 'error' is never read
179 } else
180 printf("deget(): pcbmap returned %d\n", error);
181 }
182 }
183 *depp = ldep;
184 return (0);
185}
186
187/*
188 * Truncate the file described by dep to the length specified by length.
189 */
190int
191detrunc(struct denode *dep, u_long length, int flags)
192{
193 int error;
194 int allerror = 0;
195 u_long eofentry;
196 u_long chaintofree = 0;
197 daddr_t bn, lastblock;
198 int boff;
199 int isadir = dep->de_Attributes & ATTR_DIRECTORY0x10;
200 struct mkfsbuf *bp;
201 struct msdosfsmount *pmp = dep->de_pmp;
202
203#ifdef MSDOSFS_DEBUG
204 printf("detrunc(): file %s, length %lu, flags %x\n", dep->de_Name, length, flags);
205#endif
206
207 /*
208 * Disallow attempts to truncate the root directory since it is of
209 * fixed size. That's just the way dos filesystems are. We use
210 * the VROOT bit in the mkfsvnode because checking for the directory
211 * bit and a startcluster of 0 in the denode is not adequate to
212 * recognize the root directory at this point in a file or
213 * directory's life.
214 */
215 if (dep->de_mkfsvnode != NULL((void*)0) && !FAT32(pmp)(pmp->pm_fatmask == 0x0fffffff)) {
216 printf("detrunc(): can't truncate root directory, clust %ld, offset %ld\n",
217 dep->de_dirclustde_key.dk_dirclust, dep->de_diroffsetde_key.dk_diroffset);
218 return (EINVAL22);
219 }
220
221 if (dep->de_FileSize < length)
222 return (deextend(dep, length));
223 lastblock = de_clcount(pmp, length)(((length) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift
)
- 1;
224
225 /*
226 * If the desired length is 0 then remember the starting cluster of
227 * the file and set the StartCluster field in the directory entry
228 * to 0. If the desired length is not zero, then get the number of
229 * the last cluster in the shortened file. Then get the number of
230 * the first cluster in the part of the file that is to be freed.
231 * Then set the next cluster pointer in the last cluster of the
232 * file to CLUST_EOFE.
233 */
234 if (length == 0) {
235 chaintofree = dep->de_StartCluster;
236 dep->de_StartCluster = 0;
237 eofentry = ~0;
238 } else {
239 error = pcbmap(dep, lastblock, 0, &eofentry, 0);
240 if (error) {
241#ifdef MSDOSFS_DEBUG
242 printf("detrunc(): pcbmap fails %d\n", error);
243#endif
244 return (error);
245 }
246 }
247
248 /*
249 * If the new length is not a multiple of the cluster size then we
250 * must zero the tail end of the new last cluster in case it
251 * becomes part of the file again because of a seek.
252 */
253 if ((boff = length & pmp->pm_crbomask) != 0) {
254 if (isadir) {
255 bn = cntobn(pmp, eofentry)((((eofentry)-2) << (((pmp))->pm_cnshift - ((pmp))->
pm_bnshift)) + (pmp)->pm_firstcluster)
;
256 error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn)((bn) << ((pmp)->pm_bnshift - 9)),
257 pmp->pm_bpcluster, B_MODIFY0, &bp);
258 if (error) {
259#ifdef MSDOSFS_DEBUG
260 printf("detrunc(): bread fails %d\n", error);
261#endif
262 return (error);
263 }
264 memset((char *)bp->b_data + boff, 0,
265 pmp->pm_bpcluster - boff);
266 if (flags & IO_SYNC1)
267 bwrite(bp);
268 else
269 bdwrite(bp)bwrite(bp);
270 }
271 }
272
273 /*
274 * Write out the updated directory entry. Even if the update fails
275 * we free the trailing clusters.
276 */
277 dep->de_FileSize = length;
278 if (!isadir)
279 dep->de_flag |= DE_UPDATE0x0001|DE_MODIFIED0x0008;
280#ifdef MSDOSFS_DEBUG
281 printf("detrunc(): allerror %d, eofentry %lu\n",
282 allerror, eofentry);
283#endif
284
285 /*
286 * If we need to break the cluster chain for the file then do it
287 * now.
288 */
289 if (eofentry != (u_long)~0) {
290 error = fatentry(FAT_GET_AND_SET(0x0001 | 0x0002), pmp, eofentry,
291 &chaintofree, CLUST_EOFE0xffffffff);
292 if (error) {
293#ifdef MSDOSFS_DEBUG
294 printf("detrunc(): fatentry errors %d\n", error);
295#endif
296 return (error);
297 }
298 }
299
300 /*
301 * Now free the clusters removed from the file because of the
302 * truncation.
303 */
304 if (chaintofree != 0 && !MSDOSFSEOF(chaintofree, pmp->pm_fatmask)(((chaintofree) & 0xfffffff8) == (0xfffffff8 & (pmp->
pm_fatmask)))
)
305 freeclusterchain(pmp, chaintofree);
306
307 return (allerror);
308}
309
310/*
311 * Extend the file described by dep to length specified by length.
312 */
313int
314deextend(struct denode *dep, u_long length)
315{
316 struct msdosfsmount *pmp = dep->de_pmp;
317 u_long count;
318 int error;
319
320 /*
321 * The root of a DOS filesystem cannot be extended.
322 */
323 if (dep->de_mkfsvnode != NULL((void*)0) && !FAT32(pmp)(pmp->pm_fatmask == 0x0fffffff))
324 return EINVAL22;
325
326 /*
327 * Directories cannot be extended.
328 */
329 if (dep->de_Attributes & ATTR_DIRECTORY0x10)
330 return EISDIR21;
331
332 if (length <= dep->de_FileSize)
333 return E2BIG7;
334
335 /*
336 * Compute the number of clusters to allocate.
337 */
338 count = de_clcount(pmp, length)(((length) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift
)
- de_clcount(pmp, dep->de_FileSize)(((dep->de_FileSize) + (pmp)->pm_bpcluster - 1) >>
(pmp)->pm_cnshift)
;
339 if (count > 0) {
340 if (count > pmp->pm_freeclustercount)
341 return (ENOSPC28);
342 error = extendfile(dep, count, NULL((void*)0), NULL((void*)0), DE_CLEAR1);
343 if (error) {
344 /* truncate the added clusters away again */
345 (void) detrunc(dep, dep->de_FileSize, 0);
346 return (error);
347 }
348 }
349
350 /*
351 * Zero extend file range; ubc_zerorange() uses ubc_alloc() and a
352 * memset(); we set the write size so ubc won't read in file data that
353 * is zero'd later.
354 */
355 dep->de_FileSize = length;
356 dep->de_flag |= DE_UPDATE0x0001|DE_MODIFIED0x0008;
357 return 0;
358}