Hint added.
[AROS.git] / workbench / c / Protect.c
blob796879c59bb51b55bf28bcd536c2eace1090b69a
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Protect CLI command
6 Lang: English
7 */
9 /*****************************************************************************
11 NAME
13 Protect
15 SYNOPSIS
17 FILE/A,FLAGS,ADD/S,SUB/S,ALL/S,QUIET/S
19 LOCATION
23 FUNCTION
25 Add or remove protection bits from a file or directory.
27 Protect allows the use of pattern matching and recursive directory
28 scans to protect many files/directories at any one time.
30 INPUTS
32 FILE -- Either a file, a directory or a pattern to match.
33 FLAGS -- One or more of the following flags:
35 S - Script
36 P - Pure
37 A - Archive
38 R - Read
39 W - Write
40 E - Execute
41 D - Delete
43 ADD -- Allows the bits to be set and hence allowable.
44 SUB -- Allows the bits to be cleared and hence not allowable.
45 ALL -- Allows a recursive scan of the volume/directory.
46 QUIET -- Suppresses any output to the shell.
48 RESULT
50 Standard DOS return codes.
52 NOTES
54 EXAMPLE
56 Protect ram: e add all
58 Recurses the ram: volume and attaches the executable bit.
60 BUGS
62 SEE ALSO
64 dos.library/SetProtection()
66 INTERNALS
68 ******************************************************************************/
70 #define DEBUG 0
72 #include <aros/debug.h>
73 #include <dos/dos.h>
74 #include <dos/dosasl.h>
75 #include <dos/dosextens.h>
76 #include <dos/exall.h>
77 #include <dos/rdargs.h>
78 #include <exec/memory.h>
79 #include <exec/types.h>
80 #include <utility/utility.h>
82 #include <proto/arossupport.h>
83 #include <proto/dos.h>
84 #include <proto/exec.h>
85 #include <proto/utility.h>
87 #define CTRL_C (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
89 #define Bit_Mask(bit) (1L << bit)
90 #define Bit_Clear(name, bit) name &= ~Bit_Mask(bit)
91 #define Bit_Set(name, bit) name |= Bit_Mask(bit)
93 #define ARG_TEMPLATE "FILE/A,FLAGS,ADD/S,SUB/S,ALL/S,QUIET/S"
95 #ifndef FIBB_HOLD
96 #define FIBB_HOLD 7
97 #endif
98 #ifndef FIBF_HOLD
99 #define FIBF_HOLD (1<<FIBB_HOLD)
100 #endif
102 enum
104 ARG_FILE = 0,
105 ARG_FLAGS,
106 ARG_ADD,
107 ARG_SUB,
108 ARG_ALL,
109 ARG_QUIET,
110 NOOFARGS
114 /* To define whether a command line switch was set or not.
116 #define NOT_SET(x) (x == 0)
117 #define IS_SET(x) (!NOT_SET(x))
119 #define MAX_PATH_LEN 512
121 const TEXT version[] = "$VER: Protect 41.1 (2.12.2000)\n";
123 int Do_Protect(struct AnchorPath *, STRPTR, STRPTR, BOOL, BOOL, BOOL, BOOL);
125 int doProtect(struct AnchorPath *ap, STRPTR file, LONG flags, BOOL flagsSet,
126 BOOL add, BOOL sub, BOOL all, BOOL quiet);
127 BOOL setProtection(STRPTR file, LONG oldFlags, LONG flags, BOOL flagsSet,
128 BOOL add, BOOL sub);
130 int __nocommandline;
132 int main(void)
134 struct RDArgs *rda;
135 struct AnchorPath *apath;
137 IPTR args[NOOFARGS] = { 0,
139 (IPTR)FALSE,
140 (IPTR)FALSE,
141 (IPTR)FALSE,
142 (IPTR)FALSE };
144 int retval = RETURN_OK;
146 apath = AllocVec(sizeof(struct AnchorPath) + MAX_PATH_LEN,
147 MEMF_ANY | MEMF_CLEAR);
149 if (apath != NULL)
151 /* Make sure DOS knows the buffer size. */
152 apath->ap_Strlen = MAX_PATH_LEN;
154 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
156 if (rda != NULL)
158 STRPTR file = (STRPTR)args[ARG_FILE];
159 STRPTR flags = (STRPTR)args[ARG_FLAGS];
160 BOOL add = (BOOL)args[ARG_ADD];
161 BOOL sub = (BOOL)args[ARG_SUB];
162 BOOL all = (BOOL)args[ARG_ALL];
163 BOOL quiet = (BOOL)args[ARG_QUIET];
165 LONG flagValues = FIBF_READ | FIBF_WRITE | FIBF_DELETE |
166 FIBF_EXECUTE;
168 if (flags != NULL)
170 D(Printf("Flags: %s\n", flags));
172 if (*flags == '+')
174 add = TRUE;
175 flags++;
177 if (*flags == '-')
179 sub = TRUE;
180 flags++;
183 while (*flags != 0 && retval == RETURN_OK)
185 char f = ToUpper(*flags);
187 D(Printf("Checking flag: %lc\n", f));
188 switch (f)
190 /* Active low */
191 case 'R':
192 flagValues &= ~FIBF_READ;
193 break;
195 case 'W':
196 flagValues &= ~FIBF_WRITE;
197 break;
199 case 'D':
200 flagValues &= ~FIBF_DELETE;
201 break;
203 case 'E':
204 flagValues &= ~FIBF_EXECUTE;
205 break;
207 /* Active high */
208 case 'A':
209 flagValues |= FIBF_ARCHIVE;
210 break;
212 case 'S':
213 flagValues |= FIBF_SCRIPT;
214 break;
216 case 'P':
217 flagValues |= FIBF_PURE;
218 break;
220 case 'H':
221 flagValues |= FIBF_HOLD;
222 break;
224 default:
225 Printf("Invalid flags - must be one of HSPARWED\n");
226 retval = RETURN_FAIL;
229 flags++;
230 } /* while (*flags != 0) */
233 if (add && sub)
235 Printf("ADD and SUB are mutually exclusive\n");
236 retval = RETURN_FAIL;
239 if (retval == RETURN_OK)
241 if (!all && IsDosEntryA(file, LDF_VOLUMES | LDF_DEVICES))
243 Printf("Can't set protection for %s - ", file);
244 SetIoErr(ERROR_OBJECT_WRONG_TYPE);
245 PrintFault(IoErr(), NULL);
247 retval = RETURN_FAIL;
249 else
251 retval = doProtect(apath, file, flagValues,
252 flags != NULL, add, sub, all,
253 quiet);
257 FreeArgs(rda);
259 else
261 PrintFault(IoErr(), "Protect");
262 retval = RETURN_FAIL;
265 else
267 retval = RETURN_FAIL;
270 FreeVec(apath);
272 return retval;
275 #define isDir(fib) ((fib)->fib_DirEntryType >= 0)
277 int doProtect(struct AnchorPath *ap, STRPTR file, LONG flags, BOOL flagsSet,
278 BOOL add, BOOL sub, BOOL all, BOOL quiet)
280 LONG match;
281 int retval = RETURN_OK;
282 LONG indent = 0;
283 int i; /* Loop variable */
284 BOOL success;
285 ULONG match_count = 0;
287 for (match = MatchFirst(file, ap);
288 match == 0 && retval == RETURN_OK && !CTRL_C;
289 match = MatchNext(ap))
291 match_count++;
292 if (isDir(&ap->ap_Info))
294 if (ap->ap_Flags & APF_DIDDIR)
296 indent--;
297 ap->ap_Flags &= ~APF_DIDDIR; /* Should not be necessary */
298 continue;
300 else if (all)
302 ap->ap_Flags |= APF_DODIR;
303 indent++;
309 success = setProtection(ap->ap_Buf, ap->ap_Info.fib_Protection, flags,
310 flagsSet, add, sub);
312 if (!quiet)
314 LONG ioerr = IoErr();
316 /* Fix indentation level */
317 for (i = 0; i < indent; i++)
319 PutStr(" ");
322 if (!isDir(&ap->ap_Info))
324 PutStr(" ");
327 PutStr(ap->ap_Info.fib_FileName);
329 if (isDir(&ap->ap_Info))
331 PutStr(" (dir)");
334 if (!success)
336 PrintFault(ioerr, "..error");
337 retval = RETURN_ERROR;
339 else
341 PutStr("..done\n");
346 if (match_count == 0 || IoErr() != ERROR_NO_MORE_ENTRIES)
348 PrintFault(IoErr(), NULL);
349 retval = RETURN_ERROR;
352 MatchEnd(ap);
354 return retval;
357 #define ALL_OFF (FIBF_READ | FIBF_WRITE | FIBF_DELETE | FIBF_EXECUTE)
358 #define addFlags(new, old) ((~(~old | ~new) & ALL_OFF) | \
359 ((old | new) & ~ALL_OFF))
361 #define subFlags(new, old) (((old | ~new) & ALL_OFF) | \
362 ((old & ~new) & ~ALL_OFF))
364 BOOL setProtection(STRPTR file, LONG oldFlags, LONG flags, BOOL flagsSet,
365 BOOL add, BOOL sub)
367 LONG newFlags;
369 if (flags != ALL_OFF)
371 if (add)
373 /* Enable permission */
374 newFlags = addFlags(flags, oldFlags);
376 else if (sub)
378 /* Disable permissions */
379 newFlags = subFlags(flags, oldFlags);
381 else
383 /* Clear all permissions then set the ones given. */
384 newFlags = flags;
387 else
389 /* No flags were given */
390 if (!add && !sub)
392 /* Disable all permissions */
393 newFlags = ALL_OFF;
395 else
397 /* Do nothing */
398 return FALSE;
402 if (!SetProtection(file, newFlags))
404 return FALSE;
407 return TRUE;