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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a000878c was a000878c, checked in by Martin Decky <martin@…>, 15 years ago

make sure that all statically allocated strings are declared as "const char *"
and are treated as read-only

  • Property mode set to 100644
File size: 5.9 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 <getopt.h>
37#include <mem.h>
38#include <string.h>
39
40#include "config.h"
41#include "errors.h"
42#include "util.h"
43#include "entry.h"
44#include "rm.h"
45#include "cmds.h"
46
47static const char *cmdname = "rm";
48#define RM_VERSION "0.0.1"
49
50static rm_job_t rm;
51
52static struct option const long_options[] = {
53 { "help", no_argument, 0, 'h' },
54 { "version", no_argument, 0, 'v' },
55 { "recursive", no_argument, 0, 'r' },
56 { "force", no_argument, 0, 'f' },
57 { "safe", no_argument, 0, 's' },
58 { 0, 0, 0, 0 }
59};
60
61static unsigned int rm_start(rm_job_t *rm)
62{
63 rm->recursive = 0;
64 rm->force = 0;
65 rm->safe = 0;
66
67 /* Make sure we can allocate enough memory to store
68 * what is needed in the job structure */
69 if (NULL == (rm->nwd = (char *) malloc(PATH_MAX)))
70 return 0;
71 memset(rm->nwd, 0, sizeof(rm->nwd));
72
73 if (NULL == (rm->owd = (char *) malloc(PATH_MAX)))
74 return 0;
75 memset(rm->owd, 0, sizeof(rm->owd));
76
77 if (NULL == (rm->cwd = (char *) malloc(PATH_MAX)))
78 return 0;
79 memset(rm->cwd, 0, sizeof(rm->cwd));
80
81 chdir(".");
82
83 if (NULL == (getcwd(rm->owd, PATH_MAX)))
84 return 0;
85
86 return 1;
87}
88
89static void rm_end(rm_job_t *rm)
90{
91 if (NULL != rm->nwd)
92 free(rm->nwd);
93
94 if (NULL != rm->owd)
95 free(rm->owd);
96
97 if (NULL != rm->cwd)
98 free(rm->cwd);
99
100 return;
101}
102
103static unsigned int rm_recursive(const char *path)
104{
105 int rc;
106
107 /* First see if it will just go away */
108 rc = rmdir(path);
109 if (rc == 0)
110 return 0;
111
112 /* Its not empty, recursively scan it */
113 cli_error(CL_ENOTSUP,
114 "Can not remove %s, directory not empty", path);
115 return 1;
116}
117
118static unsigned int rm_single(const char *path)
119{
120 if (unlink(path)) {
121 cli_error(CL_EFAIL, "rm: could not remove file %s", path);
122 return 1;
123 }
124 return 0;
125}
126
127static unsigned int rm_scope(const char *path)
128{
129 int fd;
130 DIR *dirp;
131
132 dirp = opendir(path);
133 if (dirp) {
134 closedir(dirp);
135 return RM_DIR;
136 }
137
138 fd = open(path, O_RDONLY);
139 if (fd > 0) {
140 close(fd);
141 return RM_FILE;
142 }
143
144 return RM_BOGUS;
145}
146
147/* Dispays help for rm in various levels */
148void help_cmd_rm(unsigned int level)
149{
150 if (level == HELP_SHORT) {
151 printf("`%s' removes files and directories.\n", cmdname);
152 } else {
153 help_cmd_rm(HELP_SHORT);
154 printf(
155 "Usage: %s [options] <path>\n"
156 "Options:\n"
157 " -h, --help A short option summary\n"
158 " -v, --version Print version information and exit\n"
159 " -r, --recursive Recursively remove sub directories\n"
160 " -f, --force Do not prompt prior to removing files\n"
161 " -s, --safe Stop if directories change during removal\n\n"
162 "Currently, %s is under development, some options don't work.\n",
163 cmdname, cmdname);
164 }
165 return;
166}
167
168/* Main entry point for rm, accepts an array of arguments */
169int cmd_rm(char **argv)
170{
171 unsigned int argc;
172 unsigned int i, scope, ret = 0;
173 int c, opt_ind;
174 size_t len;
175 char *buff = NULL;
176
177 argc = cli_count_args(argv);
178
179 if (argc < 2) {
180 cli_error(CL_EFAIL,
181 "%s: insufficient arguments. Try %s --help", cmdname, cmdname);
182 return CMD_FAILURE;
183 }
184
185 if (!rm_start(&rm)) {
186 cli_error(CL_ENOMEM, "%s: could not initialize", cmdname);
187 rm_end(&rm);
188 return CMD_FAILURE;
189 }
190
191 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
192 c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind);
193 switch (c) {
194 case 'h':
195 help_cmd_rm(HELP_LONG);
196 return CMD_SUCCESS;
197 case 'v':
198 printf("%s\n", RM_VERSION);
199 return CMD_SUCCESS;
200 case 'r':
201 rm.recursive = 1;
202 break;
203 case 'f':
204 rm.force = 1;
205 break;
206 case 's':
207 rm.safe = 1;
208 break;
209 }
210 }
211
212 if ((unsigned) optind == argc) {
213 cli_error(CL_EFAIL,
214 "%s: insufficient arguments. Try %s --help", cmdname, cmdname);
215 rm_end(&rm);
216 return CMD_FAILURE;
217 }
218
219 i = optind;
220 while (NULL != argv[i]) {
221 len = str_size(argv[i]) + 2;
222 buff = (char *) realloc(buff, len);
223 if (buff == NULL) {
224 printf("rm: out of memory\n");
225 ret = 1;
226 break;
227 }
228 memset(buff, 0, sizeof(buff));
229 snprintf(buff, len, argv[i]);
230
231 scope = rm_scope(buff);
232 switch (scope) {
233 case RM_BOGUS: /* FIXME */
234 case RM_FILE:
235 ret += rm_single(buff);
236 break;
237 case RM_DIR:
238 if (! rm.recursive) {
239 printf("%s is a directory, use -r to remove it.\n", buff);
240 ret ++;
241 } else {
242 ret += rm_recursive(buff);
243 }
244 break;
245 }
246 i++;
247 }
248
249 if (NULL != buff)
250 free(buff);
251
252 rm_end(&rm);
253
254 if (ret)
255 return CMD_FAILURE;
256 else
257 return CMD_SUCCESS;
258}
259
Note: See TracBrowser for help on using the repository browser.