···11-Terms and Conditions
22-33- Copyright � 2000 Matthew D. Gauthier
44-55- Permission is hereby granted, free of charge, to any person obtaining
66- a copy of this software and associated documentation files (the
77- "Software"), to deal in the Software without restriction, including
88- without limitation the rights to use, copy, modify, merge, publish,
99- distribute, sublicense, and/or sell copies of the Software, and to
1010- permit persons to whom the Software is furnished to do so, subject to
1111- the following conditions:
1212-1313- The above copyright notice and this permission notice shall be
1414- included in all copies or substantial portions of the Software.
1515-1616- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1717- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1818- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1919- IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2020- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2121- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2222- OTHER DEALINGS IN THE SOFTWARE.
2323-2424- Except as contained in this notice, the name of the contributors shall
2525- not be used in advertising or otherwise to promote the sale, use or
2626- other dealings in this Software without prior written authorization.
-204
src/libremovefile/checkint.3
···11-.Dd April 20, 2007
22-.Dt CHECK_INT32_ADD 3
33-.Os
44-.Sh NAME
55-.Nm check_int32_add ,
66-.Nm check_uint32_add ,
77-.Nm check_int64_add ,
88-.Nm check_uint64_add ,
99-.Nm check_int32_sub ,
1010-.Nm check_uint32_sub ,
1111-.Nm check_int64_sub ,
1212-.Nm check_uint64_sub ,
1313-.Nm check_int32_mul ,
1414-.Nm check_uint32_mul ,
1515-.Nm check_int64_mul ,
1616-.Nm check_uint64_mul ,
1717-.Nm check_int32_div ,
1818-.Nm check_uint32_div ,
1919-.Nm check_int64_div ,
2020-.Nm check_uint64_div ,
2121-.Nd detect overflow in arithmetic
2222-.Sh SYNOPSIS
2323-.In checkint.h
2424-.Ft int32_t
2525-.Fo check_int32_add
2626-.Fa "int x"
2727-.Fa "int y"
2828-.Fa "int *err"
2929-.Fc
3030-.Ft uint32_t
3131-.Fo check_uint32_add
3232-.Fa "int x"
3333-.Fa "int y"
3434-.Fa "int *err"
3535-.Fc
3636-.Ft int64_t
3737-.Fo check_int64_add
3838-.Fa "int x"
3939-.Fa "int y"
4040-.Fa "int *err"
4141-.Fc
4242-.Ft uint64_t
4343-.Fo check_uint64_add
4444-.Fa "int x"
4545-.Fa "int y"
4646-.Fa "int *err"
4747-.Fc
4848-.Ft int32_t
4949-.Fo check_int32_sub
5050-.Fa "int x"
5151-.Fa "int y"
5252-.Fa "int *err"
5353-.Fc
5454-.Ft uint32_t
5555-.Fo check_uint32_sub
5656-.Fa "int x"
5757-.Fa "int y"
5858-.Fa "int *err"
5959-.Fc
6060-.Ft int64_t
6161-.Fo check_int64_sub
6262-.Fa "int x"
6363-.Fa "int y"
6464-.Fa "int *err"
6565-.Fc
6666-.Ft uint64_t
6767-.Fo check_uint64_sub
6868-.Fa "int x"
6969-.Fa "int y"
7070-.Fa "int *err"
7171-.Fc
7272-.Ft int32_t
7373-.Fo check_int32_mul
7474-.Fa "int x"
7575-.Fa "int y"
7676-.Fa "int *err"
7777-.Fc
7878-.Ft uint32_t
7979-.Fo check_uint32_mul
8080-.Fa "int x"
8181-.Fa "int y"
8282-.Fa "int *err"
8383-.Fc
8484-.Ft int64_t
8585-.Fo check_int64_mul
8686-.Fa "int x"
8787-.Fa "int y"
8888-.Fa "int *err"
8989-.Fc
9090-.Ft uint64_t
9191-.Fo check_uint64_mul
9292-.Fa "int x"
9393-.Fa "int y"
9494-.Fa "int *err"
9595-.Fc
9696-.Ft int32_t
9797-.Fo check_int32_div
9898-.Fa "int x"
9999-.Fa "int y"
100100-.Fa "int *err"
101101-.Fc
102102-.Ft uint32_t
103103-.Fo check_uint32_div
104104-.Fa "int x"
105105-.Fa "int y"
106106-.Fa "int *err"
107107-.Fc
108108-.Ft int64_t
109109-.Fo check_int64_div
110110-.Fa "int x"
111111-.Fa "int y"
112112-.Fa "int *err"
113113-.Fc
114114-.Ft uint64_t
115115-.Fo check_uint64_div
116116-.Fa "int x"
117117-.Fa "int y"
118118-.Fa "int *err"
119119-.Fc
120120-.Sh DESCRIPTION
121121-The
122122-.Fn check_<type>_<operation> "x" "y" "err"
123123-family of functions perform the specified arithmetic operation (addition, subtraction,
124124-multiplication, or division) with the left operand of
125125-.Fa x
126126-and right operand of
127127-.Fa y
128128-and return the arithmetic result with the specified type.
129129-.Pp
130130-Either operand
131131-.Fa x
132132-or
133133-.Fa y
134134-(or both) can be of any type that is compatible to signed or unsigned
135135-8-bit, 16-bit, 32-bit, or 64-bit integers.
136136-.Pp
137137-The
138138-.Fa err
139139-argument is
140140-.Em or Ns 'ed
141141-by flags in the function to indicate if an overflow has occurred.
142142-The possible flag values are:
143143-.Pp
144144-.Bd -literal -offset indent -compact
145145-CHECKINT_NO_ERROR no overflow has occurred
146146-CHECKINT_OVERFLOW_ERROR overflow has occurred
147147-CHECKINT_TYPE_ERROR operand is of an incompatible type
148148-.Ed
149149-.Pp
150150-The
151151-.Fa err
152152-argument is not cleared in calls to the
153153-.Fn check_<type>_<operation> "x" "y" "err"
154154-functions. Detected overflow persists in the
155155-.Fa err
156156-argument until
157157-.Fa err
158158-is reset to CHECKINT_NO_ERROR.
159159-.Sh RETURN VALUES
160160-If successful, the
161161-.Fn check_<type>_<operation>
162162-functions will return the arithmetic result of performing the operation with left operand
163163-.Fa x
164164-and right operand
165165-.Fa y
166166-(even when overflow error occurs).
167167-.Pp
168168-If any other error occurs, the return value is -1
169169-and the argument
170170-.Fa err
171171-will be set to indicate the error.
172172-.Sh EXAMPLES
173173-.Bd -literal -offset indent
174174-/* Create a variable to store overflow flag */
175175-int32_t err = CHECKINT_NO_ERROR;
176176-/* Use checkint API to perform an arithmetic operation and
177177- * store result in variable. */
178178-int32_t arithmetic_result = check_int32_add(UINT_MAX, 1, &err);
179179-/* Check status of overflow flag */
180180-if (err & CHECKINT_OVERFLOW_ERROR) {
181181- /* Perform overflow resolution code */
182182- fprintf(stderr, "Overflow detected!\\n");
183183-}
184184-/* Check for type error */
185185-else if (err & CHECKINT_TYPE_ERROR) {
186186- /* Deal with incompatible types error */
187187- fprintf(stderr, "Incompatible types!\\n");
188188-}
189189-/* Reset overflow flag for next operation */
190190-err = CHECKINT_NO_ERROR;
191191-192192-.Ed
193193-.Sh ERRORS
194194-The
195195-.Fn check_<type>_<operation>
196196-functions may fail if:
197197-.Pp
198198-.Bd -literal -offset indent -compact
199199-[CHECKINT_TYPE_ERROR] operand is of an incompatible type
200200-.Ed
201201-.Sh HISTORY
202202-The
203203-.Fn checkint
204204-API was introduced in Mac OS X 10.5.
···11-.\" Copyright (c) 2015 Apple Inc.
22-.\" All rights reserved.
33-.\"
44-.\" Redistribution and use in source and binary forms, with or without
55-.\" modification, are permitted provided that the following conditions
66-.\" are met:
77-.\" 1. Redistributions of source code must retain the above copyright
88-.\" notice, this list of conditions and the following disclaimer.
99-.\" 2. Redistributions in binary form must reproduce the above copyright
1010-.\" notice, this list of conditions and the following disclaimer in the
1111-.\" documentation and/or other materials provided with the distribution.
1212-.\" 3. Neither the name of Apple Inc. ("Apple") nor the names of its
1313-.\" contributors may be used to endorse or promote products derived from
1414-.\" this software without specific prior written permission.
1515-.\"
1616-.\" THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
1717-.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1818-.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1919-.\" DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
2020-.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2121-.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2222-.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2323-.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2424-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2525-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2626-.\"
2727-.Dd Feb 26, 2015
2828-.Dt REMOVEFILE 3
2929-.Os
3030-.Sh NAME
3131-.Nm removefile , removefile_state_alloc ,
3232-.Nm removefile_state_free , removefile_state_get ,
3333-.Nm removefile_state_set
3434-.Nd remove files or directories
3535-.Sh SYNOPSIS
3636-.In removefile.h
3737-.Ft int
3838-.Fn removefile "const char *path" "removefile_state_t state" "removefile_flags_t flags"
3939-.Ft removefile_state_t
4040-.Fn removefile_state_alloc "void"
4141-.Ft int
4242-.Fn removefile_state_free "removefile_state_t state"
4343-.Ft int
4444-.Fn removefile_state_get "removefile_state_t state" "uint32_t key" "void * dst"
4545-.Ft int
4646-.Fn removefile_state_set "removefile_state_t state" "uint32_t key" "const void * value"
4747-.Ft int
4848-.Fn removefile_cancel "removefile_state_t state"
4949-.Sh DESCRIPTION
5050-.Pp
5151-These functions are used to remove a file or directory. Various levels
5252-of overwriting may be specified to prevent other people from recovering any
5353-information about the file.
5454-.Pp
5555-The
5656-.Fn removefile_state_alloc
5757-function initializes a
5858-.Vt removefile_state_t
5959-object (which is an opaque data type).
6060-This object can be passed to
6161-.Fn removefile .
6262-.Fn removefile_state_get
6363-and
6464-.Fn removefile_state_set
6565-can be used to manipulate the state (see below).
6666-The
6767-.Fn removefile_state_free
6868-function is used to deallocate the object and its contents.
6969-.Pp
7070-The
7171-.Fn removefile
7272-function removes files and directories located at the named
7373-.Va path
7474-filesystem location. The named
7575-.Va path
7676-location can be specified as either an absolute path or relative to the working directory
7777-of the calling process.
7878-If the
7979-.Va state
8080-parameter is the return value from
8181-.Fn removefile_state_alloc ,
8282-then
8383-.Fn removefile
8484-will use the information from the state object; if it is
8585-.Dv NULL ,
8686-then
8787-.Fn removefile
8888-will work normally, but less control will be available to the caller.
8989-The
9090-.Va flags
9191-parameter controls deletion options:
9292-.Bl -tag -width REMOVEFILE_SECURE_1_PASS_ZERO
9393-.It Dv REMOVEFILE_RECURSIVE
9494-If the
9595-.Va path
9696-location is a directory, then recursively delete the entire directory.
9797-.It Dv REMOVEFILE_KEEP_PARENT
9898-The file or directory at the
9999-.Va path
100100-location is not deleted. If specified in conjunction with REMOVEFILE_RECURSIVE,
101101-then all of the contents of the directory at
102102-.Va path
103103-location will be deleted, but not the directory itself.
104104-.It Dv REMOVEFILE_CROSS_MOUNT
105105-By default, recursive traversals do not cross mount points. This option allows
106106-.Fn removefile
107107-to descend into directories that have a different device number than the file from which
108108-the descent began.
109109-.It Dv REMOVEFILE_SECURE_7_PASS
110110-Overwrite the file with 7 US DoD compliant passes (0xF6, 0x00, 0xFF, random, 0x00, 0xFF, random).
111111-.It Dv REMOVEFILE_SECURE_35_PASS
112112-Overwrite the file using 35-pass Gutmann algorithm.
113113-.It Dv REMOVEFILE_SECURE_3_PASS
114114-Overwrite the file twice with random bytes, and then with 0xAA.
115115-.It Dv REMOVEFILE_SECURE_1_PASS
116116-Overwrite with a single pass of random data.
117117-.It Dv REMOVEFILE_SECURE_1_PASS_ZERO
118118-Overwrite with a single pass of zeroes.
119119-.El
120120-.Pp
121121-The
122122-.Fn removefile_state_get
123123-and
124124-.Fn removefile_state_set
125125-functions can be used to manipulate the
126126-.Ft removefile_state_t
127127-object returned by
128128-.Fn removefile_state_alloc .
129129-In both functions, the
130130-.Va dst
131131-or the
132132-.Va value
133133-parameter's type depends on the
134134-.Va key
135135-parameter that is passed in.
136136-.Bl -tag -width REMOVEFILE_STATE_CONFIRM_CALLBACK
137137-.It Dv REMOVEFILE_STATE_CONFIRM_CALLBACK
138138-Get or set the callback function of type
139139-.Va removefile_callback_t
140140-to be called prior to file deletion.
141141-.It Dv REMOVEFILE_STATE_CONFIRM_CONTEXT
142142-Get or set any parameters of type
143143-.Va void *
144144-that are needed for the confirm callback function.
145145-.It Dv REMOVEFILE_STATE_ERROR_CALLBACK
146146-Get or set the callback function of type
147147-.Va removefile_callback_t
148148-to be called when an error is detected.
149149-.It Dv REMOVEFILE_STATE_ERROR_CONTEXT
150150-Get or set any parameters of type
151151-.Va void *
152152-that are needed for the error callback function.
153153-.It Dv REMOVEFILE_STATE_ERRNO
154154-Get or set the current errno of type
155155-.Va int
156156-.It Dv REMOVEFILE_STATE_STATUS_CALLBACK
157157-Get or set the callback function of type
158158-.Va removefile_callback_t
159159-to be called subsequent to file deletion.
160160-.It Dv REMOVEFILE_STATE_STATUS_CONTEXT
161161-Get or set any parameters of type
162162-.Va void *
163163-that are needed for the status callback function.
164164-.El
165165-.Pp
166166-The
167167-.Va removefile_callback_t
168168-function pointer is defined as the following:
169169-.Pp
170170-.Ft int
171171-.Va (*removefile_callback_t) (removefile_state_t state, const char *path , void *context)
172172-.Pp
173173-The return value of the callback function is given as:
174174-.Bl -tag -width REMOVEFILE_PROCEED
175175-.It Dv REMOVEFILE_PROCEED
176176-File is deleted and
177177-.Fn removefile
178178-continues operation as normal.
179179-.It Dv REMOVEFILE_SKIP
180180-Current file is not deleted and
181181-.Fn removefile
182182-continues operation as normal.
183183-.It Dv REMOVEFILE_STOP
184184-Current file is not deleted and
185185-.Fn removefile
186186-exits without continuing further.
187187-.El
188188-.Pp
189189-The
190190-.Fn removefile_cancel
191191-function is used to cancel a remove that is in progress.
192192-.Sh RETURN VALUES
193193-The family of
194194-.Fn removefile
195195-functions returns less than 0 on error, and 0 on success.
196196-.Sh ERRORS
197197-.Fn removefile
198198-will fail if:
199199-.Bl -tag -width Er
200200-.It Bq Er EACCES
201201-The
202202-.Va path
203203-location specifies a file or directory for which the calling process does not
204204-have proper permissions.
205205-.It Bq Er EINVAL
206206-A callback returned an invalid return value (not REMOVEFILE_PROCEED, REMOVEFILE_SKIP, or REMOVEFILE_STOP)
207207-.It Bq Er EMLINK
208208-The
209209-.Va path
210210-location refers to a symbolic link.
211211-.It Bq Er ENAMETOOLONG
212212-The resource fork name of the file exceeds the maximum allowed length.
213213-.It Bq Er ENOMEM
214214-A memory allocation failed.
215215-.It Bq Er ENOTEMPTY
216216-The
217217-.Va path
218218-location specifies a directory that contains an immutable file which cannot be
219219-deleted.
220220-.It Bq Er EPERM
221221-The
222222-.Va path
223223-location specifies an immutable file that cannot be deleted.
224224-.El
225225-.Pp
226226-.Fn removefile_cancel
227227-will fail if:
228228-.Bl -tag -width Er
229229-.It Bq Er EINVAL
230230-A
231231-.Va NULL
232232-parameter was passed into
233233-.Fn removefile_cancel .
234234-.El
235235-.Pp
236236-In addition, all functions may return an error from an underlying library or
237237-system call.
238238-.Sh NOTES
239239-.Pp
240240-Write protected files owned by another user cannot be removed by
241241-.Fn removefile ,
242242-regardless of the permissions on the directory containing the file.
243243-.Pp
244244-If multiple of the REMOVEFILE_SECURE_1_PASS, REMOVEFILE_SECURE_7_PASS, and REMOVEFILE_SECURE_35_PASS
245245-flags are specified,
246246-.Fn removefile
247247-will proceed using the flag that specifies the highest number of overwriting passes.
248248-.Pp
249249-.Fn removefile
250250-is pathname-based; this means that, when descending into a hierarchy, there are potential race conditions
251251-that may add risk when run with privileges.
252252-.Pp
253253-.Fn removefile
254254-operates on symbolic links, rather than the target of the link.
255255-.Sh EXAMPLES
256256-.Bd -literal -offset indent
257257-/* Initialize a state variable */
258258-removefile_state_t s;
259259-s = removefile_state_alloc();
260260-/* Recursively remove all files and directories while keeping parent tmp directory. */
261261-removefile("/tmp", s, REMOVEFILE_RECURSIVE | REMOVEFILE_KEEP_PARENT);
262262-/* Release the state variable */
263263-removefile_state_free(s);
264264-.Pp
265265-/* A more complex way to call removefile() -- define a callback function */
266266-int removefile_status_callback(removefile_state_t state, const char * path, void * context) {
267267- fprintf(stderr, "File deleted: %s", path);
268268- return REMOVEFILE_PROCEED;
269269-}
270270-/* Initialize a state variable */
271271-s = removefile_state_alloc();
272272-/* Set callback function properties */
273273-removefile_state_set(s, REMOVEFILE_STATE_CONFIRM_CALLBACK, removefile_confirm_callback);
274274-removefile_state_set(s, REMOVEFILE_STATE_CONFIRM_CONTEXT, NULL);
275275-/* Recursively remove all files and directories while keeping parent tmp directory,
276276- calling a confirm callback prior to each file deletion. */
277277-removefile("/tmp", s, REMOVEFILE_RECURSIVE | REMOVEFILE_KEEP_PARENT);
278278-/* Release the state variable. */
279279-removefile_state_free(s);
280280-.Ed
281281-.Sh "SEE ALSO"
282282-.Xr unlink 1 ,
283283-.Xr sync 2 ,
284284-.Xr sync_volume_np 3
285285-.Sh HISTORY
286286-The
287287-.Fn removefile
288288-API was introduced in Mac OS X 10.5.
···11-#ifdef __cplusplus
22-extern "C" {
33-#endif
44-55-#include "removefile.h"
66-77-#include <sys/stat.h>
88-#include <sys/param.h>
99-#include <sys/mount.h>
1010-1111-#include <err.h>
1212-#include <errno.h>
1313-#include <fcntl.h>
1414-#include <fts.h>
1515-#include <stdio.h>
1616-#include <stdlib.h>
1717-#include <string.h>
1818-#include <sysexits.h>
1919-#include <unistd.h>
2020-2121-/*
2222- * This structure contains variables necessary to keep track of verification,
2323- * the flags set by the user, as well as associated buffers and file
2424- * attributes. These were defined previously by srm as global variables but a
2525- * structure is a much cleaner way of organizing the information and passing
2626- * it between functions.
2727- */
2828-2929-struct _removefile_state {
3030- removefile_callback_t confirm_callback;
3131- void * confirm_context;
3232- removefile_callback_t error_callback;
3333- void * error_context;
3434- int error_num; // clear on proceed
3535- removefile_callback_t status_callback;
3636- void * status_context;
3737-3838- // globals for srm
3939- int urand_file;
4040- off_t random_bytes_read;
4141- int file;
4242- off_t file_size;
4343- unsigned char * buffer;
4444- uint32_t buffsize;
4545- uint32_t allocated_buffsize;
4646- int unlink_flags;
4747- int cancelled;
4848-};
4949-5050-int __removefile_rename_unlink(const char*path, removefile_state_t state);
5151-int __removefile_tree_walker(char ** trees, removefile_state_t state);
5252-int __removefile_sunlink(const char * path, removefile_state_t state);
5353-void __removefile_init_random(const unsigned int seed, removefile_state_t state);
5454-char __removefile_random_char(removefile_state_t state);
5555-void __removefile_randomize_buffer(unsigned char *buffer, size_t length, removefile_state_t state);
5656-5757-#define __removefile_state_test_cancel(s) ((s)->cancelled != 0)
5858-5959-#ifdef __cplusplus
6060-}
6161-#endif
6262-6363-#if __APPLE__
6464-#ifndef AT_REMOVEDIR_DATALESS
6565-#define AT_REMOVEDIR_DATALESS 0x0100 /* Remove a dataless directory without materializing first */
6666-#endif
6767-#endif
-119
src/libremovefile/removefile_random.c
···11-/* srm */
22-/* Copyright (c) 2000 Matthew D. Gauthier
33- * Portions copyright (c) 2007 Apple Inc. All rights reserved.
44- *
55- * Permission is hereby granted, free of charge, to any person obtaining
66- * a copy of this software and associated documentation files (the
77- * "Software"), to deal in the Software without restriction, including
88- * without limitation the rights to use, copy, modify, merge, publish,
99- * distribute, sublicense, and/or sell copies of the Software, and to
1010- * permit persons to whom the Software is furnished to do so, subject to
1111- * the following conditions:
1212- *
1313- * The above copyright notice and this permission notice shall be
1414- * included in all copies or substantial portions of the Software.
1515- *
1616- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1717- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1818- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1919- * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2020- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2121- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2222- * OTHER DEALINGS IN THE SOFTWARE.
2323- *
2424- * Except as contained in this notice, the name of the contributors shall
2525- * not be used in advertising or otherwise to promote the sale, use or
2626- * other dealings in this Software without prior written authorization.
2727- */
2828-2929-#include <fcntl.h>
3030-#include <stdlib.h>
3131-#include <sys/stat.h>
3232-#include <sys/types.h>
3333-#include <sys/time.h>
3434-#include <unistd.h>
3535-3636-#include "removefile.h"
3737-#include "removefile_priv.h"
3838-3939-static void
4040-seed_random(removefile_state_t state) {
4141-#ifdef USE_ARC4RANDOM
4242- arc4random_stir();
4343-#else
4444- unsigned int rseed;
4545- struct timeval tv;
4646- struct timezone tz;
4747-4848- if (state->urand_file != -1) {
4949- read(state->urand_file, &rseed, sizeof(rseed));
5050- } else {
5151- rseed = rand();
5252- }
5353- (void)gettimeofday(&tv, &tz);
5454- rseed ^= tv.tv_sec + tv.tv_usec + getpid();
5555- srand(rseed);
5656-#endif
5757-}
5858-5959-void
6060-__removefile_init_random(const unsigned int seed, removefile_state_t state) {
6161-#ifdef USE_ARC4RANDOM
6262- arc4random_addrandom((unsigned char *)&seed, sizeof(seed));
6363-#else
6464- struct stat statbuf;
6565-6666- if (stat("/dev/urandom", &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
6767- state->urand_file = open("/dev/urandom", O_RDONLY);
6868- } else {
6969- srand(seed);
7070- }
7171- seed_random(state);
7272-#endif
7373-}
7474-7575-char
7676-__removefile_random_char(removefile_state_t state) {
7777-#ifdef USE_ARC4RANDOM
7878- random_bytes_read += 4;
7979- return arc4random();
8080-#else
8181- char buf[4];
8282-8383- if (state->urand_file != -1) {
8484- read(state->urand_file, &buf, 1);
8585- return buf[0];
8686- }
8787- return rand();
8888-#endif
8989-}
9090-9191-void
9292-__removefile_randomize_buffer(unsigned char *buffer, size_t length, removefile_state_t state) {
9393- size_t i;
9494-9595-#ifdef USE_ARC4RANDOM
9696- u_int32_t *p = (u_int32_t *)buffer;
9797- u_int32_t mod4length = length - (length % 4);
9898-9999- for (i = 0; i < mod4length; i += 4) {
100100- *p++ = arc4random();
101101- }
102102-103103- while (i < length) {
104104- buffer[i++] = arc4random();
105105- }
106106- state->random_bytes_read += (mod4length + ((length - mod4length) * 4));
107107- if (state->random_bytes_read > 512*1024*1024 /* RESEED_BYTES */) {
108108- state->random_bytes_read = 0;
109109- seed_random(state);
110110- }
111111-#else
112112- if (state->urand_file != -1) {
113113- read(state->urand_file, buffer, length);
114114- } else {
115115- for (i = 0; i < length; i++)
116116- buffer[i] = rand();
117117- }
118118-#endif
119119-}
-121
src/libremovefile/removefile_rename_unlink.c
···11-/* srm */
22-/* Copyright (c) 2000 Matthew D. Gauthier
33- * Portions copyright (c) 2007 Apple Inc. All rights reserved.
44- *
55- * Permission is hereby granted, free of charge, to any person obtaining
66- * a copy of this software and associated documentation files (the
77- * "Software"), to deal in the Software without restriction, including
88- * without limitation the rights to use, copy, modify, merge, publish,
99- * distribute, sublicense, and/or sell copies of the Software, and to
1010- * permit persons to whom the Software is furnished to do so, subject to
1111- * the following conditions:
1212- *
1313- * The above copyright notice and this permission notice shall be
1414- * included in all copies or substantial portions of the Software.
1515- *
1616- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1717- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1818- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1919- * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2020- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2121- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2222- * OTHER DEALINGS IN THE SOFTWARE.
2323- *
2424- * Except as contained in this notice, the name of the contributors shall
2525- * not be used in advertising or otherwise to promote the sale, use or
2626- * other dealings in this Software without prior written authorization.
2727- */
2828-2929-#include <ctype.h>
3030-#include <dirent.h>
3131-#include <errno.h>
3232-#include <stdlib.h>
3333-#include <stdio.h>
3434-#include <string.h>
3535-#include <sys/stat.h>
3636-#include <unistd.h>
3737-3838-#include <TargetConditionals.h>
3939-4040-#include "removefile.h"
4141-#include "removefile_priv.h"
4242-4343-static int empty_directory(const char *path) {
4444- DIR *dp;
4545- struct dirent *de;
4646-4747- dp = opendir(path);
4848- if (dp == NULL) {
4949- return -1;
5050- }
5151- while ((de = readdir(dp)) != NULL) {
5252- if (de->d_namlen < 3 && (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))) {
5353- continue;
5454- }
5555- (void)closedir(dp);
5656- return -1;
5757- }
5858- (void)closedir(dp);
5959- return 0;
6060-}
6161-6262-int
6363-__removefile_rename_unlink(const char *path, removefile_state_t state) {
6464- char *p, c;
6565- struct stat statbuf;
6666-6767- size_t new_name_size = strlen(path) + 15;
6868- char new_name[new_name_size];
6969- int i = 0;
7070-7171- strlcpy(new_name, path, new_name_size);
7272-7373- if ( (p = strrchr(new_name, '/')) != NULL ) {
7474- p++;
7575- *p = '\0';
7676- } else {
7777- p = new_name;
7878- }
7979-8080- do {
8181- i = 0;
8282-8383- while (i < 14) {
8484- c = __removefile_random_char(state);
8585- if (isalnum((int) c)) {
8686- p[i] = c;
8787- i++;
8888- }
8989- }
9090- p[i] = '\0';
9191- } while (lstat(new_name, &statbuf) == 0);
9292-9393- if (lstat(path, &statbuf) == -1)
9494- return -1;
9595-9696-#if __APPLE__
9797- if (S_ISDIR(statbuf.st_mode) && (statbuf.st_flags & SF_DATALESS) != 0) {
9898- return unlinkat(AT_FDCWD, path, AT_REMOVEDIR_DATALESS);
9999- }
100100-#endif
101101-102102- if (S_ISDIR(statbuf.st_mode) && (empty_directory(path) == -1)) {
103103- /* Directory isn't empty (e.g. because it contains an immutable file).
104104- Attempting to remove it will fail, so avoid renaming it. */
105105- errno = ENOTEMPTY;
106106- return -1;
107107- }
108108-109109- if (rename(path, new_name) == -1)
110110- return -1;
111111-112112- if (lstat(new_name, &statbuf) == -1) {
113113- errno = ENOENT;
114114- return -1;
115115- }
116116-117117- if (S_ISDIR(statbuf.st_mode))
118118- return rmdir(new_name);
119119-120120- return unlink(new_name);
121121-}
-456
src/libremovefile/removefile_sunlink.c
···11-/* srm */
22-/* Copyright (c) 2000 Matthew D. Gauthier
33- * Portions copyright (c) 2007 Apple Inc. All rights reserved.
44- *
55- * Permission is hereby granted, free of charge, to any person obtaining
66- * a copy of this software and associated documentation files (the
77- * "Software"), to deal in the Software without restriction, including
88- * without limitation the rights to use, copy, modify, merge, publish,
99- * distribute, sublicense, and/or sell copies of the Software, and to
1010- * permit persons to whom the Software is furnished to do so, subject to
1111- * the following conditions:
1212- *
1313- * The above copyright notice and this permission notice shall be
1414- * included in all copies or substantial portions of the Software.
1515- *
1616- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1717- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1818- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1919- * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2020- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2121- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2222- * OTHER DEALINGS IN THE SOFTWARE.
2323- *
2424- * Except as contained in this notice, the name of the contributors shall
2525- * not be used in advertising or otherwise to promote the sale, use or
2626- * other dealings in this Software without prior written authorization.
2727- */
2828-2929-#include <errno.h>
3030-#include <fcntl.h>
3131-#include <stdarg.h>
3232-#include <stdio.h>
3333-#include <stdlib.h>
3434-#include <string.h>
3535-#include <sys/ioctl.h>
3636-#include <sys/stat.h>
3737-#include <sys/types.h>
3838-#include <sys/mount.h>
3939-#include <time.h>
4040-#include <unistd.h>
4141-4242-#if HAVE_LINUX_EXT2_FS_H
4343-#include <linux/ext2_fs.h>
4444-#endif
4545-4646-#if HAVE_SYS_VFS_H
4747-#include <sys/vfs.h>
4848-#endif
4949-5050-#if HAVE_SYS_PARAM_H && HAVE_SYS_MOUNT_H
5151-#include <sys/param.h>
5252-#include <sys/mount.h>
5353-#endif
5454-5555-#if __APPLE__
5656-#include <sys/disk.h>
5757-#endif
5858-5959-#if HAVE_CHFLAGS
6060-/* define unsupported flags as 0 */
6161-# if !defined UF_IMMUTABLE
6262-# define UF_IMMUTABLE 0
6363-# endif
6464-# if !defined UF_APPEND
6565-# define UF_APPEND 0
6666-# endif
6767-# if !defined UF_NOUNLINK
6868-# define UF_NOUNLINK 0
6969-# endif
7070-# if !defined SF_IMMUTABLE
7171-# define SF_IMMUTABLE 0
7272-# endif
7373-# if !defined SF_APPEND
7474-# define SF_APPEND 0
7575-# endif
7676-# if !defined SF_NOUNLINK
7777-# define SF_NOUNLINK 0
7878-# endif
7979-#endif
8080-8181-#include "removefile.h"
8282-#include "removefile_priv.h"
8383-8484-static int
8585-init_write_buffer(struct stat *statbuf, struct statfs *fs_stats, removefile_state_t state) {
8686- u_int32_t tmp_buffsize;
8787-8888- state->file_size = statbuf->st_size;
8989- state->buffsize = statbuf->st_blksize;
9090-9191-#if HAVE_SYS_PARAM_H
9292- /* try to determine an optimal write buffer size */
9393- state->buffsize = (u_int32_t)(statbuf->st_size / statbuf->st_blksize) * statbuf->st_blksize;
9494- if ((statbuf->st_size % statbuf->st_blksize) != 0) {
9595- /* add full size of last block */
9696- state->buffsize += statbuf->st_blksize;
9797- } else if (state->buffsize < statbuf->st_blksize) {
9898- /* no smaller than one device block */
9999- state->buffsize = statbuf->st_blksize;
100100- }
101101- tmp_buffsize = MAXBSIZE;
102102- if (state->buffsize > tmp_buffsize) {
103103- /* no larger than the largest file system buffer size */
104104- state->buffsize = tmp_buffsize;
105105- }
106106-#endif
107107-108108- /* Allocated buffer must be at least 2 bytes larger than logical buffsize.
109109- This lets us align repeating 3-byte patterns across multiple buffer
110110- writes by using a variable offset (0..2) from the start of the buffer. */
111111-112112- tmp_buffsize = state->buffsize + 4;
113113-114114- if (state->buffer) {
115115- if (tmp_buffsize > state->allocated_buffsize) {
116116- free(state->buffer);
117117- state->buffer = NULL;
118118- } else {
119119- return 0; /* use existing buffer */
120120- }
121121- }
122122- if ((state->buffer = (unsigned char *)malloc(tmp_buffsize)) == NULL) {
123123- errno = ENOMEM;
124124- return -1;
125125- }
126126- state->allocated_buffsize = tmp_buffsize;
127127- return 0;
128128-}
129129-130130-static void
131131-flush(int fd) {
132132- /* force buffered writes to be flushed to disk */
133133-#if defined F_FULLFSYNC
134134- /* F_FULLFSYNC is equivalent to fsync plus device flush to media */
135135- if (fcntl(fd, F_FULLFSYNC, NULL) != 0) {
136136- /* we're not on a fs that supports this; fall back to plain fsync */
137137- fsync(fd);
138138- }
139139-#elif HAVE_FDATASYNC
140140- fdatasync(fd);
141141-#else
142142- fsync(fd);
143143-#endif
144144-}
145145-146146-static unsigned char *align_buffer(unsigned char *buf, off_t pos) {
147147- /* return a pointer to the start of the buffer which should be written,
148148- offset from the given buffer by 0, 1, or 2 bytes, so that the 3-byte
149149- pattern which the buffer contains is aligned with the previous write. */
150150- return (unsigned char *)((uintptr_t)buf + (unsigned int)(pos % 3));
151151-}
152152-153153-#if 0 /* UNUSED */
154154-void verification_failure(off_t count) {
155155- if (sizeof(off_t) == 4)
156156- printf("warning: failed to verify write at offset %d\n", count);
157157- else if (sizeof(off_t) == 8)
158158- printf("warning: failed to verify write at offset %lld\n", count);
159159- else
160160- printf("warning: previous write failed to verify!\n");
161161- fflush(stdout);
162162-}
163163-#endif /* UNUSED */
164164-165165-static void
166166-overwrite(int stage, removefile_state_t state) {
167167- ssize_t i;
168168- off_t count = 0;
169169- unsigned char *buffptr = state->buffer;
170170-171171- // break out of the function early if cancel is detected
172172- if (__removefile_state_test_cancel(state)) return;
173173-174174- lseek(state->file, 0, SEEK_SET);
175175- while (count < state->file_size - state->buffsize) {
176176- if (stage == 1 /* W_RANDOM */) {
177177- __removefile_randomize_buffer(state->buffer, state->buffsize, state);
178178- } else if (stage == 2 /* W_TRIPLE */) {
179179- buffptr = align_buffer(state->buffer, count);
180180- }
181181- i = write(state->file, buffptr, state->buffsize);
182182- if (i > 0)
183183- count += i;
184184-185185- // break out of the loop early if cancel is detected
186186- if (__removefile_state_test_cancel(state)) return;
187187- }
188188- if (stage == 1 /* W_RANDOM */) {
189189- __removefile_randomize_buffer(state->buffer, (size_t)(state->file_size - count), state);
190190- } else if (stage == 2 /* W_TRIPLE */) {
191191- buffptr = align_buffer(state->buffer, count);
192192- }
193193- i = write(state->file, buffptr, (size_t)(state->file_size - count));
194194- /*
195195- * Only flush the data if we're doing more than one pass of writes.
196196- */
197197- if ((state->unlink_flags & (REMOVEFILE_SECURE_7_PASS | REMOVEFILE_SECURE_35_PASS | REMOVEFILE_SECURE_3_PASS)) != 0)
198198- flush(state->file);
199199- lseek(state->file, 0, SEEK_SET);
200200-}
201201-202202-static void
203203-overwrite_random(int num_passes, removefile_state_t state) {
204204- int i;
205205-206206- for (i = 0; i < num_passes; i++) {
207207- overwrite(1 /* W_RANDOM */, state);
208208- }
209209-}
210210-211211-static void
212212-overwrite_byte(int byte, removefile_state_t state) {
213213- memset(state->buffer, byte, state->buffsize);
214214- overwrite(0 /* W_SINGLE */, state);
215215-}
216216-217217-static void
218218-overwrite_bytes(unsigned int byte1, unsigned int byte2, unsigned int byte3, removefile_state_t state) {
219219- u_int32_t val[3], *p = (u_int32_t *)state->buffer;
220220- unsigned int i, mod12buffsize = state->allocated_buffsize - (state->allocated_buffsize % 12);
221221-222222- val[0] = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte1;
223223- val[1] = (byte2 << 24) | (byte3 << 16) | (byte1 << 8) | byte2;
224224- val[2] = (byte3 << 24) | (byte1 << 16) | (byte2 << 8) | byte3;
225225-226226- /* fill buffer 12 bytes at a time, optimized for 4-byte alignment */
227227- for (i = 0; i < mod12buffsize; i += 12) {
228228- *p++ = val[0];
229229- *p++ = val[1];
230230- *p++ = val[2];
231231- }
232232- while (i < state->allocated_buffsize) {
233233- state->buffer[i] = ((unsigned char *)&val[0])[i % 3];
234234- i++;
235235- }
236236- overwrite(2 /* W_TRIPLE */, state);
237237-}
238238-239239-static void
240240-overwrite_file(removefile_state_t state) {
241241- if (state->unlink_flags & REMOVEFILE_SECURE_35_PASS) {
242242- /* Gutmann 35-pass overwrite */
243243- overwrite_random(4, state);
244244- overwrite_byte(0x55, state);
245245- overwrite_byte(0xAA, state);
246246- overwrite_bytes(0x92, 0x49, 0x24, state);
247247- overwrite_bytes(0x49, 0x24, 0x92, state);
248248- overwrite_bytes(0x24, 0x92, 0x49, state);
249249- overwrite_byte(0x00, state);
250250- overwrite_byte(0x11, state);
251251- overwrite_byte(0x22, state);
252252- overwrite_byte(0x33, state);
253253- overwrite_byte(0x44, state);
254254- overwrite_byte(0x55, state);
255255- overwrite_byte(0x66, state);
256256- overwrite_byte(0x77, state);
257257- overwrite_byte(0x88, state);
258258- overwrite_byte(0x99, state);
259259- overwrite_byte(0xAA, state);
260260- overwrite_byte(0xBB, state);
261261- overwrite_byte(0xCC, state);
262262- overwrite_byte(0xDD, state);
263263- overwrite_byte(0xEE, state);
264264- overwrite_byte(0xFF, state);
265265- overwrite_bytes(0x92, 0x49, 0x24, state);
266266- overwrite_bytes(0x49, 0x24, 0x92, state);
267267- overwrite_bytes(0x24, 0x92, 0x49, state);
268268- overwrite_bytes(0x6D, 0xB6, 0xDB, state);
269269- overwrite_bytes(0xB6, 0xDB, 0x6D, state);
270270- overwrite_bytes(0xDB, 0x6D, 0xB6, state);
271271- overwrite_random(4, state);
272272- } else if (state->unlink_flags & REMOVEFILE_SECURE_7_PASS) {
273273- /* DoD-compliant 7-pass overwrite */
274274- overwrite_byte(0xF6, state);
275275- overwrite_byte(0x00, state);
276276- overwrite_byte(0xFF, state);
277277- overwrite_random(1, state);
278278- overwrite_byte(0x00, state);
279279- overwrite_byte(0xFF, state);
280280- overwrite_random(1, state);
281281- } else if (state->unlink_flags & REMOVEFILE_SECURE_3_PASS) {
282282- /* DOE M2051-2 or DOD 5220.22-M */
283283- overwrite_random(2, state);
284284- overwrite_byte(0xAA, state);
285285- } else if (state->unlink_flags & REMOVEFILE_SECURE_1_PASS) {
286286- overwrite_random(1, state);
287287- } else if (state->unlink_flags & REMOVEFILE_SECURE_1_PASS_ZERO) {
288288- overwrite_byte(0, state);
289289- }
290290-}
291291-292292-int
293293-__removefile_sunlink(const char *path, removefile_state_t state) {
294294- struct stat statbuf;
295295- struct statfs fs_stats;
296296-#if HAVE_LINUX_EXT2_FS_H
297297- int flags = 0;
298298-#endif
299299- int fmode = O_WRONLY;
300300- struct flock flock;
301301-302302- if (lstat(path, &statbuf) == -1)
303303- return -1;
304304- if (!S_ISREG(statbuf.st_mode))
305305- return __removefile_rename_unlink(path, state);
306306- if (statbuf.st_nlink > 1) {
307307- return __removefile_rename_unlink(path, state);
308308- }
309309-310310- if ( (state->file = open(path, fmode)) == -1) /* BSD doesn't support O_SYNC */
311311- return -1;
312312- if (fcntl(state->file, F_WRLCK, &flock) == -1) {
313313- close(state->file);
314314- state->file = -1;
315315- return -1;
316316- }
317317-318318- if (fstatfs(state->file, &fs_stats) == -1 && errno != ENOSYS) {
319319- close(state->file);
320320- state->file = -1;
321321- return -1;
322322- }
323323-324324-#if HAVE_LINUX_EXT2_FS_H
325325- if (fs_stats.f_type == EXT2_SUPER_MAGIC)
326326- if (ioctl(state->file, EXT2_IOC_GETFLAGS, &flags) == -1) {
327327- close(state->file);
328328- state->file = -1;
329329- return -1;
330330- }
331331-332332- if ( (flags & EXT2_UNRM_FL) || (flags & EXT2_IMMUTABLE_FL) ||
333333- (flags & EXT2_APPEND_FL) )
334334- {
335335- close(state->file);
336336- state->file = -1;
337337- errno = EPERM;
338338- return -1;
339339- }
340340-341341-#endif /* HAVE_LINUX_EXT2_FS_H */
342342-343343-/* chflags(2) turns out to be a different system call in every BSD
344344- derivative. The important thing is to make sure we'll be able to
345345- unlink it after we're through messing around. Unlinking it first
346346- would remove the need for any of these checks, but would leave the
347347- user with no way to overwrite the file if the process was
348348- interrupted during the overwriting. So, instead we assume that the
349349- open() above will fail on immutable and append-only files and try
350350- and catch only platforms supporting NOUNLINK here.
351351-352352- FreeBSD - supports NOUNLINK (from 4.4 on?)
353353- MacOS X - doesn't support NOUNLINK (as of 10.3.5)
354354- OpenBSD - doesn't support NOUNLINK (as of 3.1)
355355- Tru64 - unknown
356356-357357- Note: unsupported flags are defined as 0 at the top of this file,
358358- so a specific platform check is not required here.
359359-*/
360360-361361-#if HAVE_CHFLAGS
362362- if ((statbuf.st_flags & UF_IMMUTABLE) ||
363363- (statbuf.st_flags & UF_APPEND) ||
364364- (statbuf.st_flags & UF_NOUNLINK) ||
365365- (statbuf.st_flags & SF_IMMUTABLE) ||
366366- (statbuf.st_flags & SF_APPEND) ||
367367- (statbuf.st_flags & SF_NOUNLINK))
368368- {
369369- close(state->file);
370370- state->file = -1;
371371- errno = EPERM;
372372- return -1;
373373- }
374374-#endif /* HAVE_CHFLAGS */
375375-376376- if (init_write_buffer(&statbuf, &fs_stats, state) == -1) {
377377- close(state->file);
378378- state->file = -1;
379379- return -1;
380380- }
381381-#if defined F_NOCACHE
382382- /* before performing file I/O, set F_NOCACHE to prevent caching */
383383- (void)fcntl(state->file, F_NOCACHE, 1);
384384-#endif
385385- overwrite_file(state);
386386-#if HAVE_LINUX_EXT2_FS_H
387387- ioctl(state->file, EXT2_IOC_SETFLAGS, EXT2_SECRM_FL);
388388-#endif
389389-390390- close(state->file);
391391- state->file = -1;
392392-#if __APPLE__
393393- /* Also overwrite the file's resource fork, if present. */
394394- {
395395- static const char *RSRCFORKSPEC = "/..namedfork/rsrc";
396396- off_t rsrc_fork_size;
397397- size_t rsrc_path_size = strlen(path) + strlen(RSRCFORKSPEC) + 1;
398398- char *rsrc_path = (char *)alloca(rsrc_path_size);
399399- if (rsrc_path == NULL) {
400400- errno = ENOMEM;
401401- return -1;
402402- }
403403- if (snprintf(rsrc_path, MAXPATHLEN,
404404- "%s%s", path, RSRCFORKSPEC ) > MAXPATHLEN - 1) {
405405- errno = ENAMETOOLONG;
406406- return -1;
407407- }
408408-409409- if (lstat(rsrc_path, &statbuf) != 0) {
410410- int err = errno;
411411- if (err == ENOENT || err == ENOTDIR) {
412412- rsrc_fork_size = 0;
413413- } else {
414414- return -1;
415415- }
416416- } else {
417417- rsrc_fork_size = statbuf.st_size;
418418- }
419419-420420- if (rsrc_fork_size > 0) {
421421-422422- if ((state->file = open(rsrc_path, O_WRONLY)) == -1) {
423423- return -1;
424424- }
425425- if (fcntl(state->file, F_WRLCK, &flock) == -1) {
426426- close(state->file);
427427- state->file = -1;
428428- return -1;
429429- }
430430-431431- if (init_write_buffer(&statbuf, &fs_stats, state) == -1) {
432432- close(state->file);
433433- state->file = -1;
434434- return -1;
435435- }
436436-437437- #if defined F_NOCACHE
438438- /* before performing file I/O, set F_NOCACHE to prevent caching */
439439- (void)fcntl(state->file, F_NOCACHE, 1);
440440- #endif
441441-442442- overwrite_file(state);
443443-444444- close(state->file);
445445- state->file = -1;
446446- }
447447- }
448448-#endif /* __APPLE__ */
449449-450450- if (__removefile_state_test_cancel(state)) {
451451- errno = ECANCELED;
452452- return -1;
453453- }
454454-455455- return __removefile_rename_unlink(path, state);
456456-}
-259
src/libremovefile/removefile_tree_walker.c
···11-/* srm */
22-/* Copyright (c) 2000 Matthew D. Gauthier
33- * Portions copyright (c) 2015 Apple Inc. All rights reserved.
44- *
55- * Permission is hereby granted, free of charge, to any person obtaining
66- * a copy of this software and associated documentation files (the
77- * "Software"), to deal in the Software without restriction, including
88- * without limitation the rights to use, copy, modify, merge, publish,
99- * distribute, sublicense, and/or sell copies of the Software, and to
1010- * permit persons to whom the Software is furnished to do so, subject to
1111- * the following conditions:
1212- *
1313- * The above copyright notice and this permission notice shall be
1414- * included in all copies or substantial portions of the Software.
1515- *
1616- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1717- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1818- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1919- * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2020- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2121- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2222- * OTHER DEALINGS IN THE SOFTWARE.
2323- *
2424- * Except as contained in this notice, the name of the contributors shall
2525- * not be used in advertising or otherwise to promote the sale, use or
2626- * other dealings in this Software without prior written authorization.
2727- */
2828-2929-#include <errno.h>
3030-#include <fcntl.h>
3131-#include <stdlib.h>
3232-#include <stdio.h>
3333-#include <string.h>
3434-#include <sys/resource.h>
3535-#include <sys/stat.h>
3636-#include <sys/types.h>
3737-#include <unistd.h>
3838-#include <fts.h>
3939-4040-#include "removefile.h"
4141-#include "removefile_priv.h"
4242-4343-static int
4444-__removefile_process_file(FTS* stream, FTSENT* current_file, removefile_state_t state) {
4545- int res = 0;
4646- char* path = current_file->fts_path;
4747-4848- int recursive = state->unlink_flags & REMOVEFILE_RECURSIVE;
4949- int keep_parent = state->unlink_flags & REMOVEFILE_KEEP_PARENT;
5050- int secure = state->unlink_flags & (REMOVEFILE_SECURE_7_PASS | REMOVEFILE_SECURE_35_PASS | REMOVEFILE_SECURE_1_PASS | REMOVEFILE_SECURE_3_PASS | REMOVEFILE_SECURE_1_PASS_ZERO);
5151-5252- switch (current_file->fts_info) {
5353- // attempt to unlink the directory on pre-order in case it is
5454- // a directory hard-link. If we succeed, it was a hard-link
5555- // and we should not descend any further.
5656- case FTS_D:
5757- if (unlink(path) == 0) {
5858- fts_set(stream, current_file, FTS_SKIP);
5959- }
6060- break;
6161- case FTS_DC:
6262- state->error_num = ELOOP;
6363- res = -1;
6464- break;
6565- case FTS_DNR:
6666- case FTS_ERR:
6767- case FTS_NS:
6868- state->error_num = current_file->fts_errno;
6969- res = -1;
7070- break;
7171- case FTS_DP:
7272- if (recursive &&
7373- (!keep_parent ||
7474- current_file->fts_level != FTS_ROOTLEVEL)) {
7575- if (secure) {
7676- res = __removefile_rename_unlink(path,
7777- state);
7878- } else {
7979- if (geteuid() == 0 &&
8080- (current_file->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
8181- !(current_file->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
8282- chflags(path, current_file->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0) {
8383- errno = EACCES;
8484- res = -1;
8585- } else {
8686-#if __APPLE__
8787- int is_dataless = (current_file->fts_statp->st_flags & SF_DATALESS) != 0;
8888- if (is_dataless) {
8989- int iopolicy = getiopolicy_np(IOPOL_TYPE_VFS_MATERIALIZE_DATALESS_FILES, IOPOL_SCOPE_THREAD);
9090- int non_materializing = iopolicy == IOPOL_MATERIALIZE_DATALESS_FILES_OFF;
9191- if (non_materializing || state->confirm_callback == NULL) {
9292- res = unlinkat(AT_FDCWD, path, AT_REMOVEDIR_DATALESS);
9393- } else {
9494- res = rmdir(path);
9595- }
9696- } else {
9797- res = rmdir(path);
9898- }
9999-#else
100100- res = rmdir(path);
101101-#endif
102102- }
103103- }
104104- if (res == -1) state->error_num = errno;
105105- }
106106- break;
107107- case FTS_F:
108108- case FTS_SL:
109109- case FTS_SLNONE:
110110- case FTS_DEFAULT:
111111- if (secure) {
112112- res = __removefile_sunlink(path, state);
113113- } else if (geteuid() == 0 &&
114114- (current_file->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
115115- !(current_file->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
116116- chflags(path, current_file->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0) {
117117- errno = EACCES;
118118- res = -1;
119119- } else {
120120- res = unlink(path);
121121- }
122122- if (res == -1) state->error_num = errno;
123123- break;
124124- case FTS_DOT:
125125- default:
126126- break;
127127- }
128128- return res;
129129-}
130130-131131-int
132132-__removefile_tree_walker(char **trees, removefile_state_t state) {
133133- FTSENT *current_file;
134134- FTS *stream;
135135- int rval = 0;
136136- int open_flags = 0;
137137-138138- removefile_callback_t cb_confirm = NULL;
139139- removefile_callback_t cb_status = NULL;
140140- removefile_callback_t cb_error = NULL;
141141-142142- cb_confirm = state->confirm_callback;
143143- cb_status = state->status_callback;
144144- cb_error = state->error_callback;
145145-146146- open_flags = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV;
147147-148148- /*
149149- * Don't cross a mount point when deleting recursively by default.
150150- * This default was changed in 10.11, previous to which there was
151151- * no way to prevent removefile from crossing mount points.
152152- * see: rdar://problem/6799948
153153- */
154154- if ((REMOVEFILE_CROSS_MOUNT & state->unlink_flags) != 0)
155155- open_flags &= ~FTS_XDEV;
156156-157157- stream = fts_open(trees, open_flags, NULL);
158158- if (stream == NULL) {
159159- state->error_num = errno;
160160- return -1;
161161- }
162162-163163- while ((current_file = fts_read(stream)) != NULL) {
164164- int res = REMOVEFILE_PROCEED;
165165-166166- /*
167167- * fts_number is set to REMOVEFILE_SKIP for directories where
168168- * the confirmation callback has asked to skip it. We check
169169- * this on post-order, so we don't remove an empty directory that
170170- * the caller wanted preserved.
171171- */
172172- if (current_file->fts_info == FTS_DP &&
173173- current_file->fts_number == REMOVEFILE_SKIP) {
174174- current_file->fts_number = 0;
175175- continue;
176176- }
177177-178178- /* Setting FTS_XDEV skips the mountpoint on pre-order traversal,
179179- * but you have to manually hop over it on post-order or
180180- * removefile will return an error.
181181- */
182182- if (current_file->fts_info == FTS_DP &&
183183- stream->fts_options & FTS_XDEV &&
184184- stream->fts_dev != current_file->fts_dev) {
185185- continue;
186186- }
187187-188188- // don't process the file if a cancel has been requested
189189- if (__removefile_state_test_cancel(state)) break;
190190-191191- // confirm regular files and directories in pre-order
192192- if (cb_confirm && current_file->fts_info != FTS_DP) {
193193- res = cb_confirm(state,
194194- current_file->fts_path, state->confirm_context);
195195- }
196196-197197- // don't process the file if a cancel has been requested
198198- // by the callback
199199- if (__removefile_state_test_cancel(state)) break;
200200-201201- if (res == REMOVEFILE_PROCEED) {
202202- state->error_num = 0;
203203- rval = __removefile_process_file(stream, current_file,
204204- state);
205205-206206- if (state->error_num != 0) {
207207- // Since removefile(3) is abstracting the
208208- // traversal of the directory tree, suppress
209209- // all ENOENT and ENOTDIR errors from the
210210- // calling process.
211211- // However, these errors should still be
212212- // reported for the ROOTLEVEL since those paths
213213- // were explicitly provided by the application.
214214- if ((state->error_num != ENOENT &&
215215- state->error_num != ENOTDIR) ||
216216- current_file->fts_level == FTS_ROOTLEVEL) {
217217- if (cb_error) {
218218- res = cb_error(state,
219219- current_file->fts_path,
220220- state->error_context);
221221- if (res == REMOVEFILE_PROCEED ||
222222- res == REMOVEFILE_SKIP) {
223223- rval = 0;
224224- } else if (res == REMOVEFILE_STOP) {
225225- rval = -1;
226226- }
227227- } else {
228228- res = REMOVEFILE_STOP;
229229- }
230230- }
231231- // show status for regular files and directories
232232- // in post-order
233233- } else if (cb_status &&
234234- current_file->fts_info != FTS_D) {
235235- res = cb_status(state, current_file->fts_path,
236236- state->status_context);
237237- }
238238- }
239239-240240- if (current_file->fts_info == FTS_D && res == REMOVEFILE_SKIP) {
241241- current_file->fts_number = REMOVEFILE_SKIP;
242242- }
243243-244244- if (res == REMOVEFILE_SKIP ||
245245- !(state->unlink_flags & REMOVEFILE_RECURSIVE))
246246- fts_set(stream, current_file, FTS_SKIP);
247247- if (res == REMOVEFILE_STOP ||
248248- __removefile_state_test_cancel(state))
249249- break;
250250- }
251251-252252- if (__removefile_state_test_cancel(state)) {
253253- state->error_num = ECANCELED;
254254- rval = -1;
255255- }
256256-257257- fts_close(stream);
258258- return rval;
259259-}