/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
*/
/**************************************************************
*
* OS Testing - Silicon Graphics, Inc.
*
* FUNCTION NAME : parse_open_flags
* openflags2symbols
*
* FUNCTION TITLE : converts open flag symbols into bitmask
* converts open flag bitmask into symbols
*
* SYNOPSIS:
* int parse_open_flags(symbols, badname)
* char *symbols;
* char **badname;
*
* char *openflags2symbols(openflags, sep, mode)
* int openflags;
* char *sep;
* int mode;
*
* AUTHOR : Richard Logan
*
* CO-PILOT(s) : Dean Roehrich
*
* INITIAL RELEASE : UNICOS 8.0
*
* DESIGN DESCRIPTION
* The parse_open_flags function can be used to convert
* a list of comma separated open(2) flag symbols (i.e. O_TRUNC)
* into the bitmask that can be used by open(2).
* If a symbol is unknown and <badname> is not NULL, <badname>
* will updated to point that symbol in <string>.
* Parse_open_flags will return -1 on this error.
* Otherwise parse_open_flags will return the open flag bitmask.
* If parse_open_flags returns, <string> will left unchanged.
*
* The openflags2symbols function attempts to convert open flag
* bits into human readable symbols (i.e. O_TRUNC). If there
* are more than one symbol, the <sep> string will be placed as
* a separator between symbols. Commonly used separators would
* be a comma "," or pipe "|". If <mode> is one and not all
* <openflags> bits can be converted to symbols, the "UNKNOWN"
* symbol will be added to return string.
* Openflags2symbols will return the indentified symbols.
* If no symbols are recognized the return value will be a empty
* string or the "UNKNOWN" symbol.
*
* SPECIAL REQUIREMENTS
* None.
*
* UPDATE HISTORY
* This should contain the description, author, and date of any
* "interesting" modifications (i.e. info should helpful in
* maintaining/enhancing this module).
* username description
* ----------------------------------------------------------------
* rrl This code was first created during the beginning
* of the SFS testing days. I think that was in 1993.
* This code was updated in 05/96.
* (05/96) openflags2symbols was written.
*
* BUGS/LIMITATIONS
* Currently (05/96) all known symbols are coded into openflags2symbols.
* If new open flags are added this code will have to updated
* to know about them or they will not be recognized.
*
**************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <string.h> /* strcat */
#include "open_flags.h"
#define UNKNOWN_SYMBOL "UNKNOWN"
static char Open_symbols[512]; /* space for openflags2symbols return value */
struct open_flag_t {
char *symbol;
int flag;
};
static struct open_flag_t Open_flags[] = {
{"O_RDONLY", O_RDONLY},
{"O_WRONLY", O_WRONLY},
{"O_RDWR", O_RDWR},
{"O_SYNC", O_SYNC},
{"O_CREAT", O_CREAT},
{"O_TRUNC", O_TRUNC},
{"O_EXCL", O_EXCL},
{"O_APPEND", O_APPEND},
{"O_NONBLOCK", O_NONBLOCK},
#if O_NOCTTY
{"O_NOCTTY", O_NOCTTY},
#endif
#if O_DSYNC
{"O_DSYNC", O_DSYNC},
#endif
#if O_RSYNC
{"O_RSYNC", O_RSYNC},
#endif
#if O_ASYNC
{"O_ASYNC", O_ASYNC},
#endif
#if O_PTYIGN
{"O_PTYIGN", O_PTYIGN},
#endif
#if O_NDELAY
{"O_NDELAY", O_NDELAY},
#endif
#if O_RAW
{"O_RAW", O_RAW},
#endif
#ifdef O_SSD
{"O_SSD", O_SSD},
#endif
#if O_BIG
{"O_BIG", O_BIG},
#endif
#if O_PLACE
{"O_PLACE", O_PLACE},
#endif
#if O_RESTART
{"O_RESTART", O_RESTART},
#endif
#if O_SFSXOP
{"O_SFSXOP", O_SFSXOP},
#endif
#if O_SFS_DEFER_TM
{"O_SFS_DEFER_TM", O_SFS_DEFER_TM},
#endif
#if O_WELLFORMED
{"O_WELLFORMED", O_WELLFORMED},
#endif
#if O_LDRAW
{"O_LDRAW", O_LDRAW},
#endif
#if O_T3D
{"O_T3D", O_T3D},
#endif /* O_T3D */
#if O_PARALLEL
{"O_PARALLEL", O_PARALLEL},
{"O_FSA", O_PARALLEL | O_WELLFORMED | O_RAW}, /* short cut */
#endif /* O_PARALLEL */
#ifdef O_LARGEFILE
{"O_LARGEFILE", O_LARGEFILE},
#endif
#ifdef O_DIRECT
{"O_DIRECT", O_DIRECT},
#endif
#ifdef O_PRIV
{"O_PRIV", O_PRIV},
#endif
};
int parse_open_flags(char *string, char **badname)
{
int bits = 0;
char *name;
char *cc;
char savecc;
int found;
unsigned int ind;
name = string;
cc = name;
while (1) {
for (; ((*cc != ',') && (*cc != '\0')); cc++) ;
savecc = *cc;
*cc = '\0';
found = 0;
for (ind = 0;
ind < sizeof(Open_flags) / sizeof(struct open_flag_t);
ind++) {
if (strcmp(name, Open_flags[ind].symbol) == 0) {
bits |= Open_flags[ind].flag;
found = 1;
break;
}
}
*cc = savecc; /* restore string */
if (found == 0) { /* invalid name */
if (badname != NULL)
*badname = name;
return -1;
}
if (savecc == '\0')
break;
name = ++cc;
} /* end while */
return bits;
} /* end of parse_open_flags */
char *openflags2symbols(int openflags, char *sep, int mode)
{
int ind;
int size;
int bits = openflags;
int havesome = 0;
Open_symbols[0] = '\0';
size = sizeof(Open_flags) / sizeof(struct open_flag_t);
/*
* Deal with special case of O_RDONLY. If O_WRONLY nor O_RDWR
* bits are not set, assume O_RDONLY.
*/
if ((bits & (O_WRONLY | O_RDWR)) == 0) {
strcat(Open_symbols, "O_RDONLY");
havesome = 1;
}
/*
* Loop through all but O_RDONLY elments of Open_flags
*/
for (ind = 1; ind < size; ind++) {
if ((bits & Open_flags[ind].flag) == Open_flags[ind].flag) {
if (havesome)
strcat(Open_symbols, sep);
strcat(Open_symbols, Open_flags[ind].symbol);
havesome++;
/* remove flag bits from bits */
bits = bits & (~Open_flags[ind].flag);
}
}
/*
* If not all bits were identified and mode was equal to 1,
* added UNKNOWN_SYMBOL to return string
*/
if (bits && mode == 1) { /* not all bits were identified */
if (havesome)
strcat(Open_symbols, sep);
strcat(Open_symbols, UNKNOWN_SYMBOL);
}
return Open_symbols;
} /* end of openflags2symbols */
#ifdef UNIT_TEST
/*
* The following code provides a UNIT test main for
* parse_open_flags and openflags2symbols functions.
*/
int main(argc, argv)
int argc;
char **argv;
{
int bits;
int ret;
char *err;
if (argc == 1) {
printf("Usage: %s openflagsbits\n\t%s symbols\n", argv[0],
argv[0]);
exit(1);
}
if (sscanf(argv[1], "%i", &bits) == 1) {
printf("openflags2symbols(%#o, \",\", 1) returned %s\n",
bits, openflags2symbols(bits, ",", 1));
} else {
ret = parse_open_flags(argv[1], &err);
if (ret == -1)
printf
("parse_open_flags(%s, &err) returned -1, err = %s\n",
argv[0], err);
else
printf("parse_open_flags(%s, &err) returned %#o\n",
argv[0], ret);
}
exit(0);
}
#endif /* end of UNIT_TEST */