libexplain  1.4.D001
libexplain/buffer/open_flags.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2008-2010, 2012, 2013 Peter Miller
00004  * Written by Peter Miller <pmiller@opensource.org.au>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 3 of the License, or (at
00009  * your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include <libexplain/ac/fcntl.h>
00021 
00022 #include <libexplain/buffer/open_flags.h>
00023 #include <libexplain/parse_bits.h>
00024 #include <libexplain/sizeof.h>
00025 #include <libexplain/string_buffer.h>
00026 
00027 #ifndef O_DIRECT
00028 #define O_DIRECT 0
00029 #endif
00030 #ifndef O_DIRECTORY
00031 #define O_DIRECTORY 0
00032 #endif
00033 #ifndef O_NOFOLLOW
00034 #define O_NOFOLLOW 0
00035 #endif
00036 #ifndef O_NOATIME
00037 #define O_NOATIME 0
00038 #endif
00039 #ifndef O_CLOEXEC
00040 #define O_CLOEXEC 0
00041 #endif
00042 
00043 #ifndef O_LARGEFILE
00044 #if defined(__linux__) && defined(__sparc__) && defined(__arch64__)
00045 /* It is difficult to see just how this could ever come to pass.  Oh well. */
00046 #define O_LARGEFILE 0x40000
00047 #ifndef O_LARGEFILE_HIDDEN
00048 #define O_LARGEFILE_HIDDEN 0x40000
00049 #endif
00050 #else
00051 #define O_LARGEFILE 0
00052 #endif
00053 #endif
00054 
00055 static const explain_parse_bits_table_t table[] =
00056 {
00057     { "O_RDONLY", O_RDONLY },
00058     { "O_WRONLY", O_WRONLY },
00059     { "O_RDWR", O_RDWR },
00060     { "O_CREAT", O_CREAT },
00061     { "O_EXCL", O_EXCL },
00062 #ifdef O_NOCTTY
00063     { "O_NOCTTY", O_NOCTTY },
00064 #endif
00065     { "O_TRUNC", O_TRUNC },
00066     { "O_APPEND", O_APPEND },
00067 #ifdef FAPPEND
00068     { "FAPPEND", FAPPEND }, /* BSD */
00069 #endif
00070 #ifdef O_NONBLOCK
00071     { "O_NONBLOCK", O_NONBLOCK },
00072 #endif
00073 #ifdef FNONBLOCK
00074     { "FNONBLOCK", FNONBLOCK }, /* BSD */
00075 #endif
00076 #ifdef O_NDELAY
00077     { "O_NDELAY", O_NDELAY },
00078 #endif
00079 #ifdef FNDELAY
00080     { "FNDELAY", FNDELAY }, /* BSD */
00081 #endif
00082 #ifdef O_SYNC
00083     { "O_SYNC", O_SYNC },
00084 #endif
00085 
00086     /*
00087      * No, this isn't a mistake.  On Linux sparc there is a
00088      *
00089      *     #define FFSYNC O_FSYNC
00090      *
00091      * but O_FSYNC isn't actually defined, leading to a build failure.
00092      * Thus, the O_FSYNC bracketing goes around both of them.
00093      */
00094 #ifdef O_FSYNC
00095     { "O_FSYNC", O_FSYNC },
00096 #ifdef FFSYNC
00097     { "FFSYNC", FFSYNC }, /* BSD */
00098 #endif
00099 #endif
00100 
00101 #ifdef O_DSYNC
00102     { "O_DSYNC", O_DSYNC },
00103 #endif
00104 #ifdef O_RSYNC
00105     { "O_RSYNC", O_RSYNC },
00106 #endif
00107 #ifdef O_ASYNC
00108     { "O_ASYNC", O_ASYNC },
00109 #endif
00110 #ifdef FASYNC
00111     { "FASYNC", FASYNC }, /* BSD */
00112 #endif
00113 #ifdef O_DIRECT
00114     { "O_DIRECT", O_DIRECT },
00115 #endif
00116 #ifdef O_DIRECTORY
00117     { "O_DIRECTORY", O_DIRECTORY },
00118 #endif
00119 #ifdef O_NOFOLLOW
00120     { "O_NOFOLLOW", O_NOFOLLOW },
00121 #endif
00122 #ifdef O_NOATIME
00123     { "O_NOATIME", O_NOATIME },
00124 #endif
00125 #ifdef O_CLOEXEC
00126     { "O_CLOEXEC", O_CLOEXEC },
00127 #endif
00128 #ifdef O_LARGEFILE_HIDDEN
00129     { "O_LARGEFILE", O_LARGEFILE_HIDDEN },
00130 #endif
00131 #ifdef O_LARGEFILE
00132     { "O_LARGEFILE", O_LARGEFILE },
00133 #endif
00134 #ifdef O_BINARY
00135     { "O_BINARY", O_BINARY },
00136 #endif
00137 #ifdef O_TEXT
00138     { "O_TEXT", O_TEXT },
00139 #endif
00140 #ifdef O_NOINHERIT
00141     { "O_NOINHERIT", O_NOINHERIT },
00142 #endif
00143 #ifdef O_SEARCH
00144     /* open a directory for searchin only */
00145     { "O_SEARCH", O_SEARCH },
00146 #endif
00147 #ifdef O_EXEC
00148     /* open a regular file for execution only */
00149     { "O_EXEC", O_EXEC },
00150 #endif
00151 #ifdef O_TTY_INIT
00152     { "O_TTY_INIT", O_TTY_INIT },
00153 #endif
00154 };
00155 
00156 
00157 void
00158 explain_buffer_open_flags(explain_string_buffer_t *sb, int flags)
00159 {
00160     int             low_bits;
00161     int             other;
00162 
00163     low_bits = flags & O_ACCMODE;
00164     flags &= ~O_ACCMODE;
00165     switch (low_bits)
00166     {
00167     case O_RDONLY:
00168         explain_string_buffer_puts(sb, "O_RDONLY");
00169         break;
00170 
00171     case O_RDWR:
00172         explain_string_buffer_puts(sb, "O_RDWR");
00173         break;
00174 
00175     case O_WRONLY:
00176         explain_string_buffer_puts(sb, "O_WRONLY");
00177         break;
00178 
00179 #if defined(O_SEARCH) && O_SEARCH != 0
00180      case O_SEARCH:
00181         /* open a directory for searchin only */
00182         explain_string_buffer_puts(sb, "O_SEARCH");
00183         break;
00184 #endif
00185 
00186 #if defined(O_EXEC) && O_EXEC != 0
00187     case O_EXEC:
00188         /* open a regular file for execution only */
00189         explain_string_buffer_puts(sb, "O_EXEC");
00190         break;
00191 #endif
00192 
00193     default:
00194         explain_string_buffer_printf(sb, "%d", low_bits);
00195         break;
00196     }
00197     other = 0;
00198     while (flags != 0)
00199     {
00200         int             bit;
00201         const explain_parse_bits_table_t *tp;
00202 
00203         bit = (flags & -flags);
00204         flags &= ~bit;
00205         tp = explain_parse_bits_find_by_value(bit, table, SIZEOF(table));
00206         if (tp)
00207         {
00208             explain_string_buffer_puts(sb, " | ");
00209             explain_string_buffer_puts(sb, tp->name);
00210         }
00211         else
00212             other |= bit;
00213     }
00214     if (other != 0)
00215         explain_string_buffer_printf(sb, " | %#o", other);
00216 }
00217 
00218 
00219 int
00220 explain_parse_open_flags_or_die(const char *text, const char *caption)
00221 {
00222     return explain_parse_bits_or_die(text, table, SIZEOF(table), caption);
00223 }
00224 
00225 
00226 /* vim: set ts=8 sw=4 et : */