| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2000 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| /************************************************************** |
| * |
| * 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; |
| 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 */ |