xfstests: eliminate warnings under dmapi/src/suite1/cmd (3)
[xfstests-dev.git] / dmapi / src / suite1 / cmd / set_fileattr.c
1 /*
2  * Copyright (c) 2000-2001 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include <ctype.h>
20 #include <time.h>
21
22 #include <lib/hsm.h>
23
24 #include <getopt.h>
25 #include <string.h>
26
27
28
29 extern  int     optind;
30 extern  int     opterr;
31 extern  char    *optarg;
32
33 char            *Progname;
34
35 #define MIN_HD_DATE     19800101
36 #define MIN_HD_TMSTAMP  315554400       /* timestamp of 19800101 */
37
38 static  int     dayno, day_of_week;
39 static  int     leap_year;
40
41 /*
42  * The following table is used for USA daylight savings time and
43  * gives the day number of the first day after the Sunday of the
44  * change.
45  */
46 static struct {
47         int     yrbgn;
48         int     daylb;
49         int     dayle;
50 } daytab[] = {
51         {1987,  96,     303},   /* new legislation - 1st Sun in April */
52         {1976,  119,    303},   /* normal Last Sun in Apr - last Sun in Oct */
53         {1975,  58,     303},   /* 1975: Last Sun in Feb - last Sun in Oct */
54         {1974,  5,      333},   /* 1974: Jan 6 - last Sun. in Nov */
55         {1970,  119,    303},   /* start GMT */
56 };
57 #define DAYTABSIZE (sizeof(daytab)/sizeof(daytab[0]))
58
59
60 /******************************************************************************
61 * NAME
62 *       dysize
63 *
64 * DESCRIPTION
65 *       Return number of days in year y.
66 *
67 ******************************************************************************/
68
69 int
70 dysize(int y)
71 {
72         int     temp;
73         temp = (y%4)==0;
74         if (temp) {
75                 if ( (y%100)==0) 
76                         temp = ( (y%400) != 0);
77         }
78         return(365+temp);
79 }
80
81 /******************************************************************************
82 * NAME
83 *       sunday
84 *
85 * DESCRIPTION
86 *       sunday - return sunday daynumber.  Argument d is the day number of the
87 *       first Sunday on or before the special day.  Variables leap_year, dayno,
88 *       and day_of_week must have been set before sunday is called.
89 *
90 * RETURN VALUE
91 *       The sunday daynumber.
92 *
93 ******************************************************************************/
94
95 static int
96 sunday(int d)
97 {
98         if(d >= 58)
99                 d += leap_year;
100         return(d - (d - dayno + day_of_week + 700) % 7);
101 }
102
103
104 extern  long 
105 cnvdate(int mon, int mday, int year, int hour, int min, int sec)
106 {
107         int     t, i;
108         int     daylbegin, daylend;
109         int     ly_correction;  /* Leap Year Correction */
110         int     dl_correction;  /* Daylight Savings Time Correction */
111         long    s;
112         static int days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
113
114         days[2] = 28;
115
116         /* Verify Input Parameters. */
117  
118         /*      Set  year. */
119
120         if( year < 0) {
121                 return(-1);
122         }
123         if( year < 100) {
124                 if (year < 70) year += 2000;
125                 else year += 1900;
126         }
127         if (year < 1970) {
128                 return(-1);
129         }
130         if( year>2099 ) {
131                 return(-1);
132         }
133
134         if (dysize(year) == 366) {
135                 leap_year = 1;
136                 days[2]++;
137         } else  
138                 leap_year = 0;
139         /*
140          * Set ly_correction = number of leap year days from 1/1/1970 to
141          * 1/1/year.
142          */
143         ly_correction =  ((year-1969) / 4);
144
145         /* Check Month */
146
147         if( (mon < 1) || (mon > 12)) {
148                 return(-1);
149         }
150
151         /* Check Day */
152
153         if ( (mday < 1) || (mday > days[mon]) ) {
154                 return(-1);
155         }
156
157         /* Check Time */
158
159         if( (hour<0) || (hour>23)) {
160                 return(-1);
161         }
162         if( (min<0) || (min>59)) {
163                 return(-1);
164         }
165         if( (sec<0) || (sec>59)) {
166                 return(-1);
167         }
168
169         /* Calculate Correction for Daylight Savings Time (U.S.) */
170
171         dayno = mday-1;
172         for (t=0; t<mon;)
173                 dayno += days[t++];
174         s = (year-1970)*365L + ly_correction + dayno;
175         day_of_week = (s + 4) % 7;
176
177         i = 0;
178         while (year < daytab[i].yrbgn) { 
179                 /* fall through when in correct interval */ 
180                 i++;
181                 if (i>DAYTABSIZE)
182                         return(-1);
183         }
184         daylbegin = daytab[i].daylb; 
185         daylend = daytab[i].dayle;
186
187         daylbegin = sunday(daylbegin);
188         daylend = sunday(daylend);
189         if(daylight &&
190             (dayno>daylbegin || (dayno==daylbegin && hour>=2)) &&
191             (dayno<daylend || (dayno==daylend && hour<1)))
192                 dl_correction = -1*60*60;
193         else
194                 dl_correction = 0;
195
196         /* Calculate seconds since 00:00:00 1/1/1970. */
197
198         s = ( ( s*24 +hour)*60 +min)*60 + sec + dl_correction;
199         return(s+timezone);
200 }
201
202
203 /* Cracks dates in the form YYYYMMDD and YYYYMMDDHHMMSS.  */
204
205 static int
206 get_absolute_date(
207         char    *ptr,
208         time_t  *timestamp)
209 {
210         int     l;
211         int     yr;
212         int     mon;
213         int     day;
214         int     hr;
215         int     mn;
216         int     sec;
217         char    date[9];
218         char    *last_char;
219
220         if (strlen(ptr) != 8 && strlen(ptr) != 14)
221                 return(0);
222         strncpy(date, ptr, 8);
223         date[8] = '\0';
224         l = atol(date);
225         if (l < MIN_HD_DATE)
226                 return(0);
227         yr = l / 10000;
228         l = l % 10000;
229         mon = l / 100;
230         if (mon < 0 || mon > 12)
231                 return(0);
232         day = l % 100;
233
234         /* Note: invalid day numbers are caught in cnvdate */
235
236         ptr+=8;
237
238         l = strtol(ptr, &last_char, 10);
239         if (l < 0 || l>235959 || *last_char != '\0')
240                 return(0);
241         hr = l / 10000;
242         if (hr > 23)
243                 return(0);
244         l = l % 10000;
245         mn = l / 100;
246         if (mn > 59)
247                 return(0);
248         sec = l % 100;
249         if (sec > 59)
250                 return(0);
251
252         /* Get timestamp. */
253
254         (void)tzset();
255         if ((*timestamp = cnvdate(mon, day, yr, hr, mn, sec)) < 0) {
256                 return(0);
257         }
258
259         return(1);
260 }
261
262
263 /* Cracks dates in the form:   NNs, NNm, NNh, or NNd which are interpreted
264    as NN seconds, minutes, hours, or days prior to the current time, 
265    respectively.
266 */
267
268 static int
269 get_relative_date(
270         char    *ptr,
271         time_t  *timestamp)
272 {
273         int     l;
274         char    *last_char;
275
276         if (!isdigit(*ptr))
277                 return(0);
278         l = strtol (ptr, &last_char, 10);
279         (void) time(timestamp);
280         if (strcmp(last_char, "s") == 0)
281                 /* do nothing */;
282         else if (strcmp(last_char, "m") == 0)
283                 l = l * 60;
284         else if (strcmp(last_char, "h") == 0)
285                 l = l * 60 * 60;
286         else if (strcmp(last_char, "d") == 0)
287                 l = l * 60 * 60 * 24;
288         else
289                 return(0);
290         *timestamp -= l;
291         if (*timestamp < MIN_HD_TMSTAMP)
292                 return(0);
293         return(1);
294 }
295
296
297 static void
298 usage(void)
299 {
300         fprintf(stderr, "Usage: %s [-M mode] [-u uid] [-g gid] [-a atime] \\\n"
301                 "\t[-m mtime] [-c ctime] [-d dtime] [-S size] [-s sid] pathname\n",
302                 Progname);
303         fprintf(stderr, "\nDates can either be absolute:\n");
304         fprintf(stderr, "\t\tYYYYMMDD or YYYYMMDDHHMMSS\n");
305         fprintf(stderr, "or relative (prior to) the current time:\n");
306         fprintf(stderr, "\tNNs (seconds), NNm (minutes), NNh (hours), "
307                 " or NNd (days)\n");
308         exit(1);
309 }
310
311
312 int
313 main(
314         int     argc,
315         char    **argv)
316 {
317         dm_sessid_t     sid = DM_NO_SESSION;
318         void            *hanp;
319         size_t          hlen;
320         dm_fileattr_t   fileattr;
321         u_int           mask = 0;
322         char            *pathname;
323         char            *name;
324         int             opt;
325
326         Progname = strrchr(argv[0], '/');
327         if (Progname) {
328                 Progname++;
329         } else {
330                 Progname = argv[0];
331         }
332
333         opterr = 0;
334         while ((opt = getopt(argc, argv, "M:u:g:a:m:c:d:S:s:")) != EOF) {
335                 switch (opt) {
336                 case 'M':
337                         mask |= DM_AT_MODE;
338                         fileattr.fa_mode = strtol (optarg, NULL, 8);
339                         break;
340                 case 'u':
341                         mask |= DM_AT_UID;
342                         fileattr.fa_uid = atol(optarg);
343                         break;
344                 case 'g':
345                         mask |= DM_AT_GID;
346                         fileattr.fa_gid = atol(optarg);
347                         break;
348                 case 'a':
349                         mask |= DM_AT_ATIME;
350                         if (get_absolute_date(optarg, &fileattr.FA_ATIME))
351                                 break;
352                         if (get_relative_date(optarg, &fileattr.FA_ATIME))
353                                 break;
354                         usage();
355                 case 'm':
356                         mask |= DM_AT_MTIME;
357                         if (get_absolute_date(optarg, &fileattr.FA_MTIME))
358                                 break;
359                         if (get_relative_date(optarg, &fileattr.FA_MTIME))
360                                 break;
361                         usage();
362                 case 'c':
363                         mask |= DM_AT_CTIME;
364                         if (get_absolute_date(optarg, &fileattr.FA_CTIME))
365                                 break;
366                         if (get_relative_date(optarg, &fileattr.FA_CTIME))
367                                 break;
368                         usage();
369                 case 'd':
370                         mask |= DM_AT_DTIME;
371                         if (get_absolute_date(optarg, &fileattr.FA_DTIME))
372                                 break;
373                         if (get_relative_date(optarg, &fileattr.FA_DTIME))
374                                 break;
375                         usage();
376                 case 'S':
377                         mask |= DM_AT_SIZE;
378                         fileattr.fa_size = atol(optarg);
379                         break;
380                 case 's':
381                         sid = atol(optarg);
382                         break;
383                 case '?':
384                         usage();
385                 }
386         }
387         if (optind + 1 != argc) {
388                 usage();
389         }
390         pathname = argv[optind];
391
392         if (dm_init_service(&name) == -1)  {
393                 fprintf(stderr, "Can't initialize the DMAPI\n");
394                 exit(1);
395         }
396         if (sid == DM_NO_SESSION)
397                 find_test_session(&sid);
398
399         if (dm_path_to_handle(pathname, &hanp, &hlen)) {
400                 fprintf(stderr, "dm_path_to_handle failed, %s\n",
401                         strerror(errno));
402                 exit(1);
403         }
404
405         if (dm_set_fileattr(sid, hanp, hlen, DM_NO_TOKEN, mask, &fileattr)) {
406                 fprintf(stderr, "dm_set_fileattr failed, %s\n",
407                         strerror(errno));
408                 exit(1);
409         }
410         exit(0);
411 }