improved IEEE 1003.1 mkdir, rmdir for UNIX System V
gwyn at BRL.ARPA
gwyn at BRL.ARPA
Mon Jul 7 07:38:55 AEST 1986
#!/bin/sh
# Self-unpacking archive format. To unbundle, sh this file.
echo 'dir_test.c' 1>&2
cat >'dir_test.c' <<'END OF dir_test.c'
/*
dir_test -- mkdir, rmdir function test
last edit: 86/07/05 D A Gwyn
SCCS ID: @(#)dir_test.c 1.1
*/
#include <stdio.h>
#include <string.h>
extern void _exit();
extern int access();
static char Dirname[] = "/tmp/dir.tst"; /* test directory */
extern int mkdir(), rmdir();
/*ARGSUSED*/
main( argc, argv )
int argc;
char *argv[];
{
char buf[BUFSIZ]; /* for constructing strings */
(void)system( strcat( strcpy( buf, "mkdir " ), Dirname ) );
if ( access( Dirname, 0 ) != 0 )
_exit( 1 );
if ( mkdir( Dirname, 0777 ) == 0 )
_exit( 2 );
if ( rmdir( Dirname ) != 0 )
_exit( 3 );
(void)umask( 0200 );
if ( mkdir( Dirname, 0777 ) != 0 )
_exit( 4 );
if ( access( Dirname, 0 ) != 0 )
_exit( 5 );
if ( access( Dirname, 02 ) == 0 )
_exit( 6 );
if ( access( Dirname, 05 ) != 0 )
_exit( 7 );
if ( rmdir( Dirname ) != 0 )
_exit( 8 );
return 0;
}
END OF dir_test.c
echo 'mkdir.3' 1>&2
cat >'mkdir.3' <<'END OF mkdir.3'
.TH MKDIR 3V VMB
'\" last edit: 86/07/05 D A Gwyn
'\" SCCS ID: @(#)mkdir.3 1.1
.SH NAME
mkdir \- create a directory
.SH SYNOPSIS
.B int mkdir(path,mode);
.br
.B char *path;
.br
.B int mode;
.SH DESCRIPTION
The
.I mkdir\^
function creates a new directory with name
.IR path\^ .
The mode of the new directory is initialized from
.IR mode\^ .
The protection part of the
.I mode\^
argument is modified by the process's file creation mask (see
.IR umask\^ (2)).
.P
The directory's owner
.SM ID
is set to the process's effective user ID.
Depending on the host system,
the directory group ID is set either to
the group ID of its parent directory
or to the process's effective group ID.
.P
The newly created directory is empty
except that it may contain entries for
``\s+2.\s0'' and ``\s+2..\s0''.
.SH "RETURN VALUE"
A return value of 0 indicates success.
A return value of \-1 indicated that an error has occurred
and an appropriate error code is stored in
.IR errno\^ .
No directory is created if the return value is \-1.
.SH NOTE
This function is compatible with the definition in the
IEEE 1003.1
standard.
.SH EXAMPLE
The following program is compiled by the command
.br
$ \fIcc \|\-I/vld/include \|example.c \|/vld/lib/libVMB.a\fP
.sp
.P
#include <stdio.h>
.br
extern int mkdir();
.br
main( argc, argv )
.br
int argc;
.br
char *argv[\|];
.br
{
.br
if ( argc < 2 \|||\| mkdir( argv[1], 0777 ) != 0 )
.br
{
.br
(void) fputs( ``mkdir failed'', stderr );
.br
exit( 1 );
.br
}
.br
return 0;
.br
}
.SH FILES
/bin/mkdir system directory creation utility
.br
/vld/lib/libVMB.a VLD-VMB programmer support library
.SH "SEE ALSO"
mkdir(1), mknod(2), rmdir(3V), umask(2).
.SH AUTHOR
Douglas A. Gwyn, BRL/VLD-VMB
END OF mkdir.3
echo 'mkdir.c' 1>&2
cat >'mkdir.c' <<'END OF mkdir.c'
/*
mkdir -- create a directory
last edit: 86/07/05 D A Gwyn
SCCS ID: @(#)mkdir.c 1.1
compatible with IEEE 1003.1
returns zero iff operation succeeds
*/
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
extern void _exit();
extern int access(), chmod(), close(), execv(), fcntl(), open(),
rmdir(), umask(), wait();
#ifndef F_OK
#define F_OK 0 /* access -- test existence */
#endif
#ifndef NULL
#define NULL 0
#endif
int
mkdir( path, mode ) /* returns 0 iff successful */
char *path; /* name of new directory */
int mode; /* desired access mode */
{
register int pid; /* process ID from fork() */
register int save; /* temporary */
save = errno;
if ( path == NULL ) /* usually the best we can do */
{
errno = EFAULT; /* path outside address space */
return -1;
}
else if ( path[0] == '\0' )
{
errno = ENOENT; /* path points to null string */
return -1;
}
else if ( access( path, F_OK ) == 0 )
{
errno = EEXIST; /* directory already exists */
return -1;
}
else if ( errno == EACCES /* search denied on prefix */
|| errno == ENOTDIR /* path component not dir */
)
return -1;
errno = save; /* access() changed errno */
switch ( pid = fork() )
{
case -1: /* can't fork; too bad */
return -1; /* report fork errno */
case 0: /* child process */
{
static char *mkdir_args[] = /* args for exec */
{
"/bin/mkdir", /* system "mkdir" command */
(char *)0, /* directory name goes here */
(char *)0 /* list terminator */
};
mkdir_args[1] = path;
/* be careful to avoid "mkdir" I/O side-effects */
(void)close( 0 );
(void)close( 1 );
(void)close( 2 );
if ( open( "/dev/null", O_RDWR ) != 0
|| fcntl( 0, F_DUPFD, 1 ) != 1
|| fcntl( 0, F_DUPFD, 2 ) != 2
|| execv( mkdir_args[0], mkdir_args ) != 0
)
; /* _exit in all cases */
_exit( 255 );
/*NOTREACHED*/
}
default: /* parent process */
{
int status; /* child termination status */
register int w; /* PID returned from wait() */
#ifdef SIGCLD
register void (*oldcld)() = signal( SIGCLD, SIG_DFL );
/* avoid wait on all children */
#endif
while ( (w = wait( &status )) != pid
&& (w != -1 || errno == EINTR)
)
; /* wait for proper child */
#ifdef SIGCLD
if ( oldcld != SIG_DFL ) /* restore catcher */
(void)signal( SIGCLD, oldcld );
#endif
if ( w == -1 || status != 0 )
{
errno = EACCES; /* can't write on parent? */
return -1;
}
}
}
save = umask( 0 );
if ( chmod( path, mode & ~save ) != 0 ) /* "can't happen" */
{
(void)umask( save );
(void)rmdir( path ); /* comply with spec */
return -1; /* report chmod | rmdir errno */
}
else {
(void)umask( save );
return 0; /* success */
}
}
END OF mkdir.c
echo 'rmdir.3' 1>&2
cat >'rmdir.3' <<'END OF rmdir.3'
.TH RMDIR 3V VMB
'\" last edit: 86/07/05 D A Gwyn
'\" SCCS ID: @(#)rmdir.3 1.1
.SH NAME
rmdir \- remove a directory
.SH SYNOPSIS
.B int rmdir(path);
.br
.B char *path;
.SH DESCRIPTION
The
.I rmdir\^
function removes a directory whose name is given by
.IR path\^ .
The directory must not have any entries other than, possibly,
``\s+2.\s0'' and ``\s+2..\s0''.
.P
Depending on the host system,
it may be possible to remove the root
or current working directory.
.SH "RETURN VALUE"
A return value of 0 indicates success.
A return value of \-1 indicated that an error has occurred
and an appropriate error code is stored in
.IR errno\^ .
.SH NOTE
This function is compatible with the definition in the
IEEE 1003.1
standard.
.SH EXAMPLE
The following program is compiled by the command
.br
$ \fIcc \|\-I/vld/include \|example.c \|/vld/lib/libVMB.a\fP
.sp
.P
#include <stdio.h>
.br
extern int rmdir();
.br
main( argc, argv )
.br
int argc;
.br
char *argv[\|];
.br
{
.br
if ( argc < 2 \|||\| rmdir( argv[1] ) != 0 )
.br
{
.br
(void) fputs( ``rmdir failed'', stderr );
.br
exit( 1 );
.br
}
.br
return 0;
.br
}
.SH FILES
/bin/rmdir system directory creation utility
.br
/vld/lib/libVMB.a VLD-VMB programmer support library
.SH "SEE ALSO"
mkdir(3V), remove(3V), rmdir(1).
.SH AUTHOR
Douglas A. Gwyn, BRL/VLD-VMB
END OF rmdir.3
echo 'rmdir.c' 1>&2
cat >'rmdir.c' <<'END OF rmdir.c'
/*
rmdir -- remove a directory
last edit: 86/07/05 D A Gwyn
SCCS ID: @(#)rmdir.c 1.1
compatible with IEEE 1003.1
returns zero iff operation succeeds
*/
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
extern void _exit();
extern int access(), close(), execv(), fcntl(), open(), wait();
#ifndef F_OK
#define F_OK 0 /* access -- test existence */
#endif
#ifndef NULL
#define NULL 0
#endif
int
rmdir( path ) /* returns 0 iff successful */
char *path; /* name of directory */
{
register int pid; /* process ID from fork() */
if ( path == NULL ) /* usually the best we can do */
{
errno = EFAULT; /* path outside address space */
return -1;
}
else if ( path[0] == '\0' )
{
errno = ENOENT; /* path points to null string */
return -1;
}
else if ( access( path, F_OK ) != 0 )
return -1; /* EACCES, ENOTDIR, ENOENT */
switch ( pid = fork() )
{
case -1: /* can't fork; too bad */
return -1; /* report fork errno */
case 0: /* child process */
{
static char *rmdir_args[] = /* args for exec */
{
"/bin/rmdir", /* system "rmdir" command */
(char *)0, /* directory name goes here */
(char *)0 /* list terminator */
};
rmdir_args[1] = path;
/* be careful to avoid "rmdir" I/O side-effects */
(void)close( 0 );
(void)close( 1 );
(void)close( 2 );
if ( open( "/dev/null", O_RDWR ) != 0
|| fcntl( 0, F_DUPFD, 1 ) != 1
|| fcntl( 0, F_DUPFD, 2 ) != 2
|| execv( rmdir_args[0], rmdir_args ) != 0
)
; /* _exit in all cases */
_exit( 255 );
/*NOTREACHED*/
}
default: /* parent process */
{
int status; /* child termination status */
register int w; /* PID returned from wait() */
#ifdef SIGCLD
register void (*oldcld)() = signal( SIGCLD, SIG_DFL );
/* avoid wait on all children */
#endif
while ( (w = wait( &status )) != pid
&& (w != -1 || errno == EINTR)
)
; /* wait for proper child */
#ifdef SIGCLD
if ( oldcld != SIG_DFL ) /* restore catcher */
(void)signal( SIGCLD, oldcld );
#endif
if ( w == -1 || status != 0 )
{
errno = EACCES; /* can't write on parent? */
return -1;
}
else
return 0; /* success */
}
}
/*NOTREACHED*/
}
END OF rmdir.c
More information about the Comp.unix
mailing list