FreeBSD files modified for GNO, plus additional required support files.

This commit is contained in:
tribby 1999-05-27 00:27:20 +00:00
parent 46661a883e
commit e0806f3cbb
6 changed files with 917 additions and 0 deletions

12
bin/rm/Makefile Normal file
View File

@ -0,0 +1,12 @@
#
# This makefile is intended for use with dmake(1) on Apple IIGS
# $Id: Makefile,v 1.1 1999/05/27 00:27:20 tribby Exp $
#
# Created by Dave Tribby, May 1999
# Program name
PROG= rm
# Source files
SRCS= rm.c stat_flags.c
.INCLUDE : /src/gno/prog.mk

181
bin/rm/rm.1 Normal file
View File

@ -0,0 +1,181 @@
.\" Copyright (c) 1990, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 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
.\" SUCH DAMAGE.
.\"
.\" @(#)rm.1 8.2 (Berkeley) 4/18/94
.\" $Id: rm.1,v 1.1 1999/05/27 00:27:20 tribby Exp $
.\"
.TH RM 1 "May 1999" "GNO" "Commands and Applications"
.SH NAME
.BR rm
\- remove directory entries
.SH SYNOPSIS
.BR rm
.RB [ -f | -i ]
.RB [ -dPRr ]
.IR file ...
.SH DESCRIPTION
The
.BR rm
utility attempts to remove the non-directory type files specified on the
command line.
If the permissions of the file do not permit writing, and the standard
input device is a terminal, the user is prompted (on the standard error
output) for confirmation.
.PP
The options are as follows:
.IP \fB-d\fR
Attempt to remove directories as well as other types of files.
.IP \fB-f\fR
Attempt to remove the files without prompting for confirmation,
regardless of the file's permissions.
If the file does not exist, do not display a diagnostic message or modify
the exit status to reflect an error.
The
.BI -f
option overrides any previous
.BI -i
options.
.IP \fB-i\fR
Request confirmation before attempting to remove each file, regardless of
the file's permissions, or whether or not the standard input device is a
terminal.
The
.BI -i
option overrides any previous
.BI -f
options.
.IP \fB-P\fR
Overwrite regular files before deleting them.
Files are overwritten three times, first with the byte pattern 0xff,
then 0x00, and then 0xff again, before they are deleted.
.IP \fB-R\fR
Attempt to remove the file hierarchy rooted in each file argument.
The
.BI -R
option implies the
.BI -d
option.
If the
.BI -i
option is specified, the user is prompted for confirmation before
each directory's contents are processed (as well as before the attempt
is made to remove the directory).
If the user does not respond affirmatively, the file hierarchy rooted in
that directory is skipped.
.IP \fB-r\fR
Equivalent to
.BR -R .
.PP
It is an error to attempt to remove the files ``.'' and ``..''.
.PP
The
.BR rm
utility exits 0 if all of the named files or file hierarchies were removed,
or if the
.BI -f
option was specified and all of the existing files or file hierarchies were
removed.
If an error occurs,
.BR rm
exits with a value >0.
.SH NOTE
The
.BR rm
command uses
.BR getopt (3)
to parse its arguments, which allows it to accept
the
.BI --
option which will cause it to stop processing flag options at that
point. This will allow the removal of file names that begin
with a dash
.RB ( - ).
For example:
.nf
rm -- -filename
.fi
The same behavior can be obtained by using an absolute or relative
path reference. For example:
.nf
rm /home/user/-filename
rm ./-filename
.fi
This is useful for commands that do not use
.BR getopt (3)
to parse the command line arguments.
.SH SEE ALSO
.BR rmdir (1),
.BR unlink (2),
.BR fts (3),
.BR getopt (3)
.SH BUGS
The
.BI -P
option assumes that the underlying file system is a fixed-block file
system.
In addition, only regular files are overwritten, other types of files
are not.
.SH COMPATIBILITY
The
.BR rm
utility differs from historical implementations in that the
.BI -f
option only masks attempts to remove non-existent files instead of
masking a large variety of errors.
.PP
Also, historical
implementations prompted on the standard output,
not the standard error output.
.SH STANDARDS
The
.BR rm
command is expected to be
POSIX-2
compatible.
.SH VERSION
This manual page documents GNO
.BR rm
version 1.0.
.SH ATTRIBUTIONS
This command was ported from FreeBSD source code
for distribution with GNO/ME 2.0.6.
.SH HISTORY
This is the first version of
.BR rm
to be released with GNO.
Previously, the file removal function was accomplished
via an option to the
.BR cp
command.

515
bin/rm/rm.c Normal file
View File

@ -0,0 +1,515 @@
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 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
* SUCH DAMAGE.
*
* $Id: rm.c,v 1.1 1999/05/27 00:27:20 tribby Exp $
*/
/*
* Modified for GNO (Apple IIGS) by Dave Tribby, May 1999
*
* Constructs unacceptable to compiler are replaced using #ifndef __ORCAC__
*
* Changes not related to compiler are replaced using #ifndef __GNO__
*
* Added prototyped headers, surrounded by #ifndef __STDC__
*/
#ifndef __GNO__
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1990, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94";
#endif /* not lint */
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern char *flags_to_string __P((u_long, char *));
int dflag, eval, fflag, iflag, Pflag, stdin_ok;
uid_t uid;
int check __P((char *, char *, struct stat *));
void checkdot __P((char **));
void rm_file __P((char **));
void rm_overwrite __P((char *, struct stat *));
void rm_tree __P((char **));
void usage __P((void));
/* Interface to check on how much stack space a C program uses. */
#if defined(__GNO__) && defined(__STACK_CHECK__)
#ifndef _GNO_GNO_H_
#include <gno/gno.h>
/* WARNING: gno/gno.h includes types.h, which typedefs byte; this */
/* causes compiler errors later in this program when */
/* "byte" is used as PASS macro parameter. */
#endif
static void report_stack(void)
{
fprintf(stderr,"\n ==> %d stack bytes used <== \n", _endStackCheck());
}
#endif
/*
* rm --
* 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
* file removal.
*/
int
#ifndef __STDC__
main(argc, argv)
int argc;
char *argv[];
#else
main(int argc,
char *argv[])
#endif
{
int ch, rflag;
#if defined(__GNO__) && defined(__STACK_CHECK__)
_beginStackCheck();
atexit(report_stack);
#endif
rflag = 0;
while ((ch = getopt(argc, argv, "dfiPRr")) != EOF)
switch(ch) {
case 'd':
dflag = 1;
break;
case 'f':
fflag = 1;
iflag = 0;
break;
case 'i':
fflag = 0;
iflag = 1;
break;
case 'P':
Pflag = 1;
break;
case 'R':
case 'r': /* Compatibility. */
rflag = 1;
break;
default:
usage();
}
argc -= optind;
#ifndef __ORCAC__
argv += optind;
#else
argv = argv + optind;
#endif
if (argc < 1)
usage();
checkdot(argv);
if (!*argv)
exit (eval);
stdin_ok = isatty(STDIN_FILENO);
uid = geteuid();
if (rflag)
rm_tree(argv);
else
rm_file(argv);
exit (eval);
}
void
#ifndef __STDC__
rm_tree(argv)
char **argv;
#else
rm_tree(char **argv)
#endif
{
FTS *fts;
FTSENT *p;
int needstat;
int rval;
/*
* Remove a file hierarchy. If forcing removal (-f), or interactive
* (-i) or can't ask anyway (stdin_ok), don't stat the file.
*/
needstat = !uid || !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.
*/
#define SKIPPED 1
if (!(fts = fts_open(argv,
needstat ? FTS_PHYSICAL|FTS_NOCHDIR :
FTS_PHYSICAL|FTS_NOSTAT|FTS_NOCHDIR, (int (*)())NULL)))
err(1, NULL);
while ((p = fts_read(fts)) != NULL) {
switch (p->fts_info) {
case FTS_DNR:
if (!fflag || p->fts_errno != ENOENT) {
warnx("%s: %s",
p->fts_path, strerror(p->fts_errno));
eval = 1;
}
continue;
case FTS_ERR:
errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
case FTS_NS:
/*
* FTS_NS: assume that if can't stat the file, it
* can't be unlinked.
*/
if (!needstat)
break;
if (!fflag || p->fts_errno != ENOENT) {
warnx("%s: %s",
p->fts_path, strerror(p->fts_errno));
eval = 1;
}
continue;
case FTS_D:
/* Pre-order: give user chance to skip. */
if (iflag && !check(p->fts_path, p->fts_accpath,
p->fts_statp)) {
(void)fts_set(fts, p, FTS_SKIP);
p->fts_number = SKIPPED;
}
#ifndef __GNO__
else if (!uid &&
(p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
!(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
chflags(p->fts_accpath,
p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
goto err;
#endif
continue;
case FTS_DP:
/* Post-order: see if user skipped. */
if (p->fts_number == SKIPPED)
continue;
break;
}
if (!fflag &&
!check(p->fts_path, p->fts_accpath, p->fts_statp))
continue;
rval = 0;
#ifndef __GNO__
if (!uid &&
(p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
!(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
rval = chflags(p->fts_accpath,
p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
#endif
if (!rval) {
/*
* 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))
continue;
if (errno == ENOENT) {
if (fflag)
continue;
} else if (p->fts_info != FTS_DP)
warnx("%s: unable to read", p->fts_path);
} else {
if (Pflag)
rm_overwrite(p->fts_accpath, NULL);
if (!unlink(p->fts_accpath) || (fflag && errno == ENOENT))
continue;
}
}
err:
warn("%s", p->fts_path);
eval = 1;
}
if (errno)
err(1, "fts_read");
}
void
#ifndef __STDC__
rm_file(argv)
char **argv;
#else
rm_file(char **argv)
#endif
{
struct stat sb;
int df, rval;
char *f;
df = dflag;
/*
* Remove a file. POSIX 1003.2 states that, by default, attempting
* to remove a directory is an error, so must always stat the file.
*/
while ((f = *argv++) != NULL) {
/* Assume if can't stat the file, can't unlink it. */
if (lstat(f, &sb)) {
if (!fflag || errno != ENOENT) {
warn("%s", f);
eval = 1;
}
continue;
}
if (S_ISDIR(sb.st_mode) && !df) {
warnx("%s: is a directory", f);
eval = 1;
continue;
}
if (!fflag && !check(f, f, &sb))
continue;
rval = 0;
#ifndef __GNO__
if (!uid &&
(sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
!(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
#endif
if (!rval) {
if (S_ISDIR(sb.st_mode))
rval = rmdir(f);
else {
if (Pflag)
rm_overwrite(f, &sb);
rval = unlink(f);
}
}
if (rval && (!fflag || errno != ENOENT)) {
warn("%s", f);
eval = 1;
}
}
}
/*
* rm_overwrite --
* Overwrite the file 3 times with varying bit patterns.
*
* XXX
* This is a cheap way to *really* delete files. Note that only regular
* files are deleted, directories (and therefore names) will remain.
* Also, this assumes a fixed-block file system (like FFS, or a V7 or a
* System V file system). In a logging file system, you'll have to have
* kernel support.
*/
void
#ifndef __STDC__
rm_overwrite(file, sbp)
char *file;
struct stat *sbp;
#else
rm_overwrite(char *file, struct stat *sbp)
#endif
{
struct stat sb;
off_t len;
int fd, wlen;
#ifdef __GNO__
static
#endif
char buf[8 * 1024];
fd = -1;
if (sbp == NULL) {
if (lstat(file, &sb))
goto err;
sbp = &sb;
}
if (!S_ISREG(sbp->st_mode))
return;
#ifndef __GNO__
if ((fd = open(file, O_WRONLY, 0)) == -1)
#else /* GNO: 3rd parameter legal only when creating */
if ((fd = open(file, O_WRONLY)) == -1)
#endif
goto err;
#ifndef __GNO__
#define PASS(byte) { \
memset(buf, byte, sizeof(buf)); \
for (len = sbp->st_size; len > 0; len -= wlen) { \
wlen = len < sizeof(buf) ? len : sizeof(buf); \
if (write(fd, buf, wlen) != wlen) \
goto err; \
} \
}
#else
/* NOTE: parameter name changed from "byte" to "bval" to avoid conflict */
/* with typedef in types.h. */
#define PASS(bval) { \
memset(buf, bval, sizeof(buf)); \
for (len = sbp->st_size; len > 0; len -= wlen) { \
wlen = len < sizeof(buf) ? len : sizeof(buf); \
if (write(fd, buf, wlen) != wlen) \
goto err; \
} \
}
#endif
PASS(0xff);
if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
goto err;
PASS(0x00);
if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
goto err;
PASS(0xff);
if (!fsync(fd) && !close(fd))
return;
err: eval = 1;
warn("%s", file);
}
int
#ifndef __STDC__
check(path, name, sp)
char *path, *name;
struct stat *sp;
#else
check(char *path, char *name, struct stat *sp)
#endif
{
int ch, first;
#ifdef __GNO__
static
#endif
char modep[15], flagsp[128];
/* Check -i first. */
if (iflag)
(void)fprintf(stderr, "remove %s? ", path);
else {
/*
* 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. Check stdin_ok
* first because we may not have stat'ed the file.
*/
#ifndef __GNO__
if (!stdin_ok || S_ISLNK(sp->st_mode) ||
!access(name, W_OK) &&
!(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
(!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid))
return (1);
strmode(sp->st_mode, modep);
strcpy(flagsp, flags_to_string(sp->st_flags, NULL));
if (*flagsp)
strcat(flagsp, " ");
(void)fprintf(stderr, "override %s%s%s/%s %sfor %s? ",
modep + 1, modep[9] == ' ' ? "" : " ",
user_from_uid(sp->st_uid, 0),
group_from_gid(sp->st_gid, 0),
*flagsp ? flagsp : "",
path);
#else
if (!stdin_ok || !access(name,W_OK))
return (1);
(void)fprintf(stderr, "override protection for %s? ",
path);
#endif
}
(void)fflush(stderr);
first = ch = getchar();
while (ch != '\n' && ch != EOF)
ch = getchar();
return (first == 'y' || first == 'Y');
}
#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
void
#ifndef __STDC__
checkdot(argv)
char **argv;
#else
checkdot(char **argv)
#endif
{
char *p, **save, **t;
int complained;
complained = 0;
for (t = argv; *t;) {
if ((p = strrchr(*t, '/')) != NULL)
++p;
else
p = *t;
if (ISDOT(p)) {
if (!complained++)
warnx("\".\" and \"..\" may not be removed");
eval = 1;
for (save = t; (t[0] = t[1]) != NULL; ++t);
t = save;
} else
++t;
}
}
void
#ifndef __STDC__
usage()
#else
usage(void)
#endif
{
(void)fprintf(stderr, "usage: rm [-f | -i] [-dPRr] file ...\n");
exit(1);
}

9
bin/rm/rm.desc Normal file
View File

@ -0,0 +1,9 @@
Name: rm
Version: 1.0 (May 1999)
Shell: GNO
Author: Dave Tribby (from FreeBSD code)
Contact: tribby@cup.hp.com
Where: /bin
FTP: ftp/gno/org ground.icaen.uiowa.edu apple2.caltech.edu
Remove directory entries

30
bin/rm/rm.rez Normal file
View File

@ -0,0 +1,30 @@
/*
* Resources for version and comment
* $Id $
*/
#define PROG "rm"
#define DESC "Remove directory entries."
#include "Types.rez"
/*
* Version
*/
resource rVersion (1, purgeable3) {
{ 1, 0, 0, /* Version 1.0.0 */
release, /* development|alpha|beta|final|release */
0 }, /* non-final release number */
verUS, /* Country */
PROG, /* Program name */
DESC " Released with GNO/ME."
};
/*
* Comment
*/
resource rComment (1, purgeable3) {
PROG " v1.0 (May 1999)\n"
"GNO utility: " DESC "\n"
"Ported from FreeBSD code by Dave Tribby."
};

170
bin/rm/stat.flags.c Normal file
View File

@ -0,0 +1,170 @@
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 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
* SUCH DAMAGE.
*
* $Id: stat.flags.c,v 1.1 1999/05/27 00:27:20 tribby Exp $
*/
/*
* Modified for GNO (Apple IIGS) by Dave Tribby, May 1999
*
* Constructs unacceptable to compiler are replaced using #ifndef __ORCAC__
*
* Changes not related to compiler are replaced using #ifndef __GNO__
*
* Added prototyped headers, surrounded by #ifndef __STDC__
*/
#ifndef __GNO__
#ifndef lint
static char sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93";
#endif /* not lint */
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <stddef.h>
#include <string.h>
#define SAPPEND(s) { \
if (prefix != NULL) \
(void)strcat(string, prefix); \
(void)strcat(string, s); \
prefix = ","; \
}
/*
* flags_to_string --
* Convert stat flags to a comma-separated string. If no flags
* are set, return the default string.
*/
char *
#ifndef __STDC__
flags_to_string(flags, def)
u_long flags;
char *def;
#else
flags_to_string(u_long flags, char *def)
#endif
{
static char string[128];
char *prefix;
string[0] = '\0';
prefix = NULL;
if (flags & UF_APPEND)
SAPPEND("uappnd");
if (flags & UF_IMMUTABLE)
SAPPEND("uchg");
if (flags & UF_NODUMP)
SAPPEND("nodump");
if (flags & SF_APPEND)
SAPPEND("sappnd");
if (flags & SF_ARCHIVED)
SAPPEND("arch");
if (flags & SF_IMMUTABLE)
SAPPEND("schg");
return (prefix == NULL && def != NULL ? def : string);
}
#define TEST(a, b, f) { \
if (!memcmp(a, b, sizeof(b))) { \
if (clear) { \
if (clrp) \
*clrp |= (f); \
} else if (setp) \
*setp |= (f); \
break; \
} \
}
/*
* string_to_flags --
* Take string of arguments and return stat flags. Return 0 on
* success, 1 on failure. On failure, stringp is set to point
* to the offending token.
*/
int
#ifndef __STDC__
string_to_flags(stringp, setp, clrp)
char **stringp;
u_long *setp, *clrp;
#else
string_to_flags(char **stringp, u_long *setp, u_long *clrp)
#endif
{
int clear;
char *string, *p;
clear = 0;
if (setp)
*setp = 0;
if (clrp)
*clrp = 0;
string = *stringp;
while ((p = strsep(&string, "\t ,")) != NULL) {
*stringp = p;
if (*p == '\0')
continue;
if (p[0] == 'n' && p[1] == 'o') {
clear = 1;
p += 2;
}
switch (p[0]) {
case 'a':
TEST(p, "arch", SF_ARCHIVED);
TEST(p, "archived", SF_ARCHIVED);
return (1);
case 'd':
clear = !clear;
TEST(p, "dump", UF_NODUMP);
return (1);
case 's':
TEST(p, "sappnd", SF_APPEND);
TEST(p, "sappend", SF_APPEND);
TEST(p, "schg", SF_IMMUTABLE);
TEST(p, "schange", SF_IMMUTABLE);
TEST(p, "simmutable", SF_IMMUTABLE);
return (1);
case 'u':
TEST(p, "uappnd", UF_APPEND);
TEST(p, "uappend", UF_APPEND);
TEST(p, "uchg", UF_IMMUTABLE);
TEST(p, "uchange", UF_IMMUTABLE);
TEST(p, "uimmutable", UF_IMMUTABLE);
/* FALLTHROUGH */
default:
return (1);
}
}
return (0);
}