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.21 2002/07/12 18:56:55 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <fcntl.h>
  14. #include <signal.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #endif
  18. #include "db_int.h"
  19. /*
  20.  * __os_open --
  21.  * Open a file descriptor.
  22.  */
  23. int
  24. __os_open(dbenv, name, flags, mode, fhp)
  25. DB_ENV *dbenv;
  26. const char *name;
  27. u_int32_t flags;
  28. int mode;
  29. DB_FH *fhp;
  30. {
  31. DWORD bytesWritten;
  32. u_int32_t log_size, pagesize, sectorsize;
  33. int access, attr, oflags, share, createflag;
  34. int ret, nrepeat;
  35. char *drive, dbuf[4]; /* <letter><colon><slosh><nul> */
  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. /*
  45.  * The "public" interface to the __os_open routine passes around POSIX
  46.  * 1003.1 flags, not DB flags.  If the user has defined their own open
  47.  * interface, use the POSIX flags.
  48.  */
  49. if (DB_GLOBAL(j_open) != NULL) {
  50. oflags = O_BINARY | O_NOINHERIT;
  51. if (LF_ISSET(DB_OSO_CREATE))
  52. oflags |= O_CREAT;
  53. if (LF_ISSET(DB_OSO_EXCL))
  54. oflags |= O_EXCL;
  55. if (LF_ISSET(DB_OSO_RDONLY))
  56. oflags |= O_RDONLY;
  57. else
  58. oflags |= O_RDWR;
  59. if (LF_ISSET(DB_OSO_SEQ))
  60. oflags |= _O_SEQUENTIAL;
  61. else
  62. oflags |= _O_RANDOM;
  63. if (LF_ISSET(DB_OSO_TEMP))
  64. oflags |= _O_TEMPORARY;
  65. if (LF_ISSET(DB_OSO_TRUNC))
  66. oflags |= O_TRUNC;
  67. return (__os_openhandle(dbenv, name, oflags, mode, fhp));
  68. }
  69. ret = 0;
  70. if (LF_ISSET(DB_OSO_LOG))
  71. log_size = fhp->log_size; /* XXX: Gag. */
  72. pagesize = fhp->pagesize;
  73. memset(fhp, 0, sizeof(*fhp));
  74. fhp->fd = -1;
  75. /*
  76.  * Otherwise, use the Windows/32 CreateFile interface so that we can
  77.  * play magic games with log files to get data flush effects similar
  78.  * to the POSIX O_DSYNC flag.
  79.  *
  80.  * !!!
  81.  * We currently ignore the 'mode' argument.  It would be possible
  82.  * to construct a set of security attributes that we could pass to
  83.  * CreateFile that would accurately represents the mode.  In worst
  84.  * case, this would require looking up user and all group names and
  85.  * creating an entry for each.  Alternatively, we could call the
  86.  * _chmod (partial emulation) function after file creation, although
  87.  * this leaves us with an obvious race.  However, these efforts are
  88.  * largely meaningless on FAT, the most common file system, which
  89.  * only has a "readable" and "writeable" flag, applying to all users.
  90.  */
  91. access = GENERIC_READ;
  92. if (!LF_ISSET(DB_OSO_RDONLY))
  93. access |= GENERIC_WRITE;
  94. share = FILE_SHARE_READ | FILE_SHARE_WRITE;
  95. attr = FILE_ATTRIBUTE_NORMAL;
  96. /*
  97.  * Reproduce POSIX 1003.1 semantics: if O_CREATE and O_EXCL are both
  98.  * specified, fail, returning EEXIST, unless we create the file.
  99.  */
  100. if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_EXCL))
  101. createflag = CREATE_NEW; /* create only if !exist*/
  102. else if (!LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_TRUNC))
  103. createflag = TRUNCATE_EXISTING; /* truncate, fail if !exist */
  104. else if (LF_ISSET(DB_OSO_TRUNC))
  105. createflag = CREATE_ALWAYS; /* create and truncate */
  106. else if (LF_ISSET(DB_OSO_CREATE))
  107. createflag = OPEN_ALWAYS; /* open or create */
  108. else
  109. createflag = OPEN_EXISTING; /* open only if existing */
  110. if (LF_ISSET(DB_OSO_LOG)) {
  111. F_SET(fhp, DB_FH_NOSYNC);
  112. attr |= FILE_FLAG_WRITE_THROUGH;
  113. }
  114. if (LF_ISSET(DB_OSO_SEQ))
  115. attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  116. else
  117. attr |= FILE_FLAG_RANDOM_ACCESS;
  118. if (LF_ISSET(DB_OSO_TEMP))
  119. attr |= FILE_FLAG_DELETE_ON_CLOSE;
  120. /*
  121.  * We can turn filesystem buffering off if the page size is a
  122.  * multiple of the disk's sector size. To find the sector size,
  123.  * we call GetDiskFreeSpace, which expects a drive name like "d:\"
  124.  * or NULL for the current disk (i.e., a relative path)
  125.  */
  126. if (LF_ISSET(DB_OSO_DIRECT) && pagesize != 0 && name[0] != '') {
  127. if (name[1] == ':') {
  128. drive = dbuf;
  129. snprintf(dbuf, sizeof(dbuf), "%c:\", name[0]);
  130. } else
  131. drive = NULL;
  132. if (GetDiskFreeSpace(drive, NULL, &sectorsize, NULL, NULL) &&
  133.     pagesize % sectorsize == 0)
  134. attr |= FILE_FLAG_NO_BUFFERING;
  135. }
  136. for (nrepeat = 1;; ++nrepeat) {
  137. fhp->handle =
  138.     CreateFile(name, access, share, NULL, createflag, attr, 0);
  139. if (fhp->handle == INVALID_HANDLE_VALUE) {
  140. /*
  141.  * If it's a "temporary" error, we retry up to 3 times,
  142.  * waiting up to 12 seconds.  While it's not a problem
  143.  * if we can't open a database, an inability to open a
  144.  * log file is cause for serious dismay.
  145.  */
  146. ret = __os_win32_errno();
  147. if ((ret != ENFILE && ret != EMFILE && ret != ENOSPC) ||
  148.     nrepeat > 3)
  149. goto err;
  150. (void)__os_sleep(dbenv, nrepeat * 2, 0);
  151. } else
  152. break;
  153. }
  154. /*
  155.  * Special handling needed for log files.  To get Windows to not update
  156.  * the MFT metadata on each write, extend the file to its maximum size.
  157.  * Windows will allocate all the data blocks and store them in the MFT
  158.  * (inode) area.  In addition, flush the MFT area to disk.
  159.  * This strategy only works for Win/NT; Win/9X does not
  160.  * guarantee that the logs will be zero filled.
  161.  */
  162. if (LF_ISSET(DB_OSO_LOG) && log_size != 0 && __os_is_winnt()) {
  163. if (SetFilePointer(fhp->handle,
  164.     log_size - 1, NULL, FILE_BEGIN) == (DWORD)-1)
  165. goto err;
  166. if (WriteFile(fhp->handle, "x00", 1, &bytesWritten, NULL) == 0)
  167. goto err;
  168. if (bytesWritten != 1)
  169. goto err;
  170. if (SetEndOfFile(fhp->handle) == 0)
  171. goto err;
  172. if (SetFilePointer(
  173.     fhp->handle, 0, NULL, FILE_BEGIN) == (DWORD)-1)
  174. goto err;
  175. if (FlushFileBuffers(fhp->handle) == 0)
  176. goto err;
  177. }
  178. F_SET(fhp, DB_FH_VALID);
  179. return (0);
  180. err: if (ret == 0)
  181. ret = __os_win32_errno();
  182. if (fhp->handle != INVALID_HANDLE_VALUE)
  183. (void)CloseHandle(fhp->handle);
  184. return (ret);
  185. }