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