00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 #include <sys/stat.h>
00015
00016 #ifdef HAVE_SYS_FCNTL_H
00017 #include <sys/fcntl.h>
00018 #endif
00019
00020 #include <fcntl.h>
00021 #include <string.h>
00022 #endif
00023
00024 #include "db_int.h"
00025
00026 static int __os_intermediate_dir __P((DB_ENV *, const char *));
00027 #ifdef HAVE_QNX
00028 static int __os_region_open __P((DB_ENV *, const char *, int, int, DB_FH **));
00029 #endif
00030
00031
00032
00033
00034
00035
00036
00037 int
00038 __os_have_direct()
00039 {
00040 int ret;
00041
00042 ret = 0;
00043
00044 #ifdef HAVE_O_DIRECT
00045 ret = 1;
00046 #endif
00047 #if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON)
00048 ret = 1;
00049 #endif
00050 return (ret);
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060 int
00061 __os_open(dbenv, name, flags, mode, fhpp)
00062 DB_ENV *dbenv;
00063 const char *name;
00064 u_int32_t flags;
00065 int mode;
00066 DB_FH **fhpp;
00067 {
00068 return (__os_open_extend(dbenv, name, 0, flags, mode, fhpp));
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078 int
00079 __os_open_extend(dbenv, name, page_size, flags, mode, fhpp)
00080 DB_ENV *dbenv;
00081 const char *name;
00082 u_int32_t page_size, flags;
00083 int mode;
00084 DB_FH **fhpp;
00085 {
00086 DB_FH *fhp;
00087 int oflags, ret;
00088
00089 COMPQUIET(page_size, 0);
00090
00091 *fhpp = NULL;
00092 oflags = 0;
00093
00094 #define OKFLAGS \
00095 (DB_OSO_ABSMODE | DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_DSYNC |\
00096 DB_OSO_EXCL | DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | \
00097 DB_OSO_TEMP | DB_OSO_TRUNC)
00098 if ((ret = __db_fchk(dbenv, "__os_open", flags, OKFLAGS)) != 0)
00099 return (ret);
00100
00101 #if defined(O_BINARY)
00102
00103
00104
00105
00106
00107
00108 oflags |= O_BINARY;
00109 #endif
00110
00111
00112
00113
00114
00115
00116 if (LF_ISSET(DB_OSO_CREATE))
00117 oflags |= O_CREAT;
00118
00119 if (LF_ISSET(DB_OSO_EXCL))
00120 oflags |= O_EXCL;
00121
00122 #ifdef HAVE_O_DIRECT
00123 if (LF_ISSET(DB_OSO_DIRECT))
00124 oflags |= O_DIRECT;
00125 #endif
00126 #ifdef O_DSYNC
00127 if (LF_ISSET(DB_OSO_DSYNC))
00128 oflags |= O_DSYNC;
00129 #endif
00130
00131 if (LF_ISSET(DB_OSO_RDONLY))
00132 oflags |= O_RDONLY;
00133 else
00134 oflags |= O_RDWR;
00135
00136 if (LF_ISSET(DB_OSO_TRUNC))
00137 oflags |= O_TRUNC;
00138
00139
00140
00141
00142
00143 if (dbenv != NULL &&
00144 dbenv->dir_mode != 0 && LF_ISSET(DB_OSO_CREATE) &&
00145 (ret = __os_intermediate_dir(dbenv, name)) != 0)
00146 return (ret);
00147
00148 #ifdef HAVE_QNX
00149 if (LF_ISSET(DB_OSO_REGION))
00150 return (__os_qnx_region_open(dbenv, name, oflags, mode, fhpp));
00151 #endif
00152
00153 if ((ret = __os_openhandle(dbenv, name, oflags, mode, &fhp)) != 0)
00154 return (ret);
00155
00156 #ifdef HAVE_FCHMOD
00157
00158
00159
00160
00161
00162
00163
00164
00165 if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_ABSMODE))
00166 (void)fchmod(fhp->fd, mode);
00167 #endif
00168
00169 #ifdef O_DSYNC
00170
00171
00172
00173
00174 if (LF_ISSET(DB_OSO_DSYNC))
00175 F_SET(fhp, DB_FH_NOSYNC);
00176 #endif
00177
00178 #if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON)
00179
00180
00181
00182
00183
00184 if (LF_ISSET(DB_OSO_DIRECT))
00185 (void)directio(fhp->fd, DIRECTIO_ON);
00186 #endif
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 if (LF_ISSET(DB_OSO_TEMP)) {
00199 #if defined(HAVE_UNLINK_WITH_OPEN_FAILURE) || defined(CONFIG_TEST)
00200 if ((ret = __os_strdup(dbenv, name, &fhp->name)) != 0) {
00201 (void)__os_closehandle(dbenv, fhp);
00202 (void)__os_unlink(dbenv, name);
00203 return (ret);
00204 }
00205 F_SET(fhp, DB_FH_UNLINK);
00206 #else
00207 (void)__os_unlink(dbenv, name);
00208 #endif
00209 }
00210
00211 *fhpp = fhp;
00212 return (0);
00213 }
00214
00215 #ifdef HAVE_QNX
00216
00217
00218
00219
00220 static int
00221 __os_qnx_region_open(dbenv, name, oflags, mode, fhpp)
00222 DB_ENV *dbenv;
00223 const char *name;
00224 int oflags;
00225 int mode;
00226 DB_FH **fhpp;
00227 {
00228 DB_FH *fhp;
00229 int ret;
00230 char *newname;
00231
00232 if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), fhpp)) != 0)
00233 return (ret);
00234 fhp = *fhpp;
00235
00236 if ((ret = __os_shmname(dbenv, name, &newname)) != 0)
00237 goto err;
00238
00239
00240
00241
00242
00243 fhp->fd = shm_open(newname, oflags, mode);
00244 __os_free(dbenv, newname);
00245
00246 if (fhp->fd == -1) {
00247 ret = __os_get_errno();
00248 goto err;
00249 }
00250
00251 F_SET(fhp, DB_FH_OPENED);
00252
00253 #ifdef HAVE_FCNTL_F_SETFD
00254
00255 if (fcntl(fhp->fd, F_SETFD, 1) == -1) {
00256 ret = __os_get_errno();
00257 __db_err(dbenv, "fcntl(F_SETFD): %s", strerror(ret));
00258 goto err;
00259 }
00260 #endif
00261
00262 err: if (ret != 0) {
00263 (void)__os_closehandle(dbenv, fhp);
00264 *fhpp = NULL;
00265 }
00266
00267 return (ret);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 int
00279 __os_shmname(dbenv, name, newnamep)
00280 DB_ENV *dbenv;
00281 const char *name;
00282 char **newnamep;
00283 {
00284 int ret;
00285 size_t size;
00286 char *p, *q, *tmpname;
00287
00288 *newnamep = NULL;
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 if ((ret = __os_strdup(dbenv, name, &tmpname)) != 0)
00304 return (ret);
00305
00306
00307
00308
00309
00310
00311
00312
00313 p = __db_rpath(tmpname);
00314 if (p == NULL)
00315 return (EINVAL);
00316 if (p != tmpname) {
00317 *p = '\0';
00318 q = p;
00319 p = __db_rpath(tmpname);
00320 *q = ':';
00321 }
00322 if (p != NULL) {
00323
00324
00325
00326 ret = __os_strdup(dbenv, p, newnamep);
00327 __os_free(dbenv, tmpname);
00328 return (ret);
00329 }
00330
00331
00332
00333
00334
00335 size = strlen(tmpname) + 2;
00336 if ((ret = __os_malloc(dbenv, size, &p)) != 0)
00337 return (ret);
00338 p[0] = '/';
00339 memcpy(&p[1], tmpname, size-1);
00340 __os_free(dbenv, tmpname);
00341 *newnamep = p;
00342 return (0);
00343 }
00344 #endif
00345
00346
00347
00348
00349
00350 static int
00351 __os_intermediate_dir(dbenv, name)
00352 DB_ENV *dbenv;
00353 const char *name;
00354 {
00355 size_t len;
00356 int ret;
00357 char savech, *p, *t, buf[128];
00358
00359 ret = 0;
00360
00361
00362
00363
00364
00365
00366 if ((len = strlen(name)) > sizeof(buf) - 1) {
00367 if ((ret = __os_umalloc(dbenv, len + 1, &t)) != 0)
00368 return (ret);
00369 } else
00370 t = buf;
00371 (void)strcpy(t, name);
00372
00373
00374
00375
00376
00377
00378
00379 if (PATH_SEPARATOR[1] == '\0') {
00380 for (p = t + 1; p[0] != '\0'; ++p)
00381 if (p[0] == PATH_SEPARATOR[0]) {
00382 savech = *p;
00383 *p = '\0';
00384 if (__os_exists(t, NULL) &&
00385 (ret = __os_mkdir(
00386 dbenv, t, dbenv->dir_mode)) != 0)
00387 break;
00388 *p = savech;
00389 }
00390 } else
00391 for (p = t + 1; p[0] != '\0'; ++p)
00392 if (strchr(PATH_SEPARATOR, p[0]) != NULL) {
00393 savech = *p;
00394 *p = '\0';
00395 if (__os_exists(t, NULL) &&
00396 (ret = __os_mkdir(
00397 dbenv, t, dbenv->dir_mode)) != 0)
00398 break;
00399 *p = savech;
00400 }
00401 if (t != buf)
00402 __os_free(dbenv, t);
00403 return (ret);
00404 }