Bug Summary

File:src/usr.bin/du/du.c
Warning:line 299, column 2
Potential leak of memory pointed to by 'le'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name du.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/du/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/du/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/du/du.c
1/* $OpenBSD: du.c,v 1.33 2022/12/04 23:50:48 cheloha Exp $ */
2/* $NetBSD: du.c,v 1.11 1996/10/18 07:20:35 thorpej Exp $ */
3
4/*
5 * Copyright (c) 1989, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Chris Newcomb.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/types.h>
37#include <sys/stat.h>
38
39#include <dirent.h>
40#include <err.h>
41#include <errno(*__errno()).h>
42#include <fts.h>
43#include <limits.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <sys/tree.h>
48#include <unistd.h>
49#include <util.h>
50
51
52int linkchk(FTSENT *);
53void prtout(int64_t, char *, int);
54void usage(void);
55
56int
57main(int argc, char *argv[])
58{
59 FTS *fts;
60 FTSENT *p;
61 long blocksize;
62 int64_t totalblocks;
63 int ftsoptions, listfiles, maxdepth;
64 int Hflag, Lflag, cflag, hflag, kflag;
65 int ch, notused, rval;
66 char **save;
67 const char *errstr;
68
69 if (pledge("stdio rpath", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
70 err(1, "pledge");
71
72 save = argv;
73 Hflag = Lflag = cflag = hflag = kflag = listfiles = 0;
74 totalblocks = 0;
75 ftsoptions = FTS_PHYSICAL0x0010;
76 maxdepth = -1;
77 while ((ch = getopt(argc, argv, "HLPacd:hkrsx")) != -1)
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 122
78 switch (ch) {
79 case 'H':
80 Hflag = 1;
81 Lflag = 0;
82 break;
83 case 'L':
84 Lflag = 1;
85 Hflag = 0;
86 break;
87 case 'P':
88 Hflag = Lflag = 0;
89 break;
90 case 'a':
91 listfiles = 1;
92 break;
93 case 'c':
94 cflag = 1;
95 break;
96 case 'd':
97 maxdepth = strtonum(optarg, 0, INT_MAX0x7fffffff, &errstr);
98 if (errstr) {
99 warnx("max depth %s: %s", optarg, errstr);
100 usage();
101 }
102 break;
103 case 'h':
104 hflag = 1;
105 kflag = 0;
106 break;
107 case 'k':
108 kflag = 1;
109 hflag = 0;
110 break;
111 case 's':
112 maxdepth = 0;
113 break;
114 case 'r':
115 break;
116 case 'x':
117 ftsoptions |= FTS_XDEV0x0040;
118 break;
119 default:
120 usage();
121 }
122 argc -= optind;
123 argv += optind;
124
125 /*
126 * XXX
127 * Because of the way that fts(3) works, logical walks will not count
128 * the blocks actually used by symbolic links. We rationalize this by
129 * noting that users computing logical sizes are likely to do logical
130 * copies, so not counting the links is correct. The real reason is
131 * that we'd have to re-implement the kernel's symbolic link traversing
132 * algorithm to get this right. If, for example, you have relative
133 * symbolic links referencing other relative symbolic links, it gets
134 * very nasty, very fast. The bottom line is that it's documented in
135 * the man page, so it's a feature.
136 */
137 if (Hflag
4.1
'Hflag' is 0
)
5
Taking false branch
138 ftsoptions |= FTS_COMFOLLOW0x0001;
139 if (Lflag
5.1
'Lflag' is 0
) {
6
Taking false branch
140 ftsoptions &= ~FTS_PHYSICAL0x0010;
141 ftsoptions |= FTS_LOGICAL0x0002;
142 }
143
144 if (maxdepth == -1)
7
Taking true branch
145 maxdepth = INT_MAX0x7fffffff;
146
147 if (!*argv) {
8
Assuming the condition is false
9
Taking false branch
148 argv = save;
149 argv[0] = ".";
150 argv[1] = NULL((void *)0);
151 }
152
153 if (hflag
9.1
'hflag' is 0
)
10
Taking false branch
154 blocksize = 512;
155 else if (kflag
10.1
'kflag' is 0
)
11
Taking false branch
156 blocksize = 1024;
157 else
158 (void)getbsize(&notused, &blocksize);
159 blocksize /= 512;
160
161 if ((fts = fts_open(argv, ftsoptions, NULL((void *)0))) == NULL((void *)0))
12
Assuming the condition is false
13
Taking false branch
162 err(1, "fts_open");
163
164 for (rval = 0; (p = fts_read(fts)) != NULL((void *)0);)
14
Assuming the condition is true
15
Loop condition is true. Entering loop body
165 switch (p->fts_info) {
16
Control jumps to the 'default' case at line 191
166 case FTS_D1: /* Ignore. */
167 break;
168 case FTS_DP6:
169 p->fts_parent->fts_number +=
170 p->fts_number += p->fts_statp->st_blocks;
171 if (cflag)
172 totalblocks += p->fts_statp->st_blocks;
173 /*
174 * If listing each directory, or not listing files
175 * or directories and this is post-order of the
176 * root of a traversal, display the total.
177 */
178 if (p->fts_level <= maxdepth)
179 prtout(howmany(p->fts_number,(((p->fts_number) + (((unsigned long)blocksize) - 1)) / ((
unsigned long)blocksize))
180 (unsigned long)blocksize)(((p->fts_number) + (((unsigned long)blocksize) - 1)) / ((
unsigned long)blocksize))
, p->fts_path,
181 hflag);
182 break;
183 case FTS_DC2: /* Ignore. */
184 break;
185 case FTS_DNR4: /* Warn, continue. */
186 case FTS_ERR7:
187 case FTS_NS10:
188 warnc(p->fts_errno, "%s", p->fts_path);
189 rval = 1;
190 break;
191 default:
192 if (p->fts_statp->st_nlink > 1 && linkchk(p))
17
Assuming field 'st_nlink' is > 1
18
Calling 'linkchk'
193 break;
194 /*
195 * If listing each file, or a non-directory file was
196 * the root of a traversal, display the total.
197 */
198 if ((listfiles && p->fts_level <= maxdepth) ||
199 p->fts_level == FTS_ROOTLEVEL0)
200 prtout(howmany(p->fts_statp->st_blocks,(((p->fts_statp->st_blocks) + ((blocksize) - 1)) / (blocksize
))
201 blocksize)(((p->fts_statp->st_blocks) + ((blocksize) - 1)) / (blocksize
))
, p->fts_path, hflag);
202 p->fts_parent->fts_number += p->fts_statp->st_blocks;
203 if (cflag)
204 totalblocks += p->fts_statp->st_blocks;
205 }
206 if (errno(*__errno()))
207 err(1, "fts_read");
208 if (cflag) {
209 prtout(howmany(totalblocks, blocksize)(((totalblocks) + ((blocksize) - 1)) / (blocksize)), "total", hflag);
210 }
211 fts_close(fts);
212 exit(rval);
213}
214
215
216struct links_entry {
217 RB_ENTRY(links_entry)struct { struct links_entry *rbe_left; struct links_entry *rbe_right
; struct links_entry *rbe_parent; int rbe_color; }
entry;
218 struct links_entry *fnext;
219 int links;
220 dev_t dev;
221 ino_t ino;
222};
223
224static int
225links_cmp(struct links_entry *e1, struct links_entry *e2)
226{
227 if (e1->dev == e2->dev) {
228 if (e1->ino == e2->ino)
229 return (0);
230 else
231 return (e1->ino < e2->ino ? -1 : 1);
232 }
233 else
234 return (e1->dev < e2->dev ? -1 : 1);
235}
236
237RB_HEAD(ltree, links_entry)struct ltree { struct links_entry *rbh_root; } links = RB_INITIALIZER(&links){ ((void *)0) };
238
239RB_GENERATE_STATIC(ltree, links_entry, entry, links_cmp)__attribute__((__unused__)) static void ltree_RB_INSERT_COLOR
(struct ltree *head, struct links_entry *elm) { struct links_entry
*parent, *gparent, *tmp; while ((parent = (elm)->entry.rbe_parent
) && (parent)->entry.rbe_color == 1) { gparent = (
parent)->entry.rbe_parent; if (parent == (gparent)->entry
.rbe_left) { tmp = (gparent)->entry.rbe_right; if (tmp &&
(tmp)->entry.rbe_color == 1) { (tmp)->entry.rbe_color =
0; do { (parent)->entry.rbe_color = 0; (gparent)->entry
.rbe_color = 1; } while (0); elm = gparent; continue; } if ((
parent)->entry.rbe_right == elm) { do { (tmp) = (parent)->
entry.rbe_right; if (((parent)->entry.rbe_right = (tmp)->
entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (parent)->entry.rbe_parent)) { if ((parent) == ((parent
)->entry.rbe_parent)->entry.rbe_left) ((parent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((parent)->entry
.rbe_parent)->entry.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = parent; parent = elm; elm
= tmp; } do { (parent)->entry.rbe_color = 0; (gparent)->
entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
entry.rbe_left; if (((gparent)->entry.rbe_left = (tmp)->
entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (gparent)->entry.rbe_parent)) { if ((gparent) == ((gparent
)->entry.rbe_parent)->entry.rbe_left) ((gparent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((gparent)->
entry.rbe_parent)->entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry.rbe_right = (gparent); (gparent
)->entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->
entry.rbe_parent)) do {} while (0); } while (0); } else { tmp
= (gparent)->entry.rbe_left; if (tmp && (tmp)->
entry.rbe_color == 1) { (tmp)->entry.rbe_color = 0; do { (
parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); elm = gparent; continue; } if ((parent)->
entry.rbe_left == elm) { do { (tmp) = (parent)->entry.rbe_left
; if (((parent)->entry.rbe_left = (tmp)->entry.rbe_right
)) { ((tmp)->entry.rbe_right)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = parent; parent = elm; elm
= tmp; } do { (parent)->entry.rbe_color = 0; (gparent)->
entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
entry.rbe_right; if (((gparent)->entry.rbe_right = (tmp)->
entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (gparent)->entry.rbe_parent)) { if ((gparent) == ((gparent
)->entry.rbe_parent)->entry.rbe_left) ((gparent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((gparent)->
entry.rbe_parent)->entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry.rbe_left = (gparent); (gparent
)->entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->
entry.rbe_parent)) do {} while (0); } while (0); } } (head->
rbh_root)->entry.rbe_color = 0; } __attribute__((__unused__
)) static void ltree_RB_REMOVE_COLOR(struct ltree *head, struct
links_entry *parent, struct links_entry *elm) { struct links_entry
*tmp; while ((elm == ((void *)0) || (elm)->entry.rbe_color
== 0) && elm != (head)->rbh_root) { if ((parent)->
entry.rbe_left == elm) { tmp = (parent)->entry.rbe_right; if
((tmp)->entry.rbe_color == 1) { do { (tmp)->entry.rbe_color
= 0; (parent)->entry.rbe_color = 1; } while (0); do { (tmp
) = (parent)->entry.rbe_right; if (((parent)->entry.rbe_right
= (tmp)->entry.rbe_left)) { ((tmp)->entry.rbe_left)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_left = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_right; } if (((tmp)->entry.rbe_left
== ((void *)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void *)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_right == ((void
*)0) || ((tmp)->entry.rbe_right)->entry.rbe_color == 0
) { struct links_entry *oleft; if ((oleft = (tmp)->entry.rbe_left
)) (oleft)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oleft) = (tmp)->entry.rbe_left; if (((tmp)->
entry.rbe_left = (oleft)->entry.rbe_right)) { ((oleft)->
entry.rbe_right)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oleft)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oleft); else
((tmp)->entry.rbe_parent)->entry.rbe_right = (oleft); }
else (head)->rbh_root = (oleft); (oleft)->entry.rbe_right
= (tmp); (tmp)->entry.rbe_parent = (oleft); do {} while (
0); if (((oleft)->entry.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->entry.rbe_right; } (tmp)->entry.rbe_color
= (parent)->entry.rbe_color; (parent)->entry.rbe_color
= 0; if ((tmp)->entry.rbe_right) ((tmp)->entry.rbe_right
)->entry.rbe_color = 0; do { (tmp) = (parent)->entry.rbe_right
; if (((parent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); elm = (head)->rbh_root; break
; } } else { tmp = (parent)->entry.rbe_left; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_left; if (((parent)->entry.rbe_left = (tmp
)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_left; } if (((tmp)->entry.rbe_left
== ((void *)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void *)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_left == ((void *
)0) || ((tmp)->entry.rbe_left)->entry.rbe_color == 0) {
struct links_entry *oright; if ((oright = (tmp)->entry.rbe_right
)) (oright)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oright) = (tmp)->entry.rbe_right; if (((tmp)->
entry.rbe_right = (oright)->entry.rbe_left)) { ((oright)->
entry.rbe_left)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oright)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oright);
else ((tmp)->entry.rbe_parent)->entry.rbe_right = (oright
); } else (head)->rbh_root = (oright); (oright)->entry.
rbe_left = (tmp); (tmp)->entry.rbe_parent = (oright); do {
} while (0); if (((oright)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->entry.rbe_left; } (tmp)
->entry.rbe_color = (parent)->entry.rbe_color; (parent)
->entry.rbe_color = 0; if ((tmp)->entry.rbe_left) ((tmp
)->entry.rbe_left)->entry.rbe_color = 0; do { (tmp) = (
parent)->entry.rbe_left; if (((parent)->entry.rbe_left =
(tmp)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
elm = (head)->rbh_root; break; } } } if (elm) (elm)->entry
.rbe_color = 0; } __attribute__((__unused__)) static struct links_entry
* ltree_RB_REMOVE(struct ltree *head, struct links_entry *elm
) { struct links_entry *child, *parent, *old = elm; int color
; if ((elm)->entry.rbe_left == ((void *)0)) child = (elm)->
entry.rbe_right; else if ((elm)->entry.rbe_right == ((void
*)0)) child = (elm)->entry.rbe_left; else { struct links_entry
*left; elm = (elm)->entry.rbe_right; while ((left = (elm)
->entry.rbe_left)) elm = left; child = (elm)->entry.rbe_right
; parent = (elm)->entry.rbe_parent; color = (elm)->entry
.rbe_color; if (child) (child)->entry.rbe_parent = parent;
if (parent) { if ((parent)->entry.rbe_left == elm) (parent
)->entry.rbe_left = child; else (parent)->entry.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; if ((elm)->entry.rbe_parent == old) parent = elm; (elm)->
entry = (old)->entry; if ((old)->entry.rbe_parent) { if
(((old)->entry.rbe_parent)->entry.rbe_left == old) ((old
)->entry.rbe_parent)->entry.rbe_left = elm; else ((old)
->entry.rbe_parent)->entry.rbe_right = elm; do {} while
(0); } else (head)->rbh_root = elm; ((old)->entry.rbe_left
)->entry.rbe_parent = elm; if ((old)->entry.rbe_right) (
(old)->entry.rbe_right)->entry.rbe_parent = elm; if (parent
) { left = parent; do { do {} while (0); } while ((left = (left
)->entry.rbe_parent)); } goto color; } parent = (elm)->
entry.rbe_parent; color = (elm)->entry.rbe_color; if (child
) (child)->entry.rbe_parent = parent; if (parent) { if ((parent
)->entry.rbe_left == elm) (parent)->entry.rbe_left = child
; else (parent)->entry.rbe_right = child; do {} while (0);
} else (head)->rbh_root = child; color: if (color == 0) ltree_RB_REMOVE_COLOR
(head, parent, child); return (old); } __attribute__((__unused__
)) static struct links_entry * ltree_RB_INSERT(struct ltree *
head, struct links_entry *elm) { struct links_entry *tmp; struct
links_entry *parent = ((void *)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (links_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->entry.rbe_left
; else if (comp > 0) tmp = (tmp)->entry.rbe_right; else
return (tmp); } do { (elm)->entry.rbe_parent = parent; (elm
)->entry.rbe_left = (elm)->entry.rbe_right = ((void *)0
); (elm)->entry.rbe_color = 1; } while (0); if (parent != (
(void *)0)) { if (comp < 0) (parent)->entry.rbe_left = elm
; else (parent)->entry.rbe_right = elm; do {} while (0); }
else (head)->rbh_root = elm; ltree_RB_INSERT_COLOR(head, elm
); return (((void *)0)); } __attribute__((__unused__)) static
struct links_entry * ltree_RB_FIND(struct ltree *head, struct
links_entry *elm) { struct links_entry *tmp = (head)->rbh_root
; int comp; while (tmp) { comp = links_cmp(elm, tmp); if (comp
< 0) tmp = (tmp)->entry.rbe_left; else if (comp > 0
) tmp = (tmp)->entry.rbe_right; else return (tmp); } return
(((void *)0)); } __attribute__((__unused__)) static struct links_entry
* ltree_RB_NFIND(struct ltree *head, struct links_entry *elm
) { struct links_entry *tmp = (head)->rbh_root; struct links_entry
*res = ((void *)0); int comp; while (tmp) { comp = links_cmp
(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->entry
.rbe_left; } else if (comp > 0) tmp = (tmp)->entry.rbe_right
; else return (tmp); } return (res); } __attribute__((__unused__
)) static struct links_entry * ltree_RB_NEXT(struct links_entry
*elm) { if ((elm)->entry.rbe_right) { elm = (elm)->entry
.rbe_right; while ((elm)->entry.rbe_left) elm = (elm)->
entry.rbe_left; } else { if ((elm)->entry.rbe_parent &&
(elm == ((elm)->entry.rbe_parent)->entry.rbe_left)) elm
= (elm)->entry.rbe_parent; else { while ((elm)->entry.
rbe_parent && (elm == ((elm)->entry.rbe_parent)->
entry.rbe_right)) elm = (elm)->entry.rbe_parent; elm = (elm
)->entry.rbe_parent; } } return (elm); } __attribute__((__unused__
)) static struct links_entry * ltree_RB_PREV(struct links_entry
*elm) { if ((elm)->entry.rbe_left) { elm = (elm)->entry
.rbe_left; while ((elm)->entry.rbe_right) elm = (elm)->
entry.rbe_right; } else { if ((elm)->entry.rbe_parent &&
(elm == ((elm)->entry.rbe_parent)->entry.rbe_right)) elm
= (elm)->entry.rbe_parent; else { while ((elm)->entry.
rbe_parent && (elm == ((elm)->entry.rbe_parent)->
entry.rbe_left)) elm = (elm)->entry.rbe_parent; elm = (elm
)->entry.rbe_parent; } } return (elm); } __attribute__((__unused__
)) static struct links_entry * ltree_RB_MINMAX(struct ltree *
head, int val) { struct links_entry *tmp = (head)->rbh_root
; struct links_entry *parent = ((void *)0); while (tmp) { parent
= tmp; if (val < 0) tmp = (tmp)->entry.rbe_left; else tmp
= (tmp)->entry.rbe_right; } return (parent); }
;
240
241
242int
243linkchk(FTSENT *p)
244{
245 static struct links_entry *free_list = NULL((void *)0);
246 static int stop_allocating = 0;
247 struct links_entry ltmp, *le;
248 struct stat *st;
249
250 st = p->fts_statp;
251
252 ltmp.ino = st->st_ino;
253 ltmp.dev = st->st_dev;
254
255 le = RB_FIND(ltree, &links, &ltmp)ltree_RB_FIND(&links, &ltmp);
256 if (le
18.1
'le' is equal to NULL
!= NULL((void *)0)) {
19
Taking false branch
257 /*
258 * Save memory by releasing an entry when we've seen
259 * all of it's links.
260 */
261 if (--le->links <= 0) {
262 RB_REMOVE(ltree, &links, le)ltree_RB_REMOVE(&links, le);
263 /* Recycle this node through the free list */
264 if (stop_allocating) {
265 free(le);
266 } else {
267 le->fnext = free_list;
268 free_list = le;
269 }
270 }
271 return (1);
272 }
273
274 if (stop_allocating
19.1
'stop_allocating' is 0
)
20
Taking false branch
275 return (0);
276
277 /* Add this entry to the links cache. */
278 if (free_list
20.1
'free_list' is equal to NULL
!= NULL((void *)0)) {
21
Taking false branch
279 /* Pull a node from the free list if we can. */
280 le = free_list;
281 free_list = le->fnext;
282 } else
283 /* Malloc one if we have to. */
284 le = malloc(sizeof(struct links_entry));
22
Memory is allocated
285
286 if (le == NULL((void *)0)) {
23
Assuming 'le' is not equal to NULL
24
Taking false branch
287 stop_allocating = 1;
288 warnx("No more memory for tracking hard links");
289 return (0);
290 }
291
292 le->dev = st->st_dev;
293 le->ino = st->st_ino;
294 le->links = st->st_nlink - 1;
295 le->fnext = NULL((void *)0);
296
297 RB_INSERT(ltree, &links, le)ltree_RB_INSERT(&links, le);
298
299 return (0);
25
Potential leak of memory pointed to by 'le'
300}
301
302void
303prtout(int64_t size, char *path, int hflag)
304{
305 if (!hflag)
306 (void)printf("%lld\t%s\n", size, path);
307 else {
308 char buf[FMT_SCALED_STRSIZE7];
309
310 if (fmt_scaled(size * 512, buf) == 0)
311 (void)printf("%s\t%s\n", buf, path);
312 else
313 (void)printf("%lld\t%s\n", size, path);
314 }
315}
316
317void
318usage(void)
319{
320
321 (void)fprintf(stderr(&__sF[2]),
322 "usage: du [-achkrsx] [-H | -L | -P] [-d depth] [file ...]\n");
323 exit(1);
324}