source: mainline/uspace/app/bdsh/cmds/modules/rm/rm.c@ 216d6fc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 216d6fc was 216d6fc, checked in by Tim Post <echo@…>, 17 years ago

Merge with shell @ 3241 for bdsh

  • Property mode set to 100644
File size: 5.8 KB
RevLine 
[216d6fc]1/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of the original program's authors nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <fcntl.h>
35#include <dirent.h>
36#include <assert.h>
37#include <getopt.h>
38
39#include "config.h"
40#include "errors.h"
41#include "util.h"
42#include "entry.h"
43#include "rm.h"
44#include "cmds.h"
45
46static char *cmdname = "rm";
47#define RM_VERSION "0.0.1"
48
49static rm_job_t rm;
50
51static struct option long_options[] = {
52 { "help", no_argument, 0, 'h' },
53 { "version", no_argument, 0, 'v' },
54 { "recursive", no_argument, 0, 'r' },
55 { "force", no_argument, 0, 'f' },
56 { "safe", no_argument, 0, 's' },
57 { 0, 0, 0, 0 }
58};
59
60unsigned int rm_start(rm_job_t *rm)
61{
62 rm->recursive = 0;
63 rm->force = 0;
64 rm->safe = 0;
65
66 /* Make sure we can allocate enough memory to store
67 * what is needed in the job structure */
68 if (NULL == (rm->nwd = (char *) malloc(PATH_MAX)))
69 return 0;
70 memset(rm->nwd, 0, sizeof(rm->nwd));
71
72 if (NULL == (rm->owd = (char *) malloc(PATH_MAX)))
73 return 0;
74 memset(rm->owd, 0, sizeof(rm->owd));
75
76 if (NULL == (rm->cwd = (char *) malloc(PATH_MAX)))
77 return 0;
78 memset(rm->cwd, 0, sizeof(rm->cwd));
79
80 chdir(".");
81
82 if (NULL == (getcwd(rm->owd, PATH_MAX)))
83 return 0;
84
85 return 1;
86}
87
88void rm_end(rm_job_t *rm)
89{
90 if (NULL != rm->nwd)
91 free(rm->nwd);
92
93 if (NULL != rm->owd)
94 free(rm->owd);
95
96 if (NULL != rm->cwd)
97 free(rm->cwd);
98
99 return;
100}
101
102unsigned int rm_recursive(const char *path)
103{
104 int rc;
105
106 /* First see if it will just go away */
107 rc = rmdir(path);
108 if (rc == 0)
109 return 0;
110
111 /* Its not empty, recursively scan it */
112 cli_error(CL_ENOTSUP,
113 "Can not remove %s, directory not empty", path);
114 return 1;
115}
116
117unsigned int rm_single(const char *path)
118{
119 if (unlink(path)) {
120 cli_error(CL_EFAIL, "rm: could not remove file %s", path);
121 return 1;
122 }
123 return 0;
124}
125
126unsigned int rm_scope(const char *path)
127{
128 int fd;
129 DIR *dirp;
130
131 dirp = opendir(path);
132 if (dirp) {
133 closedir(dirp);
134 return RM_DIR;
135 }
136
137 fd = open(path, O_RDONLY);
138 if (fd > 0) {
139 close(fd);
140 return RM_FILE;
141 }
142
143 return RM_BOGUS;
144}
145
146/* Dispays help for rm in various levels */
147void * help_cmd_rm(unsigned int level)
148{
149 if (level == HELP_SHORT) {
150 printf("`%s' removes files and directories.\n", cmdname);
151 } else {
152 help_cmd_rm(HELP_SHORT);
153 printf(
154 "Usage: %s [options] <path>\n"
155 "Options:\n"
156 " -h, --help A short option summary\n"
157 " -v, --version Print version information and exit\n"
158 " -r, --recursive Recursively remove sub directories\n"
159 " -f, --force Do not prompt prior to removing files\n"
160 " -s, --safe Stop if directories change during removal\n\n"
161 "Currently, %s is under development, some options don't work.\n",
162 cmdname, cmdname);
163 }
164 return CMD_VOID;
165}
166
167/* Main entry point for rm, accepts an array of arguments */
168int * cmd_rm(char **argv)
169{
170 unsigned int argc;
171 unsigned int i, scope, ret = 0;
172 int c, opt_ind;
173 size_t len;
174 char *buff = NULL;
175
176 for (argc = 0; argv[argc] != NULL; argc ++);
177 if (argc < 2) {
178 cli_error(CL_EFAIL,
179 "%s: insufficient arguments. Try %s --help", cmdname, cmdname);
180 return CMD_FAILURE;
181 }
182
183 if (!rm_start(&rm)) {
184 cli_error(CL_ENOMEM, "%s: could not initialize", cmdname);
185 rm_end(&rm);
186 return CMD_FAILURE;
187 }
188
189 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
190 c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind);
191 switch (c) {
192 case 'h':
193 help_cmd_rm(HELP_LONG);
194 return CMD_SUCCESS;
195 case 'v':
196 printf("%s\n", RM_VERSION);
197 return CMD_SUCCESS;
198 case 'r':
199 rm.recursive = 1;
200 break;
201 case 'f':
202 rm.force = 1;
203 break;
204 case 's':
205 rm.safe = 1;
206 break;
207 }
208 }
209
210 if (optind == argc) {
211 cli_error(CL_EFAIL,
212 "%s: insufficient arguments. Try %s --help", cmdname, cmdname);
213 rm_end(&rm);
214 return CMD_FAILURE;
215 }
216
217 i = optind;
218 while (NULL != argv[i]) {
219 len = strlen(argv[i]) + 2;
220 buff = (char *) realloc(buff, len);
221 assert(buff != NULL);
222 memset(buff, 0, sizeof(buff));
223 snprintf(buff, len, argv[i]);
224
225 scope = rm_scope(buff);
226 switch (scope) {
227 case RM_BOGUS: /* FIXME */
228 case RM_FILE:
229 ret += rm_single(buff);
230 break;
231 case RM_DIR:
232 if (! rm.recursive) {
233 printf("%s is a directory, use -r to remove it.\n", buff);
234 ret ++;
235 } else {
236 ret += rm_recursive(buff);
237 }
238 break;
239 }
240 i++;
241 }
242
243 if (NULL != buff)
244 free(buff);
245
246 rm_end(&rm);
247
248 if (ret)
249 return CMD_FAILURE;
250 else
251 return CMD_SUCCESS;
252}
253
Note: See TracBrowser for help on using the repository browser.