Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3d5b8f5

Browse files
my_chattr: working with multiple flags
1 parent 04d8b06 commit 3d5b8f5

File tree

2 files changed

+197
-24
lines changed

2 files changed

+197
-24
lines changed

‎15_File_Attributes/my_chattr.c‎

Lines changed: 193 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,26 @@
4848
* Set the file's project number. *
4949
* -------------------------------------------------------------------------- */
5050

51+
#include <ctype.h>
52+
#include <fcntl.h>
53+
#include <linux/fs.h>
5154
#include <stdio.h>
5255
#include <stdlib.h>
56+
#include <sys/ioctl.h>
57+
#include <sys/stat.h>
5358
#include <unistd.h>
5459

60+
void usage(char *pgm_name, char *msg)
61+
{
62+
fprintf(stderr,
63+
"Usage: %s %s\n",
64+
pgm_name,
65+
"[ -RVf ] [ -v version ] [ -p project ] [ mode ] files..."
66+
);
67+
if (msg != NULL)
68+
fprintf(stderr, "%s\n", msg);
69+
}
70+
5571
int main(int argc, char *argv[])
5672
{
5773
int opt;
@@ -61,18 +77,18 @@ int main(int argc, char *argv[])
6177
int file_version = 0;
6278
int project_num = 0;
6379
char *mode = NULL;
80+
char *file_name = NULL;
81+
char *pgm_name = argv[0];
6482

65-
while (((opt = getopt(argc, argv, ":RVfv:p:")) != -1)&& !args_done)
83+
while (!args_done&&((opt = getopt(argc, argv, ":RVfv:p:")) != -1))
6684
{
85+
if (verbosity > 1) {
86+
fprintf(stderr, "optind=%d, opt='%c',optarg='%s'\n", optind, opt, optarg);
87+
}
6788
switch (opt)
6889
{
6990
case 'R':
70-
fprintf(stderr,
71-
"Usage: %s %s\n",
72-
argv[0],
73-
"[ -RVf ] [ -v version ] [ -p project ] [ mode ] files..."
74-
);
75-
fprintf(stderr, "-R is not implemented\n");
91+
usage(pgm_name, "-R is not implemented");
7692
exit(EXIT_FAILURE);
7793
break;
7894
case 'V':
@@ -82,34 +98,86 @@ int main(int argc, char *argv[])
8298
suppress_errors = 1;
8399
break;
84100
case 'v':
85-
file_version = atoi(optarg);
101+
if (verbosity > 1) {
102+
fprintf(
103+
stderr,
104+
"set file version\nargv[%d]='%s'\n",
105+
optind,
106+
argv[optind]);
107+
}
108+
if (optarg != NULL && isdigit(*optarg)) {
109+
file_version = atoi(optarg);
110+
} else {
111+
usage(pgm_name, "-v requires a numeric argument");
112+
exit(EXIT_FAILURE);
113+
}
86114
break;
87115
case 'p':
88-
project_num = atoi(optarg);
116+
if (verbosity > 1) {
117+
fprintf(
118+
stderr,
119+
"set project number\nargv[%d]='%s'\n",
120+
optind,
121+
argv[optind]);
122+
}
123+
if (optarg != NULL && isdigit(*optarg)) {
124+
project_num = atoi(optarg);
125+
} else {
126+
usage(pgm_name, "-p requires a numeric argument");
127+
exit(EXIT_FAILURE);
128+
}
129+
break;
130+
case ':':
131+
fprintf(stderr, "Missing argument\n");
132+
if (verbosity > 1) {
133+
fprintf(
134+
stderr,
135+
"argv[%d]='%s'\n",
136+
optind,
137+
argv[optind]);
138+
}
139+
exit(EXIT_FAILURE);
89140
break;
90141
default: /* '?' */
142+
if (verbosity > 1) {
143+
fprintf(
144+
stderr,
145+
"end of arguments\nargv[%d]='%s'\n",
146+
optind,
147+
argv[optind]);
148+
}
91149
args_done = 1;
92150
break;
93151
}
94152
}
95153

96-
if (optind >= argc)
154+
optind -= (args_done) ? 1 : 0;
155+
if (optind < argc)
97156
{
157+
mode = argv[optind];
158+
switch (*mode)
159+
{
160+
case '+':
161+
case '-':
162+
case '=':
163+
if (optind + 1 >= argc)
164+
{
165+
fprintf(stderr, "Expecting file names\n");
166+
exit(EXIT_FAILURE);
167+
} else {
168+
file_name = argv[optind+1];
169+
}
170+
break;
171+
default:
172+
mode = NULL;
173+
file_name = argv[optind];
174+
break;
175+
}
176+
} else {
98177
fprintf(stderr, "Expecting file names\n");
99178
exit(EXIT_FAILURE);
100179
}
101-
102-
switch (*argv[optind])
103-
{
104-
case '+':
105-
case '-':
106-
case '=':
107-
mode = argv[optind];
108-
break;
109-
default:
110-
mode = NULL;
111-
break;
112-
}
180+
113181

114182
if (verbosity)
115183
{
@@ -137,8 +205,111 @@ int main(int argc, char *argv[])
137205
fprintf(stderr, "not changed\n");
138206
}
139207
fprintf(stderr, "Mode: %s\n", (mode) ? mode : "Not used");
208+
fprintf(stderr, "File name: %s\n", file_name);
209+
}
210+
211+
if (! mode) {
212+
fprintf(
213+
stderr,
214+
"%s: No mode specified\n",
215+
pgm_name
216+
);
217+
exit(EXIT_FAILURE);
140218
}
141219

220+
int fd = open(file_name, O_RDONLY);
221+
if (fd == -1) {
222+
fprintf(stderr, "%s: open of '%s' failed: %m\n", pgm_name, file_name);
223+
exit(EXIT_FAILURE);
224+
}
225+
226+
enum fs_ops { set_flags, rm_flags, add_flags };
227+
enum fs_ops op;
228+
switch (*mode) {
229+
case '-':
230+
op = rm_flags;
231+
break;
232+
case '+':
233+
op = add_flags;
234+
break;
235+
case '=':
236+
op = set_flags;
237+
break;
238+
default:
239+
usage(pgm_name, "Invalid mode operation");
240+
exit(EXIT_FAILURE);
241+
}
242+
243+
unsigned int fs_mask = 0;
244+
for ( char *flag_ch = mode + 1; *flag_ch; flag_ch++ ) {
245+
switch (*flag_ch) {
246+
case 'a': fs_mask |= FS_APPEND_FL; break;
247+
case 'c': fs_mask |= FS_COMPR_FL; break;
248+
case 'D': fs_mask |= FS_DIRSYNC_FL; break;
249+
case 'i': fs_mask |= FS_IMMUTABLE_FL; break;
250+
case 'j': fs_mask |= FS_JOURNAL_DATA_FL; break;
251+
case 'A': fs_mask |= FS_NOATIME_FL; break;
252+
case 'd': fs_mask |= FS_NODUMP_FL; break;
253+
case 't': fs_mask |= FS_NOTAIL_FL; break;
254+
case 's': fs_mask |= FS_SECRM_FL; break;
255+
case 'S': fs_mask |= FS_SYNC_FL; break;
256+
case 'T': fs_mask |= FS_TOPDIR_FL; break;
257+
case 'u': fs_mask |= FS_UNRM_FL; break;
258+
default:
259+
if ( ! suppress_errors ) {
260+
fprintf(
261+
stderr,
262+
"%s: invalid mode '%c' found - ignored\n",
263+
pgm_name,
264+
*flag_ch
265+
);
266+
}
267+
break;
268+
}
269+
}
270+
271+
unsigned int attr = 0;
272+
273+
if (op != set_flags && ioctl(fd, FS_IOC_GETFLAGS, &attr) == -1) {
274+
fprintf(
275+
stderr,
276+
"%s: Get flags from '%s' failed: %m\n",
277+
pgm_name,
278+
file_name);
279+
exit(EXIT_FAILURE);
280+
}
281+
282+
if (verbosity > 1) {
283+
fprintf(
284+
stderr,
285+
"op=%d,attr(before)=%0X,",
286+
op,
287+
attr);
288+
}
289+
if (op == set_flags) {
290+
attr = fs_mask;
291+
} else {
292+
attr |= fs_mask;
293+
if (op == rm_flags) {
294+
attr ^= fs_mask;
295+
}
296+
}
297+
if (verbosity > 1) {
298+
fprintf(
299+
stderr,
300+
"attr(after)=%0X,fs_mask=%0X\n",
301+
attr,
302+
fs_mask);
303+
}
304+
305+
if (ioctl(fd, FS_IOC_SETFLAGS, &attr) == -1) {
306+
fprintf(
307+
stderr,
308+
"%s: Set flags from '%s' failed: %m\n",
309+
pgm_name,
310+
file_name);
311+
exit(EXIT_FAILURE);
312+
}
142313

143314
exit(EXIT_SUCCESS);
144315
}

‎15_File_Attributes/run_test_chattr.sh‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,16 @@ do
9090
case "${fs_file}" in
9191
*base*)
9292
chattr "${mode}" "${fs_file}"
93-
result_file=$(echo "${fs_file}" | sed -re 's!.*/([^/]+)_base/target!1円!')"${mode}"
93+
result_file=$(echo "${fs_file}" | \
94+
sed -re 's!.*/([^/]+)_base/target!1円!')"${mode}"
9495
printf '%s: %s %s\n' "${mode}" $(lsattr "${fs_file}") | \
9596
sed -re 's!.*: (.*) .*/target!1円!' \
9697
>"base_results/${result_file}"
9798
;;
9899
*mine*)
99100
./my_chattr "${mode}" "${fs_file}"
100-
result_file=$(echo "${fs_file}" | sed -re 's!.*/([^/]+)_mine/target!1円!')"${mode}"
101+
result_file=$(echo "${fs_file}" | \
102+
sed -re 's!.*/([^/]+)_mine/target!1円!')"${mode}"
101103
printf '%s: %s %s\n' "${mode}" $(lsattr "${fs_file}") | \
102104
sed -re 's!.*: (.*) .*/target!1円!' \
103105
>"mine_results/${result_file}"

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /