os_open.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1997-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: os_open.c,v 11.37 2002/06/21 20:35:16 sandstro Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <fcntl.h>
  14. #include <string.h>
  15. #endif
  16. #include "db_int.h"
  17. #ifdef HAVE_QNX
  18. static int __os_region_open __P((DB_ENV *, const char *, int, int, DB_FH *));
  19. #endif
  20. /*
  21.  * __os_open --
  22.  * Open a file.
  23.  *
  24.  * PUBLIC: int __os_open __P((DB_ENV *, const char *, u_int32_t, int, DB_FH *));
  25.  */
  26. int
  27. __os_open(dbenv, name, flags, mode, fhp)
  28. DB_ENV *dbenv;
  29. const char *name;
  30. u_int32_t flags;
  31. int mode;
  32. DB_FH *fhp;
  33. {
  34. int oflags, ret;
  35. oflags = 0;
  36. #ifdef DIAGNOSTIC
  37. #define OKFLAGS
  38. (DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_EXCL | DB_OSO_LOG |
  39.  DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | DB_OSO_TEMP |
  40.  DB_OSO_TRUNC)
  41. if ((ret = __db_fchk(dbenv, "__os_open", flags, OKFLAGS)) != 0)
  42. return (ret);
  43. #endif
  44. #if defined(O_BINARY)
  45. /*
  46.  * If there's a binary-mode open flag, set it, we never want any
  47.  * kind of translation.  Some systems do translations by default,
  48.  * e.g., with Cygwin, the default mode for an open() is set by the
  49.  * mode of the mount that underlies the file.
  50.  */
  51. oflags |= O_BINARY;
  52. #endif
  53. /*
  54.  * DB requires the POSIX 1003.1 semantic that two files opened at the
  55.  * same time with DB_OSO_CREATE/O_CREAT and DB_OSO_EXCL/O_EXCL flags
  56.  * set return an EEXIST failure in at least one.
  57.  */
  58. if (LF_ISSET(DB_OSO_CREATE))
  59. oflags |= O_CREAT;
  60. if (LF_ISSET(DB_OSO_EXCL))
  61. oflags |= O_EXCL;
  62. #if defined(O_DSYNC) && defined(XXX_NEVER_SET)
  63. /*
  64.  * !!!
  65.  * We should get better performance if we push the log files to disk
  66.  * immediately instead of waiting for the sync.  However, Solaris
  67.  * (and likely any other system based on the 4BSD filesystem releases),
  68.  * doesn't implement O_DSYNC correctly, only flushing data blocks and
  69.  * not inode or indirect blocks.
  70.  */
  71. if (LF_ISSET(DB_OSO_LOG))
  72. oflags |= O_DSYNC;
  73. #endif
  74. if (LF_ISSET(DB_OSO_RDONLY))
  75. oflags |= O_RDONLY;
  76. else
  77. oflags |= O_RDWR;
  78. if (LF_ISSET(DB_OSO_TRUNC))
  79. oflags |= O_TRUNC;
  80. #ifdef HAVE_O_DIRECT
  81. if (LF_ISSET(DB_OSO_DIRECT))
  82. oflags |= O_DIRECT;
  83. #endif
  84. #ifdef HAVE_QNX
  85. if (LF_ISSET(DB_OSO_REGION))
  86. return (__os_region_open(dbenv, name, oflags, mode, fhp));
  87. #endif
  88. /* Open the file. */
  89. if ((ret = __os_openhandle(dbenv, name, oflags, mode, fhp)) != 0)
  90. return (ret);
  91. #ifdef HAVE_DIRECTIO
  92. if (LF_ISSET(DB_OSO_DIRECT))
  93. (void)directio(fhp->fd, DIRECTIO_ON);
  94. #endif
  95. /*
  96.  * Delete any temporary file.
  97.  *
  98.  * !!!
  99.  * There's a race here, where we've created a file and we crash before
  100.  * we can unlink it.  Temporary files aren't common in DB, regardless,
  101.  * it's not a security problem because the file is empty.  There's no
  102.  * reasonable way to avoid the race (playing signal games isn't worth
  103.  * the portability nightmare), so we just live with it.
  104.  */
  105. if (LF_ISSET(DB_OSO_TEMP)) {
  106. #if defined(HAVE_UNLINK_WITH_OPEN_FAILURE) || defined(CONFIG_TEST)
  107. if ((ret = __os_strdup(dbenv, name, &fhp->name)) != 0) {
  108. (void)__os_closehandle(dbenv, fhp);
  109. (void)__os_unlink(dbenv, name);
  110. return (ret);
  111. }
  112. F_SET(fhp, DB_FH_UNLINK);
  113. #else
  114. (void)__os_unlink(dbenv, name);
  115. #endif
  116. }
  117. return (0);
  118. }
  119. #ifdef HAVE_QNX
  120. /*
  121.  * __os_region_open --
  122.  * Open a shared memory region file using POSIX shm_open.
  123.  */
  124. static int
  125. __os_region_open(dbenv, name, oflags, mode, fhp)
  126. DB_ENV *dbenv;
  127. const char *name;
  128. int oflags;
  129. int mode;
  130. DB_FH *fhp;
  131. {
  132. int ret;
  133. char *newname;
  134. if ((ret = __os_shmname(dbenv, name, &newname)) != 0)
  135. goto err;
  136. memset(fhp, 0, sizeof(*fhp));
  137. fhp->fd = shm_open(newname, oflags, mode);
  138. if (fhp->fd == -1)
  139. ret = __os_get_errno();
  140. else {
  141. #ifdef HAVE_FCNTL_F_SETFD
  142. /* Deny file descriptor acces to any child process. */
  143. if (fcntl(fhp->fd, F_SETFD, 1) == -1) {
  144. ret = __os_get_errno();
  145. __db_err(dbenv, "fcntl(F_SETFD): %s", strerror(ret));
  146. __os_closehandle(dbenv, fhp);
  147. } else
  148. #endif
  149. F_SET(fhp, DB_FH_VALID);
  150. }
  151. /*
  152.  * Once we have created the object, we don't need the name
  153.  * anymore.  Other callers of this will convert themselves.
  154.  */
  155. err:
  156. if (newname != NULL)
  157. __os_free(dbenv, newname);
  158. return (ret);
  159. }
  160. /*
  161.  * __os_shmname --
  162.  * Translate a pathname into a shm_open memory object name.
  163.  *
  164.  * PUBLIC: #ifdef HAVE_QNX
  165.  * PUBLIC: int __os_shmname __P((DB_ENV *, const char *, char **));
  166.  * PUBLIC: #endif
  167.  */
  168. int
  169. __os_shmname(dbenv, name, newnamep)
  170. DB_ENV *dbenv;
  171. const char *name;
  172. char **newnamep;
  173. {
  174. int ret;
  175. size_t size;
  176. char *p, *q, *tmpname;
  177. *newnamep = NULL;
  178. /*
  179.  * POSIX states that the name for a shared memory object
  180.  * may begin with a slash '/' and support for subsequent
  181.  * slashes is implementation-dependent.  The one implementation
  182.  * we know of right now, QNX, forbids subsequent slashes.
  183.  * We don't want to be parsing pathnames for '.' and '..' in
  184.  * the middle.  In order to allow easy conversion, just take
  185.  * the last component as the shared memory name.  This limits
  186.  * the namespace a bit, but makes our job a lot easier.
  187.  *
  188.  * We should not be modifying user memory, so we use our own.
  189.  * Caller is responsible for freeing the memory we give them.
  190.  */
  191. if ((ret = __os_strdup(dbenv, name, &tmpname)) != 0)
  192. return (ret);
  193. /*
  194.  * Skip over filename component.
  195.  * We set that separator to '' so that we can do another
  196.  * __db_rpath.  However, we immediately set it then to ':'
  197.  * so that we end up with the tailing directory:filename.
  198.  * We require a home directory component.  Return an error
  199.  * if there isn't one.
  200.  */
  201. p = __db_rpath(tmpname);
  202. if (p == NULL)
  203. return (EINVAL);
  204. if (p != tmpname) {
  205. *p = '';
  206. q = p;
  207. p = __db_rpath(tmpname);
  208. *q = ':';
  209. }
  210. if (p != NULL) {
  211. /*
  212.  * If we have a path component, copy and return it.
  213.  */
  214. ret = __os_strdup(dbenv, p, newnamep);
  215. __os_free(dbenv, tmpname);
  216. return (ret);
  217. }
  218. /*
  219.  * We were given just a directory name with no path components.
  220.  * Add a leading slash, and copy the remainder.
  221.  */
  222. size = strlen(tmpname) + 2;
  223. if ((ret = __os_malloc(dbenv, size, &p)) != 0)
  224. return (ret);
  225. p[0] = '/';
  226. memcpy(&p[1], tmpname, size-1);
  227. __os_free(dbenv, tmpname);
  228. *newnamep = p;
  229. return (0);
  230. }
  231. #endif