|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 3996 (0xf9c)
Types: TextFile
Notes: UNIX file
Names: »rmdir.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/rmdir.c«
/*
* rmdir -- remove directories
*/
#include <sys/stat.h>
#include <dir.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#define equal( s1, s2) (strcmp( s1, s2) == 0)
int fflag, /* force flag */
interrupted;
struct stat dot;
char *getparent(),
*getchild(),
*strncpy(),
*strcat(),
*strcpy(),
*concat();
/*
* main
* Interrupts are handled to prevent the formation of mangled directories.
*/
main( argc, argv)
register char **argv;
{
register int status = 0;
if (*++argv!= NULL && equal( *argv, "-f")) {
if (getuid())
fatal("only superuser can force");
++fflag;
++argv;
}
if (stat( ".", &dot))
fatal("can't find .");
catch(SIGINT);
catch(SIGHUP);
signal(SIGQUIT, SIG_IGN);
if (*argv == NULL) {
fprintf(stderr, "Usage: rmdir [ -f ] dir ...\n");
exit(1);
}
else
while (*argv) {
if (rmdir(*argv++) < 0)
status = 1; /* error */
if (interrupted)
exit(1);
}
exit(status);
}
/*
* remove a directory
* The directory and its "." and ".." entries are unlinked if everything
* looks kosher. The force option causes most checking to be suppressed
* and unlinks only what is specifically named. `rmdir' takes a dim view
* to non-hierarchical directories.
*/
rmdir(dir)
register char *dir;
{
register char *child;
register FILE *f;
struct stat s;
struct direct d;
if ((int) (child = getchild( dir)) < 0) {
error("can't get child dir name %s", dir);
return(-1);
}
if (access( dir, 0) || stat( dir, &s)) {
error("can't find %s", dir);
return(-1);
}
if ((s.st_mode&S_IFMT) != S_IFDIR) {
error("%s not a directory", dir);
return(-1);
}
if (access( getparent( dir), 3)) {
error("no permission to remove %s", dir);
return(-1);
}
if (fflag == 0) {
if (equal( child, ".") || equal( child, "..")) {
error("%s not allowed", dir);
return(-1);
}
if (s.st_ino==dot.st_ino && s.st_dev==dot.st_dev) {
error("but %s is your working directory", dir);
return(-1);
}
f = fopen( dir, "r");
if (f==NULL || access( dir, 4)) {
error("can't read %s", dir);
return(-1);
}
while (fread( &d, sizeof d, 1, f) == 1) {
if (d.d_ino == 0)
continue;
if (equal( d.d_name, ".") || equal( d.d_name, ".."))
continue;
error("%s not empty", dir);
return(-1);
}
fclose(f);
if (s.st_nlink <= 2) {
unlink( concat( dir, "/."));
unlink( concat( dir, "/.."));
}
}
if (unlink( dir)) {
error("unlink %s failed", dir);
return(-1);
}
return(0);
}
/*
* return name of parent
*/
char *
getparent( dir)
char *dir;
{
register i;
register char *p;
static char *par;
int tmp;
if (par)
free( par);
i = strlen( dir);
par = malloc( i+1);
if (par == NULL)
nomemory( );
strcpy( par, dir);
for (p=par+i; p>par; )
if (*--p != '/')
break;
for (++p; *--p!='/'; )
if (p == par) {
*p = '.';
break;
}
*++p = '\0';
if (par[tmp = strlen(par)-1] == '/')
par[tmp] = 0; /* kill any ending slash */
return (par);
}
/*
* return rightmost component of pathname
*/
char *
getchild( dir)
register char *dir;
{
register char *p,
*q;
int i;
static char ch[DIRSIZ+1];
p = &dir[strlen( dir)];
do {
if (p == dir) {
error("not permitted");
return(-1);
}
} while (*--p == '/');
q = p;
while (q > dir)
if (*--q == '/') {
++q;
break;
}
i = p+1 - q;
if (i > DIRSIZ)
i = DIRSIZ;
return (strncpy( ch, q, i));
}
/*
* return concatenation of `s1' and `s2'
*/
char *
concat( s1, s2)
char *s1,
*s2;
{
static char *str;
if (str)
free( str);
str = malloc( strlen( s1)+strlen( s2)+1);
if (str == NULL)
nomemory( );
strcpy( str, s1);
return (strcat( str, s2));
}
nomemory( )
{
fatal("out of memory");
}
onintr( )
{
signal( SIGINT, SIG_IGN);
signal( SIGHUP, SIG_IGN);
++interrupted;
}
catch( sig)
{
if( signal( sig, SIG_IGN) == SIG_DFL)
signal( sig, onintr);
}
error(arg1)
char *arg1;
{
fprintf( stderr, "rmdir: %r\n", &arg1);
}
fatal(arg1)
char *arg1;
{
error(arg1);
exit(1);
}