* Copyright (c) 1990 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)rm.c 4.26 (Berkeley) 3/10/91";
int dflag
, fflag
, iflag
, retval
, stdin_ok
;
* This rm is different from historic rm's, but is expected to match
* POSIX 1003.2 behavior. The most visible difference is that -f
* has two specific effects now, ignore non-existent files and force
while ((ch
= getopt(argc
, argv
, "dfiRr")) != EOF
)
case 'r': /* compatibility */
stdin_ok
= isatty(STDIN_FILENO
);
* Remove a file hierarchy. If forcing removal (-f), or interactive
* (-i) or can't ask anyway (stdin_ok), don't stat the file.
needstat
= !fflag
&& !iflag
&& stdin_ok
;
* If the -i option is specified, the user can skip on the pre-order
* visit. The fts_number field flags skipped directories.
if (!(fts
= fts_open(argv
,
needstat
? FTS_PHYSICAL
: FTS_PHYSICAL
|FTS_NOSTAT
,
(void)fprintf(stderr
, "rm: %s.\n", strerror(errno
));
while (p
= fts_read(fts
)) {
error(p
->fts_path
, errno
);
* FTS_NS: assume that if can't stat the file, it can't be
if (!fflag
|| errno
!= ENOENT
)
error(p
->fts_path
, errno
);
/* Pre-order: give user chance to skip. */
if (iflag
&& !check(p
->fts_path
, p
->fts_accpath
,
(void)fts_set(fts
, p
, FTS_SKIP
);
/* Post-order: see if user skipped. */
if (p
->fts_number
== SKIPPED
)
!check(p
->fts_path
, p
->fts_accpath
, &p
->fts_statb
))
* If we can't read or search the directory, may still be
* able to remove it. Don't print out the un{read,search}able
* message unless the remove fails.
if (p
->fts_info
== FTS_DP
|| p
->fts_info
== FTS_DNR
) {
if (!rmdir(p
->fts_accpath
))
} else if (p
->fts_info
!= FTS_DP
)
"rm: unable to read %s.\n", p
->fts_path
);
} else if (!unlink(p
->fts_accpath
) || fflag
&& errno
== ENOENT
)
error(p
->fts_path
, errno
);
* Remove a file. POSIX 1003.2 states that, by default, attempting
* to remove a directory is an error, so must always stat the file.
/* Assume if can't stat the file, can't unlink it. */
if (!fflag
|| errno
!= ENOENT
)
if (S_ISDIR(sb
.st_mode
) && !df
) {
(void)fprintf(stderr
, "rm: %s: is a directory\n", f
);
if (!fflag
&& !check(f
, f
, &sb
))
if ((S_ISDIR(sb
.st_mode
) ? rmdir(f
) : unlink(f
)) &&
(!fflag
|| errno
!= ENOENT
))
char modep
[15], *user_from_uid(), *group_from_gid();
(void)fprintf(stderr
, "remove %s? ", path
);
* If it's not a symbolic link and it's unwritable and we're
* talking to a terminal, ask. Symbolic links are excluded
* because their permissions are meaningless.
if (S_ISLNK(sp
->st_mode
) || !stdin_ok
|| !access(name
, W_OK
))
strmode(sp
->st_mode
, modep
);
(void)fprintf(stderr
, "override %s%s%s/%s for %s? ",
modep
+ 1, modep
[9] == ' ' ? "" : " ",
user_from_uid(sp
->st_uid
, 0),
group_from_gid(sp
->st_gid
, 0), path
);
while (ch
!= '\n' && ch
!= EOF
)
#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || (a)[1] == '.' && !(a)[2]))
register char *p
, **t
, **save
;
"rm: \".\" and \"..\" may not be removed.\n");
for (save
= t
; t
[0] = t
[1]; ++t
);
(void)fprintf(stderr
, "rm: %s: %s.\n", name
, strerror(val
));
(void)fprintf(stderr
, "usage: rm [-dfiRr] file ...\n");