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