source: mainline/uspace/app/bdsh/cmds/modules/rm/rm.c@ 8df7a1c

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

Simplify entry types (and return values) for commands

  • Property mode set to 100644
File size: 5.8 KB
Line 
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 const 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
60static unsigned 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
88static void 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
102static unsigned 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
117static unsigned 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
126static unsigned 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;
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 argc = cli_count_args(argv);
177
178 if (argc < 2) {
179 cli_error(CL_EFAIL,
180 "%s: insufficient arguments. Try %s --help", cmdname, cmdname);
181 return CMD_FAILURE;
182 }
183
184 if (!rm_start(&rm)) {
185 cli_error(CL_ENOMEM, "%s: could not initialize", cmdname);
186 rm_end(&rm);
187 return CMD_FAILURE;
188 }
189
190 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
191 c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind);
192 switch (c) {
193 case 'h':
194 help_cmd_rm(HELP_LONG);
195 return CMD_SUCCESS;
196 case 'v':
197 printf("%s\n", RM_VERSION);
198 return CMD_SUCCESS;
199 case 'r':
200 rm.recursive = 1;
201 break;
202 case 'f':
203 rm.force = 1;
204 break;
205 case 's':
206 rm.safe = 1;
207 break;
208 }
209 }
210
211 if (optind == argc) {
212 cli_error(CL_EFAIL,
213 "%s: insufficient arguments. Try %s --help", cmdname, cmdname);
214 rm_end(&rm);
215 return CMD_FAILURE;
216 }
217
218 i = optind;
219 while (NULL != argv[i]) {
220 len = strlen(argv[i]) + 2;
221 buff = (char *) realloc(buff, len);
222 assert(buff != NULL);
223 memset(buff, 0, sizeof(buff));
224 snprintf(buff, len, argv[i]);
225
226 scope = rm_scope(buff);
227 switch (scope) {
228 case RM_BOGUS: /* FIXME */
229 case RM_FILE:
230 ret += rm_single(buff);
231 break;
232 case RM_DIR:
233 if (! rm.recursive) {
234 printf("%s is a directory, use -r to remove it.\n", buff);
235 ret ++;
236 } else {
237 ret += rm_recursive(buff);
238 }
239 break;
240 }
241 i++;
242 }
243
244 if (NULL != buff)
245 free(buff);
246
247 rm_end(&rm);
248
249 if (ret)
250 return CMD_FAILURE;
251 else
252 return CMD_SUCCESS;
253}
254
Note: See TracBrowser for help on using the repository browser.