diff options
author | Christopher Faylor <me@cgf.cx> | 2000-09-03 03:52:30 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2000-09-03 03:52:30 +0000 |
commit | 42f03f675735b0ab55f86824894706e39878b5cc (patch) | |
tree | 8257fcbb3933db674d2f140ed9329c64baf19977 /winsup/testsuite/libltp/lib/rmobj.c | |
parent | 312a668a2270134e00534e587ff76886f8570aae (diff) | |
download | cygnal-42f03f675735b0ab55f86824894706e39878b5cc.tar.gz cygnal-42f03f675735b0ab55f86824894706e39878b5cc.tar.bz2 cygnal-42f03f675735b0ab55f86824894706e39878b5cc.zip |
Importing Egor's testsuite.
Diffstat (limited to 'winsup/testsuite/libltp/lib/rmobj.c')
-rw-r--r-- | winsup/testsuite/libltp/lib/rmobj.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/winsup/testsuite/libltp/lib/rmobj.c b/winsup/testsuite/libltp/lib/rmobj.c new file mode 100644 index 000000000..63122c446 --- /dev/null +++ b/winsup/testsuite/libltp/lib/rmobj.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +/* $Id$ */ + +/********************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : rmobj() + * + * FUNCTION TITLE : Remove an object + * + * SYNOPSIS: + * int rmobj(char *obj, char **errmsg) + * + * AUTHOR : Kent Rogers + * + * INITIAL RELEASE : UNICOS 7.0 + * + * USER DESCRIPTION + * This routine will remove the specified object. If the specified + * object is a directory, it will recursively remove the directory + * and everything underneath it. It assumes that it has privilege + * to remove everything that it tries to remove. If rmobj() encounters + * any problems, and errmsg is not NULL, errmsg is set to point to a + * string explaining the error. + * + * DETAILED DESCRIPTION + * Allocate space for the directory and its contents + * Open the directory to get access to what is in it + * Loop through the objects in the directory: + * If the object is not "." or "..": + * Determine the file type by calling lstat() + * If the object is not a directory: + * Remove the object with unlink() + * Else: + * Call rmobj(object) to remove the object's contents + * Determine the link count on object by calling lstat() + * If the link count >= 3: + * Remove the directory with unlink() + * Else + * Remove the directory with rmdir() + * Close the directory and free the pointers + * + * RETURN VALUE + * If there are any problems, rmobj() will set errmsg (if it was not + * NULL) and return -1. Otherwise it will return 0. + * + ************************************************************/ +#include <errno.h> /* for errno */ +#include <stdio.h> /* for NULL */ +#include <stdlib.h> /* for malloc() */ +#include <string.h> /* for string function */ +#include <limits.h> /* for PATH_MAX */ +#include <sys/types.h> /* for opendir(), readdir(), closedir(), stat() */ +#include <sys/stat.h> /* for [l]stat() */ +#include <dirent.h> /* for opendir(), readdir(), closedir() */ +#include <unistd.h> /* for rmdir(), unlink() */ +#include "rmobj.h" + +#define SYSERR strerror(errno) + +int +rmobj(char *obj, char **errmsg) +{ + int ret_val = 0; /* return value from this routine */ + DIR *dir; /* pointer to a directory */ + struct dirent *dir_ent; /* pointer to directory entries */ + char dirobj[PATH_MAX]; /* object inside directory to modify */ + struct stat statbuf; /* used to hold stat information */ + static char err_msg[1024]; /* error message */ + + /* Determine the file type */ + if ( lstat(obj, &statbuf) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "lstat(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + + /* Take appropriate action, depending on the file type */ + if ( (statbuf.st_mode & S_IFMT) == S_IFDIR ) { + /* object is a directory */ + + /* Do NOT perform the request if the directory is "/" */ + if ( !strcmp(obj, "/") ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "Cannot remove /"); + *errmsg = err_msg; + } + return -1; + } + + /* Open the directory to get access to what is in it */ + if ( (dir = opendir(obj)) == NULL ) { + if ( rmdir(obj) != 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "rmdir(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } else { + return 0; + } + } + + /* Loop through the entries in the directory, removing each one */ + for ( dir_ent = (struct dirent *)readdir(dir); + dir_ent != NULL; + dir_ent = (struct dirent *)readdir(dir)) { + + /* Don't remove "." or ".." */ + if ( !strcmp(dir_ent->d_name, ".") || !strcmp(dir_ent->d_name, "..") ) + continue; + + /* Recursively call this routine to remove the current entry */ + sprintf(dirobj, "%s/%s", obj, dir_ent->d_name); + if ( rmobj(dirobj, errmsg) != 0 ) + ret_val = -1; + } + + /* Close the directory */ + closedir(dir); + + /* If there were problems removing an entry, don't attempt to + remove the directory itself */ + if ( ret_val == -1 ) + return -1; + + /* Get the link count, now that all the entries have been removed */ + if ( lstat(obj, &statbuf) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "lstat(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + + /* Remove the directory itself */ + if ( statbuf.st_nlink >= 3 ) { + /* The directory is linked; unlink() must be used */ + if ( unlink(obj) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "unlink(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } else { + /* The directory is not linked; rmdir() can be used */ + if ( rmdir(obj) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "rmdir(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } + } else { + /* object is not a directory; just use unlink() */ + if ( unlink(obj) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "unlink(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } /* if obj is a directory */ + + /* + * Everything must have went ok. + */ + return 0; +} /* rmobj() */ |