2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
33 /* $Id: rmobj.c,v 1.5 2009/07/20 10:59:32 vapier Exp $ */
35 /**********************************************************
37 * OS Testing - Silicon Graphics, Inc.
39 * FUNCTION NAME : rmobj()
41 * FUNCTION TITLE : Remove an object
44 * int rmobj(char *obj, char **errmsg)
46 * AUTHOR : Kent Rogers
48 * INITIAL RELEASE : UNICOS 7.0
51 * This routine will remove the specified object. If the specified
52 * object is a directory, it will recursively remove the directory
53 * and everything underneath it. It assumes that it has privilege
54 * to remove everything that it tries to remove. If rmobj() encounters
55 * any problems, and errmsg is not NULL, errmsg is set to point to a
56 * string explaining the error.
58 * DETAILED DESCRIPTION
59 * Allocate space for the directory and its contents
60 * Open the directory to get access to what is in it
61 * Loop through the objects in the directory:
62 * If the object is not "." or "..":
63 * Determine the file type by calling lstat()
64 * If the object is not a directory:
65 * Remove the object with unlink()
67 * Call rmobj(object) to remove the object's contents
68 * Determine the link count on object by calling lstat()
69 * If the link count >= 3:
70 * Remove the directory with unlink()
72 * Remove the directory with rmdir()
73 * Close the directory and free the pointers
76 * If there are any problems, rmobj() will set errmsg (if it was not
77 * NULL) and return -1. Otherwise it will return 0.
79 ************************************************************/
80 #include <errno.h> /* for errno */
81 #include <stdio.h> /* for NULL */
82 #include <stdlib.h> /* for malloc() */
83 #include <string.h> /* for string function */
84 #include <limits.h> /* for PATH_MAX */
85 #include <sys/types.h> /* for opendir(), readdir(), closedir(), stat() */
86 #include <sys/stat.h> /* for [l]stat() */
87 #include <dirent.h> /* for opendir(), readdir(), closedir() */
88 #include <unistd.h> /* for rmdir(), unlink() */
91 #define SYSERR strerror(errno)
94 rmobj(char *obj
, char **errmsg
)
96 int ret_val
= 0; /* return value from this routine */
97 DIR *dir
; /* pointer to a directory */
98 struct dirent
*dir_ent
; /* pointer to directory entries */
99 char dirobj
[PATH_MAX
]; /* object inside directory to modify */
100 struct stat statbuf
; /* used to hold stat information */
101 static char err_msg
[1024]; /* error message */
103 /* Determine the file type */
104 if ( lstat(obj
, &statbuf
) < 0 ) {
105 if ( errmsg
!= NULL
) {
106 sprintf(err_msg
, "lstat(%s) failed; errno=%d: %s",
113 /* Take appropriate action, depending on the file type */
114 if ( (statbuf
.st_mode
& S_IFMT
) == S_IFDIR
) {
115 /* object is a directory */
117 /* Do NOT perform the request if the directory is "/" */
118 if ( !strcmp(obj
, "/") ) {
119 if ( errmsg
!= NULL
) {
120 sprintf(err_msg
, "Cannot remove /");
126 /* Open the directory to get access to what is in it */
127 if ( (dir
= opendir(obj
)) == NULL
) {
128 if ( rmdir(obj
) != 0 ) {
129 if ( errmsg
!= NULL
) {
130 sprintf(err_msg
, "rmdir(%s) failed; errno=%d: %s",
140 /* Loop through the entries in the directory, removing each one */
141 for ( dir_ent
= (struct dirent
*)readdir(dir
);
143 dir_ent
= (struct dirent
*)readdir(dir
)) {
145 /* Don't remove "." or ".." */
146 if ( !strcmp(dir_ent
->d_name
, ".") || !strcmp(dir_ent
->d_name
, "..") )
149 /* Recursively call this routine to remove the current entry */
150 sprintf(dirobj
, "%s/%s", obj
, dir_ent
->d_name
);
151 if ( rmobj(dirobj
, errmsg
) != 0 )
155 /* Close the directory */
158 /* If there were problems removing an entry, don't attempt to
159 remove the directory itself */
163 /* Get the link count, now that all the entries have been removed */
164 if ( lstat(obj
, &statbuf
) < 0 ) {
165 if ( errmsg
!= NULL
) {
166 sprintf(err_msg
, "lstat(%s) failed; errno=%d: %s",
173 /* Remove the directory itself */
174 if ( statbuf
.st_nlink
>= 3 ) {
175 /* The directory is linked; unlink() must be used */
176 if ( unlink(obj
) < 0 ) {
177 if ( errmsg
!= NULL
) {
178 sprintf(err_msg
, "unlink(%s) failed; errno=%d: %s",
185 /* The directory is not linked; remove() can be used */
186 if ( remove(obj
) < 0 ) {
187 if ( errmsg
!= NULL
) {
188 sprintf(err_msg
, "remove(%s) failed; errno=%d: %s",
196 /* object is not a directory; just use unlink() */
197 if ( unlink(obj
) < 0 ) {
198 if ( errmsg
!= NULL
) {
199 sprintf(err_msg
, "unlink(%s) failed; errno=%d: %s",
205 } /* if obj is a directory */
208 * Everything must have went ok.