From e0806f3cbb90a1c6816450f37422f70a2c7b9e13 Mon Sep 17 00:00:00 2001 From: tribby Date: Thu, 27 May 1999 00:27:20 +0000 Subject: [PATCH] FreeBSD files modified for GNO, plus additional required support files. --- bin/rm/Makefile | 12 ++ bin/rm/rm.1 | 181 ++++++++++++++++ bin/rm/rm.c | 515 ++++++++++++++++++++++++++++++++++++++++++++ bin/rm/rm.desc | 9 + bin/rm/rm.rez | 30 +++ bin/rm/stat.flags.c | 170 +++++++++++++++ 6 files changed, 917 insertions(+) create mode 100644 bin/rm/Makefile create mode 100644 bin/rm/rm.1 create mode 100644 bin/rm/rm.c create mode 100644 bin/rm/rm.desc create mode 100644 bin/rm/rm.rez create mode 100644 bin/rm/stat.flags.c diff --git a/bin/rm/Makefile b/bin/rm/Makefile new file mode 100644 index 0000000..a81a8db --- /dev/null +++ b/bin/rm/Makefile @@ -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 diff --git a/bin/rm/rm.1 b/bin/rm/rm.1 new file mode 100644 index 0000000..8b3626f --- /dev/null +++ b/bin/rm/rm.1 @@ -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. + diff --git a/bin/rm/rm.c b/bin/rm/rm.c new file mode 100644 index 0000000..f0a406e --- /dev/null +++ b/bin/rm/rm.c @@ -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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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 +/* 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); +} diff --git a/bin/rm/rm.desc b/bin/rm/rm.desc new file mode 100644 index 0000000..97d0d17 --- /dev/null +++ b/bin/rm/rm.desc @@ -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 diff --git a/bin/rm/rm.rez b/bin/rm/rm.rez new file mode 100644 index 0000000..75c1f81 --- /dev/null +++ b/bin/rm/rm.rez @@ -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." +}; diff --git a/bin/rm/stat.flags.c b/bin/rm/stat.flags.c new file mode 100644 index 0000000..05608b5 --- /dev/null +++ b/bin/rm/stat.flags.c @@ -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 +#include + +#include +#include + +#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); +}