1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12 13/* 14 * __os_open -- 15 * Open a file descriptor (including page size and log size information). 16 * 17 * PUBLIC: int __os_open __P((ENV *, 18 * PUBLIC: const char *, u_int32_t, u_int32_t, int, DB_FH **)); 19 */ 20int 21__os_open(env, name, page_size, flags, mode, fhpp) 22 ENV *env; 23 const char *name; 24 u_int32_t page_size, flags; 25 int mode; 26 DB_FH **fhpp; 27{ 28 DB_ENV *dbenv; 29 DB_FH *fhp; 30 int oflags, ret; 31 32 COMPQUIET(page_size, 0); 33 34 dbenv = env == NULL ? NULL : env->dbenv; 35 *fhpp = NULL; 36 oflags = 0; 37 38 if (dbenv != NULL && 39 FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) 40 __db_msg(env, "fileops: open %s", name); 41 42#define OKFLAGS \ 43 (DB_OSO_ABSMODE | DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_DSYNC |\ 44 DB_OSO_EXCL | DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | \ 45 DB_OSO_TEMP | DB_OSO_TRUNC) 46 if ((ret = __db_fchk(env, "__os_open", flags, OKFLAGS)) != 0) 47 return (ret); 48 49#if defined(O_BINARY) 50 /* 51 * If there's a binary-mode open flag, set it, we never want any 52 * kind of translation. Some systems do translations by default, 53 * e.g., with Cygwin, the default mode for an open() is set by the 54 * mode of the mount that underlies the file. 55 */ 56 oflags |= O_BINARY; 57#endif 58 59 /* 60 * DB requires the POSIX 1003.1 semantic that two files opened at the 61 * same time with DB_OSO_CREATE/O_CREAT and DB_OSO_EXCL/O_EXCL flags 62 * set return an EEXIST failure in at least one. 63 */ 64 if (LF_ISSET(DB_OSO_CREATE)) 65 oflags |= O_CREAT; 66 67 if (LF_ISSET(DB_OSO_EXCL)) 68 oflags |= O_EXCL; 69 70#ifdef HAVE_O_DIRECT 71 if (LF_ISSET(DB_OSO_DIRECT)) 72 oflags |= O_DIRECT; 73#endif 74#ifdef O_DSYNC 75 if (LF_ISSET(DB_OSO_DSYNC)) 76 oflags |= O_DSYNC; 77#endif 78 79 if (LF_ISSET(DB_OSO_RDONLY)) 80 oflags |= O_RDONLY; 81 else 82 oflags |= O_RDWR; 83 84 if (LF_ISSET(DB_OSO_TRUNC)) 85 oflags |= O_TRUNC; 86 87 /* 88 * Undocumented feature: allow applications to create intermediate 89 * directories whenever a file is opened. 90 */ 91 if (dbenv != NULL && 92 env->dir_mode != 0 && LF_ISSET(DB_OSO_CREATE) && 93 (ret = __db_mkpath(env, name)) != 0) 94 return (ret); 95 96 /* Open the file. */ 97#ifdef HAVE_QNX 98 if (LF_ISSET(DB_OSO_REGION)) 99 ret = __os_qnx_region_open(env, name, oflags, mode, &fhp); 100 else 101#endif 102 ret = __os_openhandle(env, name, oflags, mode, &fhp); 103 if (ret != 0) 104 return (ret); 105 106 if (LF_ISSET(DB_OSO_REGION)) 107 F_SET(fhp, DB_FH_REGION); 108#ifdef HAVE_FCHMOD 109 /* 110 * If the code using Berkeley DB is a library, that code may not be able 111 * to control the application's umask value. Allow applications to set 112 * absolute file modes. We can't fix the race between file creation and 113 * the fchmod call -- we can't modify the process' umask here since the 114 * process may be multi-threaded and the umask value is per-process, not 115 * per-thread. 116 */ 117 if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_ABSMODE)) 118 (void)fchmod(fhp->fd, mode); 119#endif 120 121#ifdef O_DSYNC 122 /* 123 * If we can configure the file descriptor to flush on write, the 124 * file descriptor does not need to be explicitly sync'd. 125 */ 126 if (LF_ISSET(DB_OSO_DSYNC)) 127 F_SET(fhp, DB_FH_NOSYNC); 128#endif 129 130#if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON) 131 /* 132 * The Solaris C library includes directio, but you have to set special 133 * compile flags to #define DIRECTIO_ON. Require both in order to call 134 * directio. 135 */ 136 if (LF_ISSET(DB_OSO_DIRECT)) 137 (void)directio(fhp->fd, DIRECTIO_ON); 138#endif 139 140 /* 141 * Delete any temporary file. 142 * 143 * !!! 144 * There's a race here, where we've created a file and we crash before 145 * we can unlink it. Temporary files aren't common in DB, regardless, 146 * it's not a security problem because the file is empty. There's no 147 * reasonable way to avoid the race (playing signal games isn't worth 148 * the portability nightmare), so we just live with it. 149 */ 150 if (LF_ISSET(DB_OSO_TEMP)) { 151#if defined(HAVE_UNLINK_WITH_OPEN_FAILURE) || defined(CONFIG_TEST) 152 F_SET(fhp, DB_FH_UNLINK); 153#else 154 (void)__os_unlink(env, name, 0); 155#endif 156 } 157 158 *fhpp = fhp; 159 return (0); 160} 161