xfstests: some refinements on "make depend"
[xfstests-dev.git] / lib / open_flags.c
1 /*
2  * Copyright (c) 2000 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  *
20  *    OS Testing - Silicon Graphics, Inc.
21  *
22  *    FUNCTION NAME     : parse_open_flags
23  *                        openflags2symbols
24  *
25  *    FUNCTION TITLE    : converts open flag symbols into bitmask
26  *                        converts open flag bitmask into symbols
27  *
28  *    SYNOPSIS:
29  *      int parse_open_flags(symbols, badname)
30  *      char *symbols;
31  *      char **badname;
32  *
33  *      char *openflags2symbols(openflags, sep, mode)
34  *      int openflags;
35  *      char *sep;
36  *      int mode;
37  *
38  *    AUTHOR            : Richard Logan
39  *
40  *    CO-PILOT(s)       : Dean Roehrich
41  *
42  *    INITIAL RELEASE   : UNICOS 8.0
43  *
44  *    DESIGN DESCRIPTION
45  *      The parse_open_flags function can be used to convert
46  *      a list of comma separated open(2) flag symbols (i.e. O_TRUNC)
47  *      into the bitmask that can be used by open(2).
48  *      If a symbol is unknown and <badname> is not NULL, <badname>
49  *      will updated to point that symbol in <string>.
50  *      Parse_open_flags will return -1 on this error.
51  *      Otherwise parse_open_flags will return the open flag bitmask.
52  *      If parse_open_flags returns, <string> will left unchanged.
53  *
54  *      The openflags2symbols function attempts to convert open flag
55  *      bits into human readable  symbols (i.e. O_TRUNC).  If there 
56  *      are more than one symbol, the <sep> string will be placed as
57  *      a separator between symbols.  Commonly used separators would
58  *      be a comma "," or pipe "|".  If <mode> is one and not all 
59  *      <openflags> bits can be converted to symbols, the "UNKNOWN"
60  *      symbol will be added to return string.
61  *      Openflags2symbols will return the indentified symbols.
62  *      If no symbols are recognized the return value will be a empty
63  *      string or the "UNKNOWN" symbol.
64  *
65  *    SPECIAL REQUIREMENTS
66  *      None.
67  *
68  *    UPDATE HISTORY
69  *      This should contain the description, author, and date of any
70  *      "interesting" modifications (i.e. info should helpful in
71  *      maintaining/enhancing this module).
72  *      username     description
73  *      ----------------------------------------------------------------
74  *      rrl    This code was first created during the beginning
75  *              of the SFS testing days.  I think that was in 1993.
76  *             This code was updated in 05/96.
77  *              (05/96)  openflags2symbols was written.
78  *
79  *    BUGS/LIMITATIONS
80  *      Currently (05/96) all known symbols are coded into openflags2symbols.
81  *      If new open flags are added this code will have to updated
82  *      to know about them or they will not be recognized.
83  *
84  **************************************************************/
85
86 #include <stdio.h>
87 #include <unistd.h>
88 #include <fcntl.h>
89 #include <sys/param.h>
90 #include <string.h> /* strcat */
91 #include "open_flags.h"
92
93 #define UNKNOWN_SYMBOL  "UNKNOWN"
94
95 static char Open_symbols[512];    /* space for openflags2symbols return value */
96
97 struct open_flag_t {
98     char *symbol;
99     int  flag;
100 };
101
102 static struct open_flag_t Open_flags[] = {
103     { "O_RDONLY",       O_RDONLY },
104     { "O_WRONLY",       O_WRONLY },
105     { "O_RDWR",         O_RDWR },
106     { "O_SYNC",         O_SYNC },
107     { "O_CREAT",        O_CREAT },
108     { "O_TRUNC",        O_TRUNC },
109     { "O_EXCL",         O_EXCL },
110     { "O_APPEND",       O_APPEND },
111     { "O_NONBLOCK",     O_NONBLOCK },
112 #if O_NOCTTY
113     { "O_NOCTTY",       O_NOCTTY },
114 #endif
115 #if O_DSYNC
116     { "O_DSYNC",        O_DSYNC },
117 #endif
118 #if O_RSYNC
119     { "O_RSYNC",        O_RSYNC },
120 #endif
121 #if O_ASYNC
122     { "O_ASYNC",        O_ASYNC },
123 #endif
124 #if O_PTYIGN
125     { "O_PTYIGN",       O_PTYIGN },
126 #endif
127 #if O_NDELAY
128     { "O_NDELAY",       O_NDELAY },
129 #endif
130 #if O_RAW
131     { "O_RAW",          O_RAW },
132 #endif
133 #ifdef O_SSD
134     { "O_SSD",          O_SSD },
135 #endif
136 #if O_BIG
137     { "O_BIG",          O_BIG },
138 #endif
139 #if O_PLACE
140     { "O_PLACE",        O_PLACE },
141 #endif
142 #if O_RESTART
143     { "O_RESTART",      O_RESTART },
144 #endif
145 #if O_SFSXOP
146     { "O_SFSXOP",       O_SFSXOP },
147 #endif
148 #if O_SFS_DEFER_TM
149     { "O_SFS_DEFER_TM", O_SFS_DEFER_TM },
150 #endif
151 #if O_WELLFORMED
152     { "O_WELLFORMED",   O_WELLFORMED },
153 #endif
154 #if O_LDRAW
155     { "O_LDRAW",        O_LDRAW },
156 #endif
157 #if O_T3D
158     { "O_T3D",  O_T3D },
159 #endif /* O_T3D */
160 #if O_PARALLEL
161     { "O_PARALLEL",     O_PARALLEL },
162     { "O_FSA",  O_PARALLEL|O_WELLFORMED|O_RAW },        /* short cut */
163 #endif /* O_PARALLEL */
164 #ifdef O_LARGEFILE
165     { "O_LARGEFILE",    O_LARGEFILE },
166 #endif
167 #ifdef O_DIRECT
168     { "O_DIRECT",       O_DIRECT },
169 #endif
170 #ifdef O_PRIV
171     { "O_PRIV",         O_PRIV },
172 #endif
173
174 };
175
176 int 
177 parse_open_flags(char *string, char **badname)
178 {
179    int  bits = 0;
180    char *name;
181    char *cc;
182    char savecc;
183    int  found;
184    int  ind;
185
186    name=string;
187    cc=name;
188
189    while ( 1 ) {
190
191       for(; ((*cc != ',') && (*cc != '\0')); cc++);
192       savecc = *cc;
193       *cc = '\0';
194
195       found = 0;
196
197       for(ind=0; ind < sizeof(Open_flags)/sizeof(struct open_flag_t); ind++) {
198           if ( strcmp(name, Open_flags[ind].symbol) == 0 ) {
199               bits |= Open_flags[ind].flag;
200               found=1;
201               break;
202           }
203       }
204
205       *cc = savecc;     /* restore string */
206
207       if ( found == 0 ) {       /* invalid name */
208          if ( badname != NULL )
209            *badname = name;
210          return -1;
211       }
212
213       if ( savecc == '\0' )
214         break;
215
216       name = ++cc;
217
218    }    /* end while */
219
220    return bits;
221
222 }       /* end of parse_open_flags */
223
224
225 char *
226 openflags2symbols(int openflags, char *sep, int mode)
227 {
228     int ind;
229     int size;
230     int bits = openflags;
231     int havesome=0;
232
233     Open_symbols[0]='\0';
234
235     size=sizeof(Open_flags)/sizeof(struct open_flag_t);
236
237     /*
238      * Deal with special case of O_RDONLY.  If O_WRONLY nor O_RDWR
239      * bits are not set, assume O_RDONLY.
240      */
241
242     if ( (bits & (O_WRONLY | O_RDWR)) == 0 ) {
243         strcat(Open_symbols, "O_RDONLY");
244         havesome=1;
245     }
246
247     /*
248      *  Loop through all but O_RDONLY elments of Open_flags
249      */
250     for(ind=1; ind < size; ind++) {
251           
252         if ( (bits & Open_flags[ind].flag) == Open_flags[ind].flag ) {
253             if ( havesome ) 
254                 strcat(Open_symbols, sep);
255
256             strcat(Open_symbols, Open_flags[ind].symbol);
257             havesome++;
258
259             /* remove flag bits from bits */
260             bits = bits & (~Open_flags[ind].flag);
261         }
262     }
263
264     /*
265      * If not all bits were identified and mode was equal to 1,
266      * added UNKNOWN_SYMBOL to return string
267      */
268     if ( bits && mode == 1 )  {    /* not all bits were identified */
269         if ( havesome )
270             strcat(Open_symbols, sep);
271         strcat(Open_symbols,  UNKNOWN_SYMBOL);
272     }
273
274     return Open_symbols;
275
276 }   /* end of openflags2symbols */
277
278
279 #ifdef UNIT_TEST
280
281 /*
282  * The following code provides a UNIT test main for
283  * parse_open_flags and openflags2symbols functions.
284  */
285
286 int
287 main(argc, argv)
288 int argc;
289 char **argv;
290 {
291     int bits;
292     int ret;
293     char *err;
294
295     if (argc == 1 ) {
296         printf("Usage: %s openflagsbits\n\t%s symbols\n", argv[0], argv[0]);
297         exit(1);
298     }
299
300     if ( sscanf(argv[1], "%i", &bits) == 1 ) {
301         printf("openflags2symbols(%#o, \",\", 1) returned %s\n",
302             bits, openflags2symbols(bits, ",", 1));
303         
304     } else {
305         ret=parse_open_flags(argv[1], &err);
306         if ( ret == -1 )
307             printf("parse_open_flags(%s, &err) returned -1, err = %s\n", 
308                 argv[0], err);
309         else
310             printf("parse_open_flags(%s, &err) returned %#o\n", argv[0], ret);
311     }
312
313     exit(0);
314 }
315
316 #endif /* end of UNIT_TEST */