libexplain
1.4.D001
|
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 : */