OpenCoverage

shred.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/shred.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* shred.c - overwrite files and devices to make it harder to recover data-
2-
3 Copyright (C) 1999-2018 Free Software Foundation, Inc.-
4 Copyright (C) 1997, 1998, 1999 Colin Plumb.-
5-
6 This program is free software: you can redistribute it and/or modify-
7 it under the terms of the GNU General Public License as published by-
8 the Free Software Foundation, either version 3 of the License, or-
9 (at your option) any later version.-
10-
11 This program is distributed in the hope that it will be useful,-
12 but WITHOUT ANY WARRANTY; without even the implied warranty of-
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
14 GNU General Public License for more details.-
15-
16 You should have received a copy of the GNU General Public License-
17 along with this program. If not, see <https://www.gnu.org/licenses/>.-
18-
19 Written by Colin Plumb. */-
20-
21/*-
22 * Do a more secure overwrite of given files or devices, to make it harder-
23 * for even very expensive hardware probing to recover the data.-
24 *-
25 * Although this process is also known as "wiping", I prefer the longer-
26 * name both because I think it is more evocative of what is happening and-
27 * because a longer name conveys a more appropriate sense of deliberateness.-
28 *-
29 * For the theory behind this, see "Secure Deletion of Data from Magnetic-
30 * and Solid-State Memory", on line at-
31 * https://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html-
32 *-
33 * Just for the record, reversing one or two passes of disk overwrite-
34 * is not terribly difficult with hardware help. Hook up a good-quality-
35 * digitizing oscilloscope to the output of the head preamplifier and copy-
36 * the high-res digitized data to a computer for some off-line analysis.-
37 * Read the "current" data and average all the pulses together to get an-
38 * "average" pulse on the disk. Subtract this average pulse from all of-
39 * the actual pulses and you can clearly see the "echo" of the previous-
40 * data on the disk.-
41 *-
42 * Real hard drives have to balance the cost of the media, the head,-
43 * and the read circuitry. They use better-quality media than absolutely-
44 * necessary to limit the cost of the read circuitry. By throwing that-
45 * assumption out, and the assumption that you want the data processed-
46 * as fast as the hard drive can spin, you can do better.-
47 *-
48 * If asked to wipe a file, this also unlinks it, renaming it in a-
49 * clever way to try to leave no trace of the original filename.-
50 *-
51 * This was inspired by a desire to improve on some code titled:-
52 * Wipe V1.0-- Overwrite and delete files. S. 2/3/96-
53 * but I've rewritten everything here so completely that no trace of-
54 * the original remains.-
55 *-
56 * Thanks to:-
57 * Bob Jenkins, for his good RNG work and patience with the FSF copyright-
58 * paperwork.-
59 * Jim Meyering, for his work merging this into the GNU fileutils while-
60 * still letting me feel a sense of ownership and pride. Getting me to-
61 * tolerate the GNU brace style was quite a feat of diplomacy.-
62 * Paul Eggert, for lots of useful discussion and code. I disagree with-
63 * an awful lot of his suggestions, but they're disagreements worth having.-
64 *-
65 * Things to think about:-
66 * - Security: Is there any risk to the race-
67 * between overwriting and unlinking a file? Will it do anything-
68 * drastically bad if told to attack a named pipe or socket?-
69 */-
70-
71/* The official name of this program (e.g., no 'g' prefix). */-
72#define PROGRAM_NAME "shred"-
73-
74#define AUTHORS proper_name ("Colin Plumb")-
75-
76#include <config.h>-
77-
78#include <getopt.h>-
79#include <stdio.h>-
80#include <assert.h>-
81#include <setjmp.h>-
82#include <sys/types.h>-
83#if defined __linux__ && HAVE_SYS_MTIO_H-
84# include <sys/mtio.h>-
85#endif-
86-
87#include "system.h"-
88#include "argmatch.h"-
89#include "xdectoint.h"-
90#include "die.h"-
91#include "error.h"-
92#include "fcntl--.h"-
93#include "human.h"-
94#include "randint.h"-
95#include "randread.h"-
96#include "renameat2.h"-
97#include "stat-size.h"-
98-
99/* Default number of times to overwrite. */-
100enum { DEFAULT_PASSES = 3 };-
101-
102/* How many seconds to wait before checking whether to output another-
103 verbose output line. */-
104enum { VERBOSE_UPDATE = 5 };-
105-
106/* Sector size and corresponding mask, for recovering after write failures.-
107 The size must be a power of 2. */-
108enum { SECTOR_SIZE = 512 };-
109enum { SECTOR_MASK = SECTOR_SIZE - 1 };-
110verify (0 < SECTOR_SIZE && (SECTOR_SIZE & SECTOR_MASK) == 0);-
111-
112enum remove_method-
113{-
114 remove_none = 0, /* the default: only wipe data. */-
115 remove_unlink, /* don't obfuscate name, just unlink. */-
116 remove_wipe, /* obfuscate name before unlink. */-
117 remove_wipesync /* obfuscate name, syncing each byte, before unlink. */-
118};-
119-
120static char const *const remove_args[] =-
121{-
122 "unlink", "wipe", "wipesync", NULL-
123};-
124-
125static enum remove_method const remove_methods[] =-
126{-
127 remove_unlink, remove_wipe, remove_wipesync-
128};-
129-
130struct Options-
131{-
132 bool force; /* -f flag: chmod files if necessary */-
133 size_t n_iterations; /* -n flag: Number of iterations */-
134 off_t size; /* -s flag: size of file */-
135 enum remove_method remove_file; /* -u flag: remove file after shredding */-
136 bool verbose; /* -v flag: Print progress */-
137 bool exact; /* -x flag: Do not round up file size */-
138 bool zero_fill; /* -z flag: Add a final zero pass */-
139};-
140-
141/* For long options that have no equivalent short option, use a-
142 non-character as a pseudo short option, starting with CHAR_MAX + 1. */-
143enum-
144{-
145 RANDOM_SOURCE_OPTION = CHAR_MAX + 1-
146};-
147-
148static struct option const long_opts[] =-
149{-
150 {"exact", no_argument, NULL, 'x'},-
151 {"force", no_argument, NULL, 'f'},-
152 {"iterations", required_argument, NULL, 'n'},-
153 {"size", required_argument, NULL, 's'},-
154 {"random-source", required_argument, NULL, RANDOM_SOURCE_OPTION},-
155 {"remove", optional_argument, NULL, 'u'},-
156 {"verbose", no_argument, NULL, 'v'},-
157 {"zero", no_argument, NULL, 'z'},-
158 {GETOPT_HELP_OPTION_DECL},-
159 {GETOPT_VERSION_OPTION_DECL},-
160 {NULL, 0, NULL, 0}-
161};-
162-
163void-
164usage (int status)-
165{-
166 if (status != EXIT_SUCCESS)
status != 0Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 14 times by 1 test
Evaluated by:
  • shred
4-14
167 emit_try_help ();
executed 4 times by 1 test: end of block
Executed by:
  • shred
4
168 else-
169 {-
170 printf (_("Usage: %s [OPTION]... FILE...\n"), program_name);-
171 fputs (_("\-
172Overwrite the specified FILE(s) repeatedly, in order to make it harder\n\-
173for even very expensive hardware probing to recover the data.\n\-
174"), stdout);-
175 fputs (_("\-
176\n\-
177If FILE is -, shred standard output.\n\-
178"), stdout);-
179-
180 emit_mandatory_arg_note ();-
181-
182 printf (_("\-
183 -f, --force change permissions to allow writing if necessary\n\-
184 -n, --iterations=N overwrite N times instead of the default (%d)\n\-
185 --random-source=FILE get random bytes from FILE\n\-
186 -s, --size=N shred this many bytes (suffixes like K, M, G accepted)\n\-
187"), DEFAULT_PASSES);-
188 fputs (_("\-
189 -u deallocate and remove file after overwriting\n\-
190 --remove[=HOW] like -u but give control on HOW to delete; See below\n\-
191 -v, --verbose show progress\n\-
192 -x, --exact do not round file sizes up to the next full block;\n\-
193 this is the default for non-regular files\n\-
194 -z, --zero add a final overwrite with zeros to hide shredding\n\-
195"), stdout);-
196 fputs (HELP_OPTION_DESCRIPTION, stdout);-
197 fputs (VERSION_OPTION_DESCRIPTION, stdout);-
198 fputs (_("\-
199\n\-
200Delete FILE(s) if --remove (-u) is specified. The default is not to remove\n\-
201the files because it is common to operate on device files like /dev/hda,\n\-
202and those files usually should not be removed.\n\-
203The optional HOW parameter indicates how to remove a directory entry:\n\-
204'unlink' => use a standard unlink call.\n\-
205'wipe' => also first obfuscate bytes in the name.\n\-
206'wipesync' => also sync each obfuscated byte to disk.\n\-
207The default mode is 'wipesync', but note it can be expensive.\n\-
208\n\-
209"), stdout);-
210 fputs (_("\-
211CAUTION: Note that shred relies on a very important assumption:\n\-
212that the file system overwrites data in place. This is the traditional\n\-
213way to do things, but many modern file system designs do not satisfy this\n\-
214assumption. The following are examples of file systems on which shred is\n\-
215not effective, or is not guaranteed to be effective in all file system modes:\n\-
216\n\-
217"), stdout);-
218 fputs (_("\-
219* log-structured or journaled file systems, such as those supplied with\n\-
220AIX and Solaris (and JFS, ReiserFS, XFS, Ext3, etc.)\n\-
221\n\-
222* file systems that write redundant data and carry on even if some writes\n\-
223fail, such as RAID-based file systems\n\-
224\n\-
225* file systems that make snapshots, such as Network Appliance's NFS server\n\-
226\n\-
227"), stdout);-
228 fputs (_("\-
229* file systems that cache in temporary locations, such as NFS\n\-
230version 3 clients\n\-
231\n\-
232* compressed file systems\n\-
233\n\-
234"), stdout);-
235 fputs (_("\-
236In the case of ext3 file systems, the above disclaimer applies\n\-
237(and shred is thus of limited effectiveness) only in data=journal mode,\n\-
238which journals file data in addition to just metadata. In both the\n\-
239data=ordered (default) and data=writeback modes, shred works as usual.\n\-
240Ext3 journaling modes can be changed by adding the data=something option\n\-
241to the mount options for a particular file system in the /etc/fstab file,\n\-
242as documented in the mount man page (man mount).\n\-
243\n\-
244"), stdout);-
245 fputs (_("\-
246In addition, file system backups and remote mirrors may contain copies\n\-
247of the file that cannot be removed, and that will allow a shredded file\n\-
248to be recovered later.\n\-
249"), stdout);-
250 emit_ancillary_info (PROGRAM_NAME);-
251 }
executed 14 times by 1 test: end of block
Executed by:
  • shred
14
252 exit (status);
executed 18 times by 1 test: exit (status);
Executed by:
  • shred
18
253}-
254-
255/*-
256 * Determine if pattern type is periodic or not.-
257 */-
258static bool-
259periodic_pattern (int type)-
260{-
261 if (type <= 0)
type <= 0Description
TRUEevaluated 96 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 41 times by 1 test
Evaluated by:
  • shred
41-96
262 return false;
executed 96 times by 1 test: return 0 ;
Executed by:
  • shred
96
263-
264 unsigned char r[3];-
265 unsigned int bits = type & 0xfff;-
266-
267 bits |= bits << 12;-
268 r[0] = (bits >> 4) & 255;-
269 r[1] = (bits >> 8) & 255;-
270 r[2] = bits & 255;-
271-
272 return (r[0] != r[1]) || (r[0] != r[2]);
executed 41 times by 1 test: return (r[0] != r[1]) || (r[0] != r[2]);
Executed by:
  • shred
41
273}-
274-
275/*-
276 * Fill a buffer with a fixed pattern.-
277 *-
278 * The buffer must be at least 3 bytes long, even if-
279 * size is less. Larger sizes are filled exactly.-
280 */-
281static void-
282fillpattern (int type, unsigned char *r, size_t size)-
283{-
284 size_t i;-
285 unsigned int bits = type & 0xfff;-
286-
287 bits |= bits << 12;-
288 r[0] = (bits >> 4) & 255;-
289 r[1] = (bits >> 8) & 255;-
290 r[2] = bits & 255;-
291 for (i = 3; i <= size / 2; i *= 2)
i <= size / 2Description
TRUEevaluated 210 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 58 times by 1 test
Evaluated by:
  • shred
58-210
292 memcpy (r + i, r, i);
executed 210 times by 1 test: memcpy (r + i, r, i);
Executed by:
  • shred
210
293 if (i < size)
i < sizeDescription
TRUEevaluated 27 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 31 times by 1 test
Evaluated by:
  • shred
27-31
294 memcpy (r + i, r, size - i);
executed 27 times by 1 test: memcpy (r + i, r, size - i);
Executed by:
  • shred
27
295-
296 /* Invert the first bit of every sector. */-
297 if (type & 0x1000)
type & 0x1000Description
TRUEnever evaluated
FALSEevaluated 58 times by 1 test
Evaluated by:
  • shred
0-58
298 for (i = 0; i < size; i += SECTOR_SIZE)
i < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
299 r[i] ^= 0x80;
never executed: r[i] ^= 0x80;
0
300}
executed 58 times by 1 test: end of block
Executed by:
  • shred
58
301-
302/*-
303 * Generate a 6-character (+ nul) pass name string-
304 * FIXME: allow translation of "random".-
305 */-
306#define PASS_NAME_SIZE 7-
307static void-
308passname (unsigned char const *data, char name[PASS_NAME_SIZE])-
309{-
310 if (data)
dataDescription
TRUEevaluated 58 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 79 times by 1 test
Evaluated by:
  • shred
58-79
311 sprintf (name, "%02x%02x%02x", data[0], data[1], data[2]);
executed 58 times by 1 test: sprintf (name, "%02x%02x%02x", data[0], data[1], data[2]);
Executed by:
  • shred
58
312 else-
313 memcpy (name, "random", PASS_NAME_SIZE);
executed 79 times by 1 test: memcpy (name, "random", 7);
Executed by:
  • shred
79
314}-
315-
316/* Return true when it's ok to ignore an fsync or fdatasync-
317 failure that set errno to ERRNO_VAL. */-
318static bool-
319ignorable_sync_errno (int errno_val)-
320{-
321 return (errno_val == EINVAL
never executed: return (errno_val == 22 || errno_val == 9 || errno_val == 21 );
0
322 || errno_val == EBADF
never executed: return (errno_val == 22 || errno_val == 9 || errno_val == 21 );
0
323 /* HP-UX does this */
never executed: return (errno_val == 22 || errno_val == 9 || errno_val == 21 );
0
324 || errno_val == EISDIR);
never executed: return (errno_val == 22 || errno_val == 9 || errno_val == 21 );
0
325}-
326-
327/* Request that all data for FD be transferred to the corresponding-
328 storage device. QNAME is the file name (quoted for colons).-
329 Report any errors found. Return 0 on success, -1-
330 (setting errno) on failure. It is not an error if fdatasync and/or-
331 fsync is not supported for this file, or if the file is not a-
332 writable file descriptor. */-
333static int-
334dosync (int fd, char const *qname)-
335{-
336 int err;-
337-
338#if HAVE_FDATASYNC-
339 if (fdatasync (fd) == 0)
fdatasync (fd) == 0Description
TRUEevaluated 182 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-182
340 return 0;
executed 182 times by 1 test: return 0;
Executed by:
  • shred
182
341 err = errno;-
342 if ( ! ignorable_sync_errno (err))
! ignorable_sync_errno (err)Description
TRUEnever evaluated
FALSEnever evaluated
0
343 {-
344 error (0, err, _("%s: fdatasync failed"), qname);-
345 errno = err;-
346 return -1;
never executed: return -1;
0
347 }-
348#endif-
349-
350 if (fsync (fd) == 0)
fsync (fd) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
351 return 0;
never executed: return 0;
0
352 err = errno;-
353 if ( ! ignorable_sync_errno (err))
! ignorable_sync_errno (err)Description
TRUEnever evaluated
FALSEnever evaluated
0
354 {-
355 error (0, err, _("%s: fsync failed"), qname);-
356 errno = err;-
357 return -1;
never executed: return -1;
0
358 }-
359-
360 sync ();-
361 return 0;
never executed: return 0;
0
362}-
363-
364/* Turn on or off direct I/O mode for file descriptor FD, if possible.-
365 Try to turn it on if ENABLE is true. Otherwise, try to turn it off. */-
366static void-
367direct_mode (int fd, bool enable)-
368{-
369 if (O_DIRECT)-
370 {-
371 int fd_flags = fcntl (fd, F_GETFL);-
372 if (0 < fd_flags)
0 < fd_flagsDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-4
373 {-
374 int new_flags = (enable
enableDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
2
375 ? (fd_flags | O_DIRECT)-
376 : (fd_flags & ~O_DIRECT));-
377 if (new_flags != fd_flags)
new_flags != fd_flagsDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-4
378 fcntl (fd, F_SETFL, new_flags);
executed 4 times by 1 test: rpl_fcntl (fd, 4 , new_flags);
Executed by:
  • shred
4
379 }
executed 4 times by 1 test: end of block
Executed by:
  • shred
4
380 }
executed 4 times by 1 test: end of block
Executed by:
  • shred
4
381-
382#if HAVE_DIRECTIO && defined DIRECTIO_ON && defined DIRECTIO_OFF-
383 /* This is Solaris-specific. */-
384 directio (fd, enable ? DIRECTIO_ON : DIRECTIO_OFF);-
385#endif-
386}-
387-
388/* Rewind FD; its status is ST. */-
389static bool-
390dorewind (int fd, struct stat const *st)-
391{-
392 if (S_ISCHR (st->st_mode))
(((( st->st_mo... == (0020000))Description
TRUEnever evaluated
FALSEevaluated 137 times by 1 test
Evaluated by:
  • shred
0-137
393 {-
394#if defined __linux__ && HAVE_SYS_MTIO_H-
395 /* In the Linux kernel, lseek does not work on tape devices; it-
396 returns a randomish value instead. Try the low-level tape-
397 rewind operation first. */-
398 struct mtop op;-
399 op.mt_op = MTREW;-
400 op.mt_count = 1;-
401 if (ioctl (fd, MTIOCTOP, &op) == 0)
ioctl (fd, (((...)) , &op) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
402 return true;
never executed: return 1 ;
0
403#endif-
404 }
never executed: end of block
0
405 off_t offset = lseek (fd, 0, SEEK_SET);-
406 if (0 < offset)
0 < offsetDescription
TRUEnever evaluated
FALSEevaluated 137 times by 1 test
Evaluated by:
  • shred
0-137
407 errno = EINVAL;
never executed: (*__errno_location ()) = 22 ;
0
408 return offset == 0;
executed 137 times by 1 test: return offset == 0;
Executed by:
  • shred
137
409}-
410-
411/* By convention, negative sizes represent unknown values. */-
412-
413static bool-
414known (off_t size)-
415{-
416 return 0 <= size;
executed 366 times by 1 test: return 0 <= size;
Executed by:
  • shred
366
417}-
418-
419/*-
420 * Do pass number K of N, writing *SIZEP bytes of the given pattern TYPE-
421 * to the file descriptor FD. K and N are passed in only for verbose-
422 * progress message purposes. If N == 0, no progress messages are printed.-
423 *-
424 * If *SIZEP == -1, the size is unknown, and it will be filled in as soon-
425 * as writing fails with ENOSPC.-
426 *-
427 * Return 1 on write error, -1 on other error, 0 on success.-
428 */-
429static int-
430dopass (int fd, struct stat const *st, char const *qname, off_t *sizep,-
431 int type, struct randread_source *s,-
432 unsigned long int k, unsigned long int n)-
433{-
434 off_t size = *sizep;-
435 off_t offset; /* Current file position */-
436 time_t thresh IF_LINT ( = 0); /* Time to maybe print next status update */-
437 time_t now = 0; /* Current time */-
438 size_t lim; /* Amount of data to try writing */-
439 size_t soff; /* Offset into buffer for next write */-
440 ssize_t ssize; /* Return value from write */-
441-
442 /* Fill pattern buffer. Aligning it to a page so we can do direct I/O. */-
443 size_t page_size = getpagesize ();-
444#define PERIODIC_OUTPUT_SIZE (60 * 1024)-
445#define NONPERIODIC_OUTPUT_SIZE (64 * 1024)-
446 verify (PERIODIC_OUTPUT_SIZE % 3 == 0);-
447 size_t output_size = periodic_pattern (type)
periodic_pattern (type)Description
TRUEevaluated 12 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 125 times by 1 test
Evaluated by:
  • shred
12-125
448 ? PERIODIC_OUTPUT_SIZE : NONPERIODIC_OUTPUT_SIZE;-
449#define PAGE_ALIGN_SLOP (page_size - 1) /* So directio works */-
450#define FILLPATTERN_SIZE (((output_size + 2) / 3) * 3) /* Multiple of 3 */-
451#define PATTERNBUF_SIZE (PAGE_ALIGN_SLOP + FILLPATTERN_SIZE)-
452 void *fill_pattern_mem = xmalloc (PATTERNBUF_SIZE);-
453 unsigned char *pbuf = ptr_align (fill_pattern_mem, page_size);-
454-
455 char pass_string[PASS_NAME_SIZE]; /* Name of current pass */-
456 bool write_error = false;-
457 bool other_error = false;-
458-
459 /* Printable previous offset into the file */-
460 char previous_offset_buf[LONGEST_HUMAN_READABLE + 1];-
461 char const *previous_human_offset IF_LINT ( = 0);-
462-
463 /* As a performance tweak, avoid direct I/O for small sizes,-
464 as it's just a performance rather then security consideration,-
465 and direct I/O can often be unsupported for small non aligned sizes. */-
466 bool try_without_directio = 0 < size && size < output_size;
0 < sizeDescription
TRUEevaluated 137 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
size < output_sizeDescription
TRUEevaluated 135 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
0-137
467 if (! try_without_directio)
! try_without_directioDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 135 times by 1 test
Evaluated by:
  • shred
2-135
468 direct_mode (fd, true);
executed 2 times by 1 test: direct_mode (fd, 1 );
Executed by:
  • shred
2
469-
470 if (! dorewind (fd, st))
! dorewind (fd, st)Description
TRUEnever evaluated
FALSEevaluated 137 times by 1 test
Evaluated by:
  • shred
0-137
471 {-
472 error (0, errno, _("%s: cannot rewind"), qname);-
473 other_error = true;-
474 goto free_pattern_mem;
never executed: goto free_pattern_mem;
0
475 }-
476-
477 /* Constant fill patterns need only be set up once. */-
478 if (type >= 0)
type >= 0Description
TRUEevaluated 58 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 79 times by 1 test
Evaluated by:
  • shred
58-79
479 {-
480 lim = known (size) && size < FILLPATTERN_SIZE ? size : FILLPATTERN_SIZE;
known (size)Description
TRUEevaluated 58 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
size < (((outp...+ 2) / 3) * 3)Description
TRUEevaluated 58 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-58
481 fillpattern (type, pbuf, lim);-
482 passname (pbuf, pass_string);-
483 }
executed 58 times by 1 test: end of block
Executed by:
  • shred
58
484 else-
485 {-
486 passname (0, pass_string);-
487 }
executed 79 times by 1 test: end of block
Executed by:
  • shred
79
488-
489 /* Set position if first status update */-
490 if (n)
nDescription
TRUEevaluated 23 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 114 times by 1 test
Evaluated by:
  • shred
23-114
491 {-
492 error (0, 0, _("%s: pass %lu/%lu (%s)..."), qname, k, n, pass_string);-
493 thresh = time (NULL) + VERBOSE_UPDATE;-
494 previous_human_offset = "";-
495 }
executed 23 times by 1 test: end of block
Executed by:
  • shred
23
496-
497 offset = 0;-
498 while (true)-
499 {-
500 /* How much to write this time? */-
501 lim = output_size;-
502 if (known (size) && size - offset < output_size)
known (size)Description
TRUEevaluated 306 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
size - offset < output_sizeDescription
TRUEevaluated 274 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 32 times by 1 test
Evaluated by:
  • shred
0-306
503 {-
504 if (size < offset)
size < offsetDescription
TRUEnever evaluated
FALSEevaluated 274 times by 1 test
Evaluated by:
  • shred
0-274
505 break;
never executed: break;
0
506 lim = size - offset;-
507 if (!lim)
!limDescription
TRUEevaluated 137 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 137 times by 1 test
Evaluated by:
  • shred
137
508 break;
executed 137 times by 1 test: break;
Executed by:
  • shred
137
509 }
executed 137 times by 1 test: end of block
Executed by:
  • shred
137
510 if (type < 0)
type < 0Description
TRUEevaluated 111 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 58 times by 1 test
Evaluated by:
  • shred
58-111
511 randread (s, pbuf, lim);
executed 111 times by 1 test: randread (s, pbuf, lim);
Executed by:
  • shred
111
512 /* Loop to retry partial writes. */-
513 for (soff = 0; soff < lim; soff += ssize)
soff < limDescription
TRUEevaluated 171 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 169 times by 1 test
Evaluated by:
  • shred
169-171
514 {-
515 ssize = write (fd, pbuf + soff, lim - soff);-
516 if (0 < ssize)
0 < ssizeDescription
TRUEevaluated 169 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
2-169
517 assume (ssize <= lim - soff);
executed 169 times by 1 test: ((ssize <= lim - soff) ? (void) 0 : __builtin_unreachable ());
Executed by:
  • shred
169
518 else-
519 {-
520 if (! known (size) && (ssize == 0 || errno == ENOSPC))
! known (size)Description
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
ssize == 0Description
TRUEnever evaluated
FALSEnever evaluated
(*__errno_location ()) == 28Description
TRUEnever evaluated
FALSEnever evaluated
0-2
521 {-
522 /* We have found the end of the file. */-
523 if (soff <= OFF_T_MAX - offset)
soff <= ((off_... 1))) - offsetDescription
TRUEnever evaluated
FALSEnever evaluated
0
524 *sizep = size = offset + soff;
never executed: *sizep = size = offset + soff;
0
525 break;
never executed: break;
0
526 }-
527 else-
528 {-
529 int errnum = errno;-
530 char buf[INT_BUFSIZE_BOUND (uintmax_t)];-
531-
532 /* Retry without direct I/O since this may not be supported-
533 at all on some (file) systems, or with the current size.-
534 I.e., a specified --size that is not aligned, or when-
535 dealing with slop at the end of a file with --exact. */-
536 if (! try_without_directio && errno == EINVAL)
! try_without_directioDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
(*__errno_location ()) == 22Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-2
537 {-
538 direct_mode (fd, false);-
539 ssize = 0;-
540 try_without_directio = true;-
541 continue;
executed 2 times by 1 test: continue;
Executed by:
  • shred
2
542 }-
543 error (0, errnum, _("%s: error writing at offset %s"),-
544 qname, umaxtostr (offset + soff, buf));-
545-
546 /* 'shred' is often used on bad media, before throwing it-
547 out. Thus, it shouldn't give up on bad blocks. This-
548 code works because lim is always a multiple of-
549 SECTOR_SIZE, except at the end. This size constraint-
550 also enables direct I/O on some (file) systems. */-
551 verify (PERIODIC_OUTPUT_SIZE % SECTOR_SIZE == 0);-
552 verify (NONPERIODIC_OUTPUT_SIZE % SECTOR_SIZE == 0);-
553 if (errnum == EIO && known (size)
errnum == 5Description
TRUEnever evaluated
FALSEnever evaluated
known (size)Description
TRUEnever evaluated
FALSEnever evaluated
0
554 && (soff | SECTOR_MASK) < lim)
(soff | SECTOR_MASK) < limDescription
TRUEnever evaluated
FALSEnever evaluated
0
555 {-
556 size_t soff1 = (soff | SECTOR_MASK) + 1;-
557 if (lseek (fd, offset + soff1, SEEK_SET) != -1)
lseek (fd, off...ff1, 0 ) != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
558 {-
559 /* Arrange to skip this block. */-
560 ssize = soff1 - soff;-
561 write_error = true;-
562 continue;
never executed: continue;
0
563 }-
564 error (0, errno, _("%s: lseek failed"), qname);-
565 }
never executed: end of block
0
566 other_error = true;-
567 goto free_pattern_mem;
never executed: goto free_pattern_mem;
0
568 }-
569 }-
570 }-
571-
572 /* Okay, we have written "soff" bytes. */-
573-
574 if (OFF_T_MAX - offset < soff)
((off_t) (! (!... offset < soffDescription
TRUEnever evaluated
FALSEevaluated 169 times by 1 test
Evaluated by:
  • shred
0-169
575 {-
576 error (0, 0, _("%s: file too large"), qname);-
577 other_error = true;-
578 goto free_pattern_mem;
never executed: goto free_pattern_mem;
0
579 }-
580-
581 offset += soff;-
582-
583 bool done = offset == size;-
584-
585 /* Time to print progress? */-
586 if (n && ((done && *previous_human_offset)
nDescription
TRUEevaluated 23 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 146 times by 1 test
Evaluated by:
  • shred
doneDescription
TRUEevaluated 23 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
*previous_human_offsetDescription
TRUEnever evaluated
FALSEevaluated 23 times by 1 test
Evaluated by:
  • shred
0-146
587 || thresh <= (now = time (NULL))))
thresh <= (now...((void *)0) ))Description
TRUEnever evaluated
FALSEevaluated 23 times by 1 test
Evaluated by:
  • shred
0-23
588 {-
589 char offset_buf[LONGEST_HUMAN_READABLE + 1];-
590 char size_buf[LONGEST_HUMAN_READABLE + 1];-
591 int human_progress_opts = (human_autoscale | human_SI-
592 | human_base_1024 | human_B);-
593 char const *human_offset-
594 = human_readable (offset, offset_buf,-
595 human_floor | human_progress_opts, 1, 1);-
596-
597 if (done || !STREQ (previous_human_offset, human_offset))
never executed: __result = (((const unsigned char *) (const char *) ( previous_human_offset ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( human_offset ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
doneDescription
TRUEnever evaluated
FALSEnever evaluated
!( __extension...)))); }) == 0)Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
598 {-
599 if (! known (size))
! known (size)Description
TRUEnever evaluated
FALSEnever evaluated
0
600 error (0, 0, _("%s: pass %lu/%lu (%s)...%s"),
never executed: error (0, 0, dcgettext (((void *)0), "%s: pass %lu/%lu (%s)...%s" , 5) , qname, k, n, pass_string, human_offset);
0
601 qname, k, n, pass_string, human_offset);
never executed: error (0, 0, dcgettext (((void *)0), "%s: pass %lu/%lu (%s)...%s" , 5) , qname, k, n, pass_string, human_offset);
0
602 else-
603 {-
604 uintmax_t off = offset;-
605 int percent = (size == 0
size == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
606 ? 100-
607 : (off <= TYPE_MAXIMUM (uintmax_t) / 100
off <= ((uintm...2 + 1))) / 100Description
TRUEnever evaluated
FALSEnever evaluated
0
608 ? off * 100 / size-
609 : off / (size / 100)));-
610 char const *human_size-
611 = human_readable (size, size_buf,-
612 human_ceiling | human_progress_opts,-
613 1, 1);-
614 if (done)
doneDescription
TRUEnever evaluated
FALSEnever evaluated
0
615 human_offset = human_size;
never executed: human_offset = human_size;
0
616 error (0, 0, _("%s: pass %lu/%lu (%s)...%s/%s %d%%"),-
617 qname, k, n, pass_string, human_offset, human_size,-
618 percent);-
619 }
never executed: end of block
0
620-
621 strcpy (previous_offset_buf, human_offset);-
622 previous_human_offset = previous_offset_buf;-
623 thresh = now + VERBOSE_UPDATE;-
624-
625 /*-
626 * Force periodic syncs to keep displayed progress accurate-
627 * FIXME: Should these be present even if -v is not enabled,-
628 * to keep the buffer cache from filling with dirty pages?-
629 * It's a common problem with programs that do lots of writes,-
630 * like mkfs.-
631 */-
632 if (dosync (fd, qname) != 0)
dosync (fd, qname) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
633 {-
634 if (errno != EIO)
(*__errno_location ()) != 5Description
TRUEnever evaluated
FALSEnever evaluated
0
635 {-
636 other_error = true;-
637 goto free_pattern_mem;
never executed: goto free_pattern_mem;
0
638 }-
639 write_error = true;-
640 }
never executed: end of block
0
641 }
never executed: end of block
0
642 }
never executed: end of block
0
643 }
executed 169 times by 1 test: end of block
Executed by:
  • shred
169
644-
645 /* Force what we just wrote to hit the media. */-
646 if (dosync (fd, qname) != 0)
dosync (fd, qname) != 0Description
TRUEnever evaluated
FALSEevaluated 137 times by 1 test
Evaluated by:
  • shred
0-137
647 {-
648 if (errno != EIO)
(*__errno_location ()) != 5Description
TRUEnever evaluated
FALSEnever evaluated
0
649 {-
650 other_error = true;-
651 goto free_pattern_mem;
never executed: goto free_pattern_mem;
0
652 }-
653 write_error = true;-
654 }
never executed: end of block
0
655-
656free_pattern_mem:
code before this statement executed 137 times by 1 test: free_pattern_mem:
Executed by:
  • shred
137
657 free (fill_pattern_mem);-
658-
659 return other_error ? -1 : write_error;
executed 137 times by 1 test: return other_error ? -1 : write_error;
Executed by:
  • shred
137
660}-
661-
662/*-
663 * The passes start and end with a random pass, and the passes in between-
664 * are done in random order. The idea is to deprive someone trying to-
665 * reverse the process of knowledge of the overwrite patterns, so they-
666 * have the additional step of figuring out what was done to the disk-
667 * before they can try to reverse or cancel it.-
668 *-
669 * First, all possible 1-bit patterns. There are two of them.-
670 * Then, all possible 2-bit patterns. There are four, but the two-
671 * which are also 1-bit patterns can be omitted.-
672 * Then, all possible 3-bit patterns. Likewise, 8-2 = 6.-
673 * Then, all possible 4-bit patterns. 16-4 = 12.-
674 *-
675 * The basic passes are:-
676 * 1-bit: 0x000, 0xFFF-
677 * 2-bit: 0x555, 0xAAA-
678 * 3-bit: 0x249, 0x492, 0x924, 0x6DB, 0xB6D, 0xDB6 (+ 1-bit)-
679 * 100100100100 110110110110-
680 * 9 2 4 D B 6-
681 * 4-bit: 0x111, 0x222, 0x333, 0x444, 0x666, 0x777,-
682 * 0x888, 0x999, 0xBBB, 0xCCC, 0xDDD, 0xEEE (+ 1-bit, 2-bit)-
683 * Adding three random passes at the beginning, middle and end-
684 * produces the default 25-pass structure.-
685 *-
686 * The next extension would be to 5-bit and 6-bit patterns.-
687 * There are 30 uncovered 5-bit patterns and 64-8-2 = 46 uncovered-
688 * 6-bit patterns, so they would increase the time required-
689 * significantly. 4-bit patterns are enough for most purposes.-
690 *-
691 * The main gotcha is that this would require a trickier encoding,-
692 * since lcm(2,3,4) = 12 bits is easy to fit into an int, but-
693 * lcm(2,3,4,5) = 60 bits is not.-
694 *-
695 * One extension that is included is to complement the first bit in each-
696 * 512-byte block, to alter the phase of the encoded data in the more-
697 * complex encodings. This doesn't apply to MFM, so the 1-bit patterns-
698 * are considered part of the 3-bit ones and the 2-bit patterns are-
699 * considered part of the 4-bit patterns.-
700 *-
701 *-
702 * How does the generalization to variable numbers of passes work?-
703 *-
704 * Here's how...-
705 * Have an ordered list of groups of passes. Each group is a set.-
706 * Take as many groups as will fit, plus a random subset of the-
707 * last partial group, and place them into the passes list.-
708 * Then shuffle the passes list into random order and use that.-
709 *-
710 * One extra detail: if we can't include a large enough fraction of the-
711 * last group to be interesting, then just substitute random passes.-
712 *-
713 * If you want more passes than the entire list of groups can-
714 * provide, just start repeating from the beginning of the list.-
715 */-
716static int const-
717 patterns[] =-
718{-
719 -2, /* 2 random passes */-
720 2, 0x000, 0xFFF, /* 1-bit */-
721 2, 0x555, 0xAAA, /* 2-bit */-
722 -1, /* 1 random pass */-
723 6, 0x249, 0x492, 0x6DB, 0x924, 0xB6D, 0xDB6, /* 3-bit */-
724 12, 0x111, 0x222, 0x333, 0x444, 0x666, 0x777,-
725 0x888, 0x999, 0xBBB, 0xCCC, 0xDDD, 0xEEE, /* 4-bit */-
726 -1, /* 1 random pass */-
727 /* The following patterns have the first bit per block flipped */-
728 8, 0x1000, 0x1249, 0x1492, 0x16DB, 0x1924, 0x1B6D, 0x1DB6, 0x1FFF,-
729 14, 0x1111, 0x1222, 0x1333, 0x1444, 0x1555, 0x1666, 0x1777,-
730 0x1888, 0x1999, 0x1AAA, 0x1BBB, 0x1CCC, 0x1DDD, 0x1EEE,-
731 -1, /* 1 random pass */-
732 0 /* End */-
733};-
734-
735/*-
736 * Generate a random wiping pass pattern with num passes.-
737 * This is a two-stage process. First, the passes to include-
738 * are chosen, and then they are shuffled into the desired-
739 * order.-
740 */-
741static void-
742genpattern (int *dest, size_t num, struct randint_source *s)-
743{-
744 size_t randpasses;-
745 int const *p;-
746 int *d;-
747 size_t n;-
748 size_t accum, top, swap;-
749 int k;-
750-
751 if (!num)
!numDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 21 times by 1 test
Evaluated by:
  • shred
4-21
752 return;
executed 4 times by 1 test: return;
Executed by:
  • shred
4
753-
754 /* Stage 1: choose the passes to use */-
755 p = patterns;-
756 randpasses = 0;-
757 d = dest; /* Destination for generated pass list */-
758 n = num; /* Passes remaining to fill */-
759-
760 while (true)-
761 {-
762 k = *p++; /* Block descriptor word */-
763 if (!k)
!kDescription
TRUEnever evaluated
FALSEevaluated 49 times by 1 test
Evaluated by:
  • shred
0-49
764 { /* Loop back to the beginning */-
765 p = patterns;-
766 }
never executed: end of block
0
767 else if (k < 0)
k < 0Description
TRUEevaluated 22 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 27 times by 1 test
Evaluated by:
  • shred
22-27
768 { /* -k random passes */-
769 k = -k;-
770 if ((size_t) k >= n)
(size_t) k >= nDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 20 times by 1 test
Evaluated by:
  • shred
2-20
771 {-
772 randpasses += n;-
773 break;
executed 2 times by 1 test: break;
Executed by:
  • shred
2
774 }-
775 randpasses += k;-
776 n -= k;-
777 }
executed 20 times by 1 test: end of block
Executed by:
  • shred
20
778 else if ((size_t) k <= n)
(size_t) k <= nDescription
TRUEevaluated 8 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 19 times by 1 test
Evaluated by:
  • shred
8-19
779 { /* Full block of patterns */-
780 memcpy (d, p, k * sizeof (int));-
781 p += k;-
782 d += k;-
783 n -= k;-
784 }
executed 8 times by 1 test: end of block
Executed by:
  • shred
8
785 else if (n < 2 || 3 * n < (size_t) k)
n < 2Description
TRUEevaluated 18 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
3 * n < (size_t) kDescription
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
0-18
786 { /* Finish with random */-
787 randpasses += n;-
788 break;
executed 18 times by 1 test: break;
Executed by:
  • shred
18
789 }-
790 else-
791 { /* Pad out with n of the k available */-
792 do-
793 {-
794 if (n == (size_t) k || randint_choose (s, k) < n)
n == (size_t) kDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • shred
FALSEevaluated 11 times by 1 test
Evaluated by:
  • shred
randint_choose (s, k) < nDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 5 times by 1 test
Evaluated by:
  • shred
1-11
795 {-
796 *d++ = *p;-
797 n--;-
798 }
executed 7 times by 1 test: end of block
Executed by:
  • shred
7
799 p++;-
800 k--;-
801 }
executed 12 times by 1 test: end of block
Executed by:
  • shred
12
802 while (n);
nDescription
TRUEevaluated 11 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
1-11
803 break;
executed 1 time by 1 test: break;
Executed by:
  • shred
1
804 }-
805 }-
806 top = num - randpasses; /* Top of initialized data */-
807 /* assert (d == dest+top); */-
808-
809 /*-
810 * We now have fixed patterns in the dest buffer up to-
811 * "top", and we need to scramble them, with "randpasses"-
812 * random passes evenly spaced among them.-
813 *-
814 * We want one at the beginning, one at the end, and-
815 * evenly spaced in between. To do this, we basically-
816 * use Bresenham's line draw (a.k.a DDA) algorithm-
817 * to draw a line with slope (randpasses-1)/(num-1).-
818 * (We use a positive accumulator and count down to-
819 * do this.)-
820 *-
821 * So for each desired output value, we do the following:-
822 * - If it should be a random pass, copy the pass type-
823 * to top++, out of the way of the other passes, and-
824 * set the current pass to -1 (random).-
825 * - If it should be a normal pattern pass, choose an-
826 * entry at random between here and top-1 (inclusive)-
827 * and swap the current entry with that one.-
828 */-
829 randpasses--; /* To speed up later math */-
830 accum = randpasses; /* Bresenham DDA accumulator */-
831 for (n = 0; n < num; n++)
n < numDescription
TRUEevaluated 83 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 21 times by 1 test
Evaluated by:
  • shred
21-83
832 {-
833 if (accum <= randpasses)
accum <= randpassesDescription
TRUEevaluated 56 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 27 times by 1 test
Evaluated by:
  • shred
27-56
834 {-
835 accum += num - 1;-
836 dest[top++] = dest[n];-
837 dest[n] = -1;-
838 }
executed 56 times by 1 test: end of block
Executed by:
  • shred
56
839 else-
840 {-
841 swap = n + randint_choose (s, top - n);-
842 k = dest[n];-
843 dest[n] = dest[swap];-
844 dest[swap] = k;-
845 }
executed 27 times by 1 test: end of block
Executed by:
  • shred
27
846 accum -= randpasses;-
847 }
executed 83 times by 1 test: end of block
Executed by:
  • shred
83
848 /* assert (top == num); */-
849}
executed 21 times by 1 test: end of block
Executed by:
  • shred
21
850-
851/*-
852 * The core routine to actually do the work. This overwrites the first-
853 * size bytes of the given fd. Return true if successful.-
854 */-
855static bool-
856do_wipefd (int fd, char const *qname, struct randint_source *s,-
857 struct Options const *flags)-
858{-
859 size_t i;-
860 struct stat st;-
861 off_t size; /* Size to write, size to read */-
862 off_t i_size = 0; /* For small files, initial size to overwrite inode */-
863 unsigned long int n; /* Number of passes for printing purposes */-
864 int *passarray;-
865 bool ok = true;-
866 struct randread_source *rs;-
867-
868 n = 0; /* dopass takes n == 0 to mean "don't print progress" */-
869 if (flags->verbose)
flags->verboseDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 21 times by 1 test
Evaluated by:
  • shred
4-21
870 n = flags->n_iterations + flags->zero_fill;
executed 4 times by 1 test: n = flags->n_iterations + flags->zero_fill;
Executed by:
  • shred
4
871-
872 if (fstat (fd, &st))
fstat (fd, &st)Description
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
0-25
873 {-
874 error (0, errno, _("%s: fstat failed"), qname);-
875 return false;
never executed: return 0 ;
0
876 }-
877-
878 /* If we know that we can't possibly shred the file, give up now.-
879 Otherwise, we may go into an infinite loop writing data before we-
880 find that we can't rewind the device. */-
881 if ((S_ISCHR (st.st_mode) && isatty (fd))
(((( st.st_mod... == (0020000))Description
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
isatty (fd)Description
TRUEnever evaluated
FALSEnever evaluated
0-25
882 || S_ISFIFO (st.st_mode)
(((( st.st_mod... == (0010000))Description
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
0-25
883 || S_ISSOCK (st.st_mode))
(((( st.st_mod... == (0140000))Description
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
0-25
884 {-
885 error (0, 0, _("%s: invalid file type"), qname);-
886 return false;
never executed: return 0 ;
0
887 }-
888 else if (S_ISREG (st.st_mode) && st.st_size < 0)
(((( st.st_mod... == (0100000))Description
TRUEevaluated 25 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
st.st_size < 0Description
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
0-25
889 {-
890 error (0, 0, _("%s: file has negative size"), qname);-
891 return false;
never executed: return 0 ;
0
892 }-
893-
894 /* Allocate pass array */-
895 passarray = xnmalloc (flags->n_iterations, sizeof *passarray);-
896-
897 size = flags->size;-
898 if (size == -1)
size == -1Description
TRUEevaluated 17 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 8 times by 1 test
Evaluated by:
  • shred
8-17
899 {-
900 if (S_ISREG (st.st_mode))
(((( st.st_mod... == (0100000))Description
TRUEevaluated 17 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-17
901 {-
902 size = st.st_size;-
903-
904 if (! flags->exact)
! flags->exactDescription
TRUEevaluated 12 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 5 times by 1 test
Evaluated by:
  • shred
5-12
905 {-
906 /* Round up to the nearest block size to clear slack space. */-
907 off_t remainder = size % ST_BLKSIZE (st);
0 < (st).st_blksizeDescription
TRUEevaluated 12 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
(st).st_blksiz..._t)-1) / 8 + 1Description
TRUEevaluated 12 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-12
908 if (size && size < ST_BLKSIZE (st))
sizeDescription
TRUEevaluated 5 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 7 times by 1 test
Evaluated by:
  • shred
size < ((0 < (...lksize : 512 )Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-7
909 i_size = size;
executed 5 times by 1 test: i_size = size;
Executed by:
  • shred
5
910 if (remainder != 0)
remainder != 0Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 7 times by 1 test
Evaluated by:
  • shred
5-7
911 {-
912 off_t size_incr = ST_BLKSIZE (st) - remainder;
0 < (st).st_blksizeDescription
TRUEevaluated 5 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
(st).st_blksiz..._t)-1) / 8 + 1Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-5
913 size += MIN (size_incr, OFF_T_MAX - size);
(( size_incr )...1))) - size ))Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-5
914 }
executed 5 times by 1 test: end of block
Executed by:
  • shred
5
915 }
executed 12 times by 1 test: end of block
Executed by:
  • shred
12
916 }
executed 17 times by 1 test: end of block
Executed by:
  • shred
17
917 else-
918 {-
919 /* The behavior of lseek is unspecified, but in practice if-
920 it returns a positive number that's the size of this-
921 device. */-
922 size = lseek (fd, 0, SEEK_END);-
923 if (size <= 0)
size <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
924 {-
925 /* We are unable to determine the length, up front.-
926 Let dopass do that as part of its first iteration. */-
927 size = -1;-
928 }
never executed: end of block
0
929 }
never executed: end of block
0
930 }-
931 else if (S_ISREG (st.st_mode)
(((( st.st_mod... == (0100000))Description
TRUEevaluated 8 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-8
932 && st.st_size < MIN (ST_BLKSIZE (st), size))
st.st_size < (... ) ):( size ))Description
TRUEevaluated 8 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
0-8
933 i_size = st.st_size;
executed 8 times by 1 test: i_size = st.st_size;
Executed by:
  • shred
8
934-
935 /* Schedule the passes in random order. */-
936 genpattern (passarray, flags->n_iterations, s);-
937-
938 rs = randint_get_source (s);-
939-
940 while (true)-
941 {-
942 off_t pass_size;-
943 unsigned long int pn = n;-
944-
945 if (i_size)
i_sizeDescription
TRUEevaluated 12 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 43 times by 1 test
Evaluated by:
  • shred
12-43
946 {-
947 pass_size = i_size;-
948 i_size = 0;-
949 pn = 0;-
950 }
executed 12 times by 1 test: end of block
Executed by:
  • shred
12
951 else if (size)
sizeDescription
TRUEevaluated 18 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
18-25
952 {-
953 pass_size = size;-
954 size = 0;-
955 }
executed 18 times by 1 test: end of block
Executed by:
  • shred
18
956 /* TODO: consider handling tail packing by-
957 writing the tail padding as a separate pass,-
958 (that would not rewind). */-
959 else-
960 break;
executed 25 times by 1 test: break;
Executed by:
  • shred
25
961-
962 for (i = 0; i < flags->n_iterations + flags->zero_fill; i++)
i < flags->n_i...ags->zero_fillDescription
TRUEevaluated 137 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 30 times by 1 test
Evaluated by:
  • shred
30-137
963 {-
964 int err = 0;-
965 int type = i < flags->n_iterations ? passarray[i] : 0;
i < flags->n_iterationsDescription
TRUEevaluated 131 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 6 times by 1 test
Evaluated by:
  • shred
6-131
966-
967 err = dopass (fd, &st, qname, &pass_size, type, rs, i + 1, pn);-
968-
969 if (err)
errDescription
TRUEnever evaluated
FALSEevaluated 137 times by 1 test
Evaluated by:
  • shred
0-137
970 {-
971 ok = false;-
972 if (err < 0)
err < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
973 goto wipefd_out;
never executed: goto wipefd_out;
0
974 }
never executed: end of block
0
975 }
executed 137 times by 1 test: end of block
Executed by:
  • shred
137
976 }
executed 30 times by 1 test: end of block
Executed by:
  • shred
30
977-
978 /* Now deallocate the data. The effect of ftruncate on-
979 non-regular files is unspecified, so don't worry about any-
980 errors reported for them. */-
981 if (flags->remove_file && ftruncate (fd, 0) != 0
flags->remove_fileDescription
TRUEevaluated 15 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 10 times by 1 test
Evaluated by:
  • shred
ftruncate (fd, 0) != 0Description
TRUEnever evaluated
FALSEevaluated 15 times by 1 test
Evaluated by:
  • shred
0-15
982 && S_ISREG (st.st_mode))
(((( st.st_mod... == (0100000))Description
TRUEnever evaluated
FALSEnever evaluated
0
983 {-
984 error (0, errno, _("%s: error truncating"), qname);-
985 ok = false;-
986 goto wipefd_out;
never executed: goto wipefd_out;
0
987 }-
988-
989wipefd_out:
code before this statement executed 25 times by 1 test: wipefd_out:
Executed by:
  • shred
25
990 free (passarray);-
991 return ok;
executed 25 times by 1 test: return ok;
Executed by:
  • shred
25
992}-
993-
994/* A wrapper with a little more checking for fds on the command line */-
995static bool-
996wipefd (int fd, char const *qname, struct randint_source *s,-
997 struct Options const *flags)-
998{-
999 int fd_flags = fcntl (fd, F_GETFL);-
1000-
1001 if (fd_flags < 0)
fd_flags < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1002 {-
1003 error (0, errno, _("%s: fcntl failed"), qname);-
1004 return false;
never executed: return 0 ;
0
1005 }-
1006 if (fd_flags & O_APPEND)
fd_flags & 02000Description
TRUEnever evaluated
FALSEnever evaluated
0
1007 {-
1008 error (0, 0, _("%s: cannot shred append-only file descriptor"), qname);-
1009 return false;
never executed: return 0 ;
0
1010 }-
1011 return do_wipefd (fd, qname, s, flags);
never executed: return do_wipefd (fd, qname, s, flags);
0
1012}-
1013-
1014/* --- Name-wiping code --- */-
1015-
1016/* Characters allowed in a file name - a safe universal set. */-
1017static char const nameset[] =-
1018"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.";-
1019-
1020/* Increment NAME (with LEN bytes). NAME must be a big-endian base N-
1021 number with the digits taken from nameset. Return true if successful.-
1022 Otherwise, (because NAME already has the greatest possible value)-
1023 return false. */-
1024-
1025static bool-
1026incname (char *name, size_t len)-
1027{-
1028 while (len--)
len--Description
TRUEevaluated 65 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
1-65
1029 {-
1030 char const *p = strchr (nameset, name[len]);
__builtin_cons... ( name[len] )Description
TRUEnever evaluated
FALSEevaluated 65 times by 1 test
Evaluated by:
  • shred
!__builtin_con..._p ( nameset )Description
TRUEnever evaluated
FALSEnever evaluated
( name[len] ) == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0-65
1031-
1032 /* Given that NAME is composed of bytes from NAMESET,-
1033 P will never be NULL here. */-
1034 assert (p);-
1035-
1036 /* If this character has a successor, use it. */-
1037 if (p[1])
p[1]Description
TRUEevaluated 64 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
1-64
1038 {-
1039 name[len] = p[1];-
1040 return true;
executed 64 times by 1 test: return 1 ;
Executed by:
  • shred
64
1041 }-
1042-
1043 /* Otherwise, set this digit to 0 and increment the prefix. */-
1044 name[len] = nameset[0];-
1045 }
executed 1 time by 1 test: end of block
Executed by:
  • shred
1
1046-
1047 return false;
executed 1 time by 1 test: return 0 ;
Executed by:
  • shred
1
1048}-
1049-
1050/*-
1051 * Repeatedly rename a file with shorter and shorter names,-
1052 * to obliterate all traces of the file name (and length) on any system-
1053 * that adds a trailing delimiter to on-disk file names and reuses-
1054 * the same directory slot. Finally, unlink it.-
1055 * The passed-in filename is modified in place to the new filename.-
1056 * (Which is unlinked if this function succeeds, but is still present if-
1057 * it fails for some reason.)-
1058 *-
1059 * The main loop is written carefully to not get stuck if all possible-
1060 * names of a given length are occupied. It counts down the length from-
1061 * the original to 0. While the length is non-zero, it tries to find an-
1062 * unused file name of the given length. It continues until either the-
1063 * name is available and the rename succeeds, or it runs out of names-
1064 * to try (incname wraps and returns 1). Finally, it unlinks the file.-
1065 *-
1066 * The unlink is Unix-specific, as ANSI-standard remove has more-
1067 * portability problems with C libraries making it "safe". rename-
1068 * is ANSI-standard.-
1069 *-
1070 * To force the directory data out, we try to open the directory and-
1071 * invoke fdatasync and/or fsync on it. This is non-standard, so don't-
1072 * insist that it works: just fall back to a global sync in that case.-
1073 * This is fairly significantly Unix-specific. Of course, on any-
1074 * file system with synchronous metadata updates, this is unnecessary.-
1075 */-
1076static bool-
1077wipename (char *oldname, char const *qoldname, struct Options const *flags)-
1078{-
1079 char *newname = xstrdup (oldname);-
1080 char *base = last_component (newname);-
1081 char *dir = dir_name (newname);-
1082 char *qdir = xstrdup (quotef (dir));-
1083 bool first = true;-
1084 bool ok = true;-
1085 int dir_fd = -1;-
1086-
1087 if (flags->remove_file == remove_wipesync)
flags->remove_...emove_wipesyncDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
2-13
1088 dir_fd = open (dir, O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
executed 13 times by 1 test: dir_fd = open_safer (dir, 00 | 0200000 | 0400 | 04000 );
Executed by:
  • shred
13
1089-
1090 if (flags->verbose)
flags->verboseDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 11 times by 1 test
Evaluated by:
  • shred
4-11
1091 error (0, 0, _("%s: removing"), qoldname);
executed 4 times by 1 test: error (0, 0, dcgettext (((void *)0), "%s: removing" , 5) , qoldname);
Executed by:
  • shred
4
1092-
1093 if (flags->remove_file != remove_unlink)
flags->remove_... remove_unlinkDescription
TRUEevaluated 14 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
1-14
1094 for (size_t len = base_len (base); len != 0; len--)
len != 0Description
TRUEevaluated 53 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 14 times by 1 test
Evaluated by:
  • shred
14-53
1095 {-
1096 memset (base, nameset[0], len);-
1097 base[len] = 0;-
1098 bool rename_ok;-
1099 while (! (rename_ok = (renameat2 (AT_FDCWD, oldname, AT_FDCWD, newname,
! (rename_ok =...<< 0) ) == 0))Description
TRUEevaluated 75 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 42 times by 1 test
Evaluated by:
  • shred
42-75
1100 RENAME_NOREPLACE)
! (rename_ok =...<< 0) ) == 0))Description
TRUEevaluated 75 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 42 times by 1 test
Evaluated by:
  • shred
42-75
1101 == 0))
! (rename_ok =...<< 0) ) == 0))Description
TRUEevaluated 75 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 42 times by 1 test
Evaluated by:
  • shred
42-75
1102 && errno == EEXIST && incname (base, len))
(*__errno_location ()) == 17Description
TRUEevaluated 65 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 10 times by 1 test
Evaluated by:
  • shred
incname (base, len)Description
TRUEevaluated 64 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
1-65
1103 continue;
executed 64 times by 1 test: continue;
Executed by:
  • shred
64
1104 if (rename_ok)
rename_okDescription
TRUEevaluated 42 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 11 times by 1 test
Evaluated by:
  • shred
11-42
1105 {-
1106 if (0 <= dir_fd && dosync (dir_fd, qdir) != 0)
0 <= dir_fdDescription
TRUEevaluated 32 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 10 times by 1 test
Evaluated by:
  • shred
dosync (dir_fd, qdir) != 0Description
TRUEnever evaluated
FALSEevaluated 32 times by 1 test
Evaluated by:
  • shred
0-32
1107 ok = false;
never executed: ok = 0 ;
0
1108 if (flags->verbose)
flags->verboseDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 36 times by 1 test
Evaluated by:
  • shred
6-36
1109 {-
1110 /* People seem to understand this better than talking-
1111 about renaming OLDNAME. NEWNAME doesn't need-
1112 quoting because we picked it. OLDNAME needs to be-
1113 quoted only the first time. */-
1114 char const *old = first ? qoldname : oldname;
firstDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
2-4
1115 error (0, 0,-
1116 _("%s: renamed to %s"), old, newname);-
1117 first = false;-
1118 }
executed 6 times by 1 test: end of block
Executed by:
  • shred
6
1119 memcpy (oldname + (base - newname), base, len + 1);-
1120 }
executed 42 times by 1 test: end of block
Executed by:
  • shred
42
1121 }
executed 53 times by 1 test: end of block
Executed by:
  • shred
53
1122-
1123 if (unlink (oldname) != 0)
unlink (oldname) != 0Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • shred
FALSEevaluated 14 times by 1 test
Evaluated by:
  • shred
1-14
1124 {-
1125 error (0, errno, _("%s: failed to remove"), qoldname);-
1126 ok = false;-
1127 }
executed 1 time by 1 test: end of block
Executed by:
  • shred
1
1128 else if (flags->verbose)
flags->verboseDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 10 times by 1 test
Evaluated by:
  • shred
4-10
1129 error (0, 0, _("%s: removed"), qoldname);
executed 4 times by 1 test: error (0, 0, dcgettext (((void *)0), "%s: removed" , 5) , qoldname);
Executed by:
  • shred
4
1130 if (0 <= dir_fd)
0 <= dir_fdDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
2-13
1131 {-
1132 if (dosync (dir_fd, qdir) != 0)
dosync (dir_fd, qdir) != 0Description
TRUEnever evaluated
FALSEevaluated 13 times by 1 test
Evaluated by:
  • shred
0-13
1133 ok = false;
never executed: ok = 0 ;
0
1134 if (close (dir_fd) != 0)
close (dir_fd) != 0Description
TRUEnever evaluated
FALSEevaluated 13 times by 1 test
Evaluated by:
  • shred
0-13
1135 {-
1136 error (0, errno, _("%s: failed to close"), qdir);-
1137 ok = false;-
1138 }
never executed: end of block
0
1139 }
executed 13 times by 1 test: end of block
Executed by:
  • shred
13
1140 free (newname);-
1141 free (dir);-
1142 free (qdir);-
1143 return ok;
executed 15 times by 1 test: return ok;
Executed by:
  • shred
15
1144}-
1145-
1146/*-
1147 * Finally, the function that actually takes a filename and grinds-
1148 * it into hamburger.-
1149 *-
1150 * FIXME-
1151 * Detail to note: since we do not restore errno to EACCES after-
1152 * a failed chmod, we end up printing the error code from the chmod.-
1153 * This is actually the error that stopped us from proceeding, so-
1154 * it's arguably the right one, and in practice it'll be either EACCES-
1155 * again or EPERM, which both give similar error messages.-
1156 * Does anyone disagree?-
1157 */-
1158static bool-
1159wipefile (char *name, char const *qname,-
1160 struct randint_source *s, struct Options const *flags)-
1161{-
1162 bool ok;-
1163 int fd;-
1164-
1165 fd = open (name, O_WRONLY | O_NOCTTY | O_BINARY);-
1166 if (fd < 0
fd < 0Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • shred
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
1-25
1167 && (errno == EACCES && flags->force)
(*__errno_location ()) == 13Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
flags->forceDescription
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • shred
0-1
1168 && chmod (name, S_IWUSR) == 0)
chmod (name, 0200 ) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1169 fd = open (name, O_WRONLY | O_NOCTTY | O_BINARY);
never executed: fd = open_safer (name, 01 | 0400 | 0 );
0
1170 if (fd < 0)
fd < 0Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • shred
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
1-25
1171 {-
1172 error (0, errno, _("%s: failed to open for writing"), qname);-
1173 return false;
executed 1 time by 1 test: return 0 ;
Executed by:
  • shred
1
1174 }-
1175-
1176 ok = do_wipefd (fd, qname, s, flags);-
1177 if (close (fd) != 0)
close (fd) != 0Description
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • shred
0-25
1178 {-
1179 error (0, errno, _("%s: failed to close"), qname);-
1180 ok = false;-
1181 }
never executed: end of block
0
1182 if (ok && flags->remove_file)
okDescription
TRUEevaluated 25 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
flags->remove_fileDescription
TRUEevaluated 15 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 10 times by 1 test
Evaluated by:
  • shred
0-25
1183 ok = wipename (name, qname, flags);
executed 15 times by 1 test: ok = wipename (name, qname, flags);
Executed by:
  • shred
15
1184 return ok;
executed 25 times by 1 test: return ok;
Executed by:
  • shred
25
1185}-
1186-
1187-
1188/* Buffers for random data. */-
1189static struct randint_source *randint_source;-
1190-
1191/* Just on general principles, wipe buffers containing information-
1192 that may be related to the possibly-pseudorandom values used during-
1193 shredding. */-
1194static void-
1195clear_random_data (void)-
1196{-
1197 randint_all_free (randint_source);-
1198}
executed 24 times by 1 test: end of block
Executed by:
  • shred
24
1199-
1200-
1201int-
1202main (int argc, char **argv)-
1203{-
1204 bool ok = true;-
1205 struct Options flags = { 0, };-
1206 char **file;-
1207 int n_files;-
1208 int c;-
1209 int i;-
1210 char const *random_source = NULL;-
1211-
1212 initialize_main (&argc, &argv);-
1213 set_program_name (argv[0]);-
1214 setlocale (LC_ALL, "");-
1215 bindtextdomain (PACKAGE, LOCALEDIR);-
1216 textdomain (PACKAGE);-
1217-
1218 atexit (close_stdout);-
1219-
1220 flags.n_iterations = DEFAULT_PASSES;-
1221 flags.size = -1;-
1222-
1223 while ((c = getopt_long (argc, argv, "fn:s:uvxz", long_opts, NULL)) != -1)
(c = getopt_lo... *)0) )) != -1Description
TRUEevaluated 87 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 24 times by 1 test
Evaluated by:
  • shred
24-87
1224 {-
1225 switch (c)-
1226 {-
1227 case 'f':
executed 2 times by 1 test: case 'f':
Executed by:
  • shred
2
1228 flags.force = true;-
1229 break;
executed 2 times by 1 test: break;
Executed by:
  • shred
2
1230-
1231 case 'n':
executed 15 times by 1 test: case 'n':
Executed by:
  • shred
15
1232 flags.n_iterations = xdectoumax (optarg, 0,-
1233 MIN (ULONG_MAX,-
1234 SIZE_MAX / sizeof (int)), "",-
1235 _("invalid number of passes"), 0);-
1236 break;
executed 13 times by 1 test: break;
Executed by:
  • shred
13
1237-
1238 case RANDOM_SOURCE_OPTION:
executed 2 times by 1 test: case RANDOM_SOURCE_OPTION:
Executed by:
  • shred
2
1239 if (random_source && !STREQ (random_source, optarg))
never executed: __result = (((const unsigned char *) (const char *) ( random_source ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( optarg ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
random_sourceDescription
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • shred
!( __extension...)))); }) == 0)Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-2
1240 die (EXIT_FAILURE, 0, _("multiple random sources specified"));
never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"multiple random sources specified\", 5)), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , 0, dcgettext (((void *)0), "multiple random sources specified" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "multiple random sources specified" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))));
0
1241 random_source = optarg;-
1242 break;
executed 2 times by 1 test: break;
Executed by:
  • shred
2
1243-
1244 case 'u':
executed 17 times by 1 test: case 'u':
Executed by:
  • shred
17
1245 if (optarg == NULL)
optarg == ((void *)0)Description
TRUEevaluated 13 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 4 times by 1 test
Evaluated by:
  • shred
4-13
1246 flags.remove_file = remove_wipesync;
executed 13 times by 1 test: flags.remove_file = remove_wipesync;
Executed by:
  • shred
13
1247 else-
1248 flags.remove_file = XARGMATCH ("--remove", optarg,
executed 4 times by 1 test: flags.remove_file = ((remove_methods) [__xargmatch_internal ("--remove", optarg, remove_args, (char const *) (remove_methods), sizeof *(remove_methods), argmatch_die)]) ;
Executed by:
  • shred
4
1249 remove_args, remove_methods);
executed 4 times by 1 test: flags.remove_file = ((remove_methods) [__xargmatch_internal ("--remove", optarg, remove_args, (char const *) (remove_methods), sizeof *(remove_methods), argmatch_die)]) ;
Executed by:
  • shred
4
1250 break;
executed 16 times by 1 test: break;
Executed by:
  • shred
16
1251-
1252 case 's':
executed 11 times by 1 test: case 's':
Executed by:
  • shred
11
1253 flags.size = xnumtoumax (optarg, 0, 0, OFF_T_MAX, "cbBkKMGTPEZY0",-
1254 _("invalid file size"), 0);-
1255 break;
executed 8 times by 1 test: break;
Executed by:
  • shred
8
1256-
1257 case 'v':
executed 6 times by 1 test: case 'v':
Executed by:
  • shred
6
1258 flags.verbose = true;-
1259 break;
executed 6 times by 1 test: break;
Executed by:
  • shred
6
1260-
1261 case 'x':
executed 6 times by 1 test: case 'x':
Executed by:
  • shred
6
1262 flags.exact = true;-
1263 break;
executed 6 times by 1 test: break;
Executed by:
  • shred
6
1264-
1265 case 'z':
executed 4 times by 1 test: case 'z':
Executed by:
  • shred
4
1266 flags.zero_fill = true;-
1267 break;
executed 4 times by 1 test: break;
Executed by:
  • shred
4
1268-
1269 case_GETOPT_HELP_CHAR;
never executed: break;
executed 14 times by 1 test: case GETOPT_HELP_CHAR:
Executed by:
  • shred
0-14
1270-
1271 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
executed 7 times by 1 test: exit ( 0 );
Executed by:
  • shred
never executed: break;
executed 7 times by 1 test: case GETOPT_VERSION_CHAR:
Executed by:
  • shred
0-7
1272-
1273 default:
executed 3 times by 1 test: default:
Executed by:
  • shred
3
1274 usage (EXIT_FAILURE);-
1275 }
never executed: end of block
0
1276 }-
1277-
1278 file = argv + optind;-
1279 n_files = argc - optind;-
1280-
1281 if (n_files == 0)
n_files == 0Description
TRUEnever evaluated
FALSEevaluated 24 times by 1 test
Evaluated by:
  • shred
0-24
1282 {-
1283 error (0, 0, _("missing file operand"));-
1284 usage (EXIT_FAILURE);-
1285 }
never executed: end of block
0
1286-
1287 randint_source = randint_all_new (random_source, SIZE_MAX);-
1288 if (! randint_source)
! randint_sourceDescription
TRUEnever evaluated
FALSEevaluated 24 times by 1 test
Evaluated by:
  • shred
0-24
1289 die (EXIT_FAILURE, errno, "%s", quotef (random_source));
never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), \"%s\", quotearg_n_style_colon (0, shell_escape_quoting_style, random_source)), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , (*__errno_loca...escape_quoting_style, random_source)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , "%s", quotearg_n_style_colon (0, shell_escape_quoting_style, random_source)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))));
0
1290 atexit (clear_random_data);-
1291-
1292 for (i = 0; i < n_files; i++)
i < n_filesDescription
TRUEevaluated 26 times by 1 test
Evaluated by:
  • shred
FALSEevaluated 24 times by 1 test
Evaluated by:
  • shred
24-26
1293 {-
1294 char *qname = xstrdup (quotef (file[i]));-
1295 if (STREQ (file[i], "-"))
never executed: __result = (((const unsigned char *) (const char *) ( file[i] ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( "-" ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
( __extension_...)))); }) == 0)Description
TRUEnever evaluated
FALSEevaluated 26 times by 1 test
Evaluated by:
  • shred
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEevaluated 26 times by 1 test
Evaluated by:
  • shred
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEevaluated 26 times by 1 test
Evaluated by:
  • shred
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-26
1296 {-
1297 ok &= wipefd (STDOUT_FILENO, qname, randint_source, &flags);-
1298 }
never executed: end of block
0
1299 else-
1300 {-
1301 /* Plain filename - Note that this overwrites *argv! */-
1302 ok &= wipefile (file[i], qname, randint_source, &flags);-
1303 }
executed 26 times by 1 test: end of block
Executed by:
  • shred
26
1304 free (qname);-
1305 }
executed 26 times by 1 test: end of block
Executed by:
  • shred
26
1306-
1307 return ok ? EXIT_SUCCESS : EXIT_FAILURE;
executed 24 times by 1 test: return ok ? 0 : 1 ;
Executed by:
  • shred
24
1308}-
1309/*-
1310 * vim:sw=2:sts=2:-
1311 */-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2