Home | History | Annotate | Download | only in doio
      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.,
     21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 parse_open_flags(char *string, char **badname)
    191 {
    192 	int bits = 0;
    193 	char *name;
    194 	char *cc;
    195 	char savecc;
    196 	int found;
    197 	unsigned int ind;
    198 
    199 	name = string;
    200 	cc = name;
    201 
    202 	while (1) {
    203 
    204 		for (; ((*cc != ',') && (*cc != '\0')); cc++) ;
    205 		savecc = *cc;
    206 		*cc = '\0';
    207 
    208 		found = 0;
    209 
    210 		for (ind = 0;
    211 		     ind < sizeof(Open_flags) / sizeof(struct open_flag_t);
    212 		     ind++) {
    213 			if (strcmp(name, Open_flags[ind].symbol) == 0) {
    214 				bits |= Open_flags[ind].flag;
    215 				found = 1;
    216 				break;
    217 			}
    218 		}
    219 
    220 		*cc = savecc;	/* restore string */
    221 
    222 		if (found == 0) {	/* invalid name */
    223 			if (badname != NULL)
    224 				*badname = name;
    225 			return -1;
    226 		}
    227 
    228 		if (savecc == '\0')
    229 			break;
    230 
    231 		name = ++cc;
    232 
    233 	}			/* end while */
    234 
    235 	return bits;
    236 
    237 }				/* end of parse_open_flags */
    238 
    239 char *openflags2symbols(int openflags, char *sep, int mode)
    240 {
    241 	int ind;
    242 	int size;
    243 	int bits = openflags;
    244 	int havesome = 0;
    245 
    246 	Open_symbols[0] = '\0';
    247 
    248 	size = sizeof(Open_flags) / sizeof(struct open_flag_t);
    249 
    250 	/*
    251 	 * Deal with special case of O_RDONLY.  If O_WRONLY nor O_RDWR
    252 	 * bits are not set, assume O_RDONLY.
    253 	 */
    254 
    255 	if ((bits & (O_WRONLY | O_RDWR)) == 0) {
    256 		strcat(Open_symbols, "O_RDONLY");
    257 		havesome = 1;
    258 	}
    259 
    260 	/*
    261 	 *  Loop through all but O_RDONLY elments of Open_flags
    262 	 */
    263 	for (ind = 1; ind < size; ind++) {
    264 
    265 		if ((bits & Open_flags[ind].flag) == Open_flags[ind].flag) {
    266 			if (havesome)
    267 				strcat(Open_symbols, sep);
    268 
    269 			strcat(Open_symbols, Open_flags[ind].symbol);
    270 			havesome++;
    271 
    272 			/* remove flag bits from bits */
    273 			bits = bits & (~Open_flags[ind].flag);
    274 		}
    275 	}
    276 
    277 	/*
    278 	 * If not all bits were identified and mode was equal to 1,
    279 	 * added UNKNOWN_SYMBOL to return string
    280 	 */
    281 	if (bits && mode == 1) {	/* not all bits were identified */
    282 		if (havesome)
    283 			strcat(Open_symbols, sep);
    284 		strcat(Open_symbols, UNKNOWN_SYMBOL);
    285 	}
    286 
    287 	return Open_symbols;
    288 
    289 }				/* end of openflags2symbols */
    290 
    291 #ifdef UNIT_TEST
    292 
    293 /*
    294  * The following code provides a UNIT test main for
    295  * parse_open_flags and openflags2symbols functions.
    296  */
    297 
    298 int main(argc, argv)
    299 int argc;
    300 char **argv;
    301 {
    302 	int bits;
    303 	int ret;
    304 	char *err;
    305 
    306 	if (argc == 1) {
    307 		printf("Usage: %s openflagsbits\n\t%s symbols\n", argv[0],
    308 		       argv[0]);
    309 		exit(1);
    310 	}
    311 
    312 	if (sscanf(argv[1], "%i", &bits) == 1) {
    313 		printf("openflags2symbols(%#o, \",\", 1) returned %s\n",
    314 		       bits, openflags2symbols(bits, ",", 1));
    315 
    316 	} else {
    317 		ret = parse_open_flags(argv[1], &err);
    318 		if (ret == -1)
    319 			printf
    320 			    ("parse_open_flags(%s, &err) returned -1, err = %s\n",
    321 			     argv[0], err);
    322 		else
    323 			printf("parse_open_flags(%s, &err) returned %#o\n",
    324 			       argv[0], ret);
    325 	}
    326 
    327 	exit(0);
    328 }
    329 
    330 #endif /* end of UNIT_TEST */
    331