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+ 5571int  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}
0 commit comments