Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!caip!brl-adm!brl-smoke!smoke!gwyn@BRL.ARPA From: gwyn@BRL.ARPA Newsgroups: net.unix Subject: improved IEEE 1003.1 mkdir, rmdir for UNIX System V Message-ID: <1981@brl-smoke.ARPA> Date: Sun, 6-Jul-86 17:38:55 EDT Article-I.D.: brl-smok.1981 Posted: Sun Jul 6 17:38:55 1986 Date-Received: Mon, 7-Jul-86 02:18:04 EDT Sender: news@brl-smoke.ARPA Lines: 460 #!/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 #include 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 .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 #include #include 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 .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 #include #include 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