00001 /*- 00002 * See the file LICENSE for redistribution information. 00003 * 00004 * Copyright (c) 1998, 1999, 2000 00005 * Sleepycat Software. All rights reserved. 00006 */ 00007 00008 #include "config.h" 00009 00010 #ifndef lint 00011 static const char revid[] = "$Id: os__handle_8c-source.html,v 1.1 2008年06月08日 10:21:16 sebdiaz Exp $"; 00012 #endif /* not lint */ 00013 00014 #ifndef NO_SYSTEM_INCLUDES 00015 #include <sys/types.h> 00016 00017 #include <errno.h> 00018 #include <fcntl.h> 00019 #include <string.h> 00020 #include <unistd.h> 00021 #endif 00022 00023 #include "db_int.h" 00024 #include "os_jump.h" 00025 00026 /* 00027 * CDB___os_openhandle -- 00028 * Open a file, using POSIX 1003.1 open flags. 00029 * 00030 * PUBLIC: int CDB___os_openhandle __P((DB_ENV *, const char *, int, int, DB_FH *)); 00031 */ 00032 int 00033 CDB___os_openhandle(dbenv, name, flags, mode, fhp) 00034 DB_ENV *dbenv; 00035 const char *name; 00036 int flags, mode; 00037 DB_FH *fhp; 00038 { 00039 int ret, try; 00040 #ifdef HAVE_VXWORKS 00041 int newflags; 00042 #endif 00043 00044 memset(fhp, 0, sizeof(*fhp)); 00045 00046 /* If the application specified an interface, use it. */ 00047 if (CDB___db_jump.j_open != NULL) { 00048 if ((fhp->fd = CDB___db_jump.j_open(name, flags, mode)) == -1) 00049 return (CDB___os_get_errno()); 00050 F_SET(fhp, DB_FH_VALID); 00051 return (0); 00052 } 00053 00054 for (ret = 0, try = 1; try < 4; ++try) { 00055 #ifdef HAVE_VXWORKS 00056 /* 00057 * VxWorks does not support O_CREAT on open, you have to use 00058 * creat() instead. (It does not support O_EXCL or O_TRUNC 00059 * either, even though they are defined "for future support".) 00060 * If O_EXCL is specified, single thread and try to open the 00061 * file. If successful, return EEXIST. Otherwise, call creat 00062 * and then end single threading. 00063 */ 00064 if (LF_ISSET(O_CREAT)) { 00065 DB_BEGIN_SINGLE_THREAD; 00066 newflags = flags & ~(O_CREAT | O_EXCL); 00067 if (LF_ISSET(O_EXCL)) { 00068 if ((fhp->fd = 00069 open(name, newflags, mode)) != -1) { 00070 /* 00071 * If we get here, we want O_EXCL 00072 * create, and it exists. Close and 00073 * return EEXISTS. 00074 */ 00075 (void)close(fhp->fd); 00076 DB_END_SINGLE_THREAD; 00077 return (EEXIST); 00078 } 00079 /* 00080 * XXX 00081 * Assume any error means non-existence. 00082 * Unfortunately return values (even for 00083 * non-existence) are driver specific so 00084 * there is no single error we can use to 00085 * verify we truly got the equivalent of 00086 * ENOENT. 00087 */ 00088 } 00089 fhp->fd = creat(name, newflags); 00090 DB_END_SINGLE_THREAD; 00091 } else 00092 00093 /* FALLTHROUGH */ 00094 #endif 00095 #ifdef __VMS 00096 /* 00097 * !!! 00098 * Open with full sharing on VMS. 00099 * 00100 * We use these flags because they are the ones set by the VMS 00101 * CRTL mmap() call when it opens a file, and we have to be 00102 * able to open files that mmap() has previously opened, e.g., 00103 * when we're joining already existing DB regions. 00104 */ 00105 fhp->fd = open(name, flags, mode, "shr=get,put,upd,del,upi"); 00106 #else 00107 fhp->fd = open(name, flags, mode); 00108 #endif 00109 00110 if (fhp->fd == -1) { 00111 /* 00112 * If it's a "temporary" error, we retry up to 3 times, 00113 * waiting up to 12 seconds. While it's not a problem 00114 * if we can't open a database, an inability to open a 00115 * log file is cause for serious dismay. 00116 */ 00117 ret = CDB___os_get_errno(); 00118 if (ret == ENFILE || ret == EMFILE || ret == ENOSPC) { 00119 (void)CDB___os_sleep(dbenv, try * 2, 0); 00120 continue; 00121 } 00122 } else { 00123 #if defined(HAVE_FCNTL_F_SETFD) 00124 /* Deny file descriptor access to any child process. */ 00125 if (fcntl(fhp->fd, F_SETFD, 1) == -1) { 00126 ret = CDB___os_get_errno(); 00127 CDB___db_err(dbenv, "fcntl(F_SETFD): %s", 00128 strerror(ret)); 00129 (void)CDB___os_closehandle(fhp); 00130 } else 00131 #endif 00132 F_SET(fhp, DB_FH_VALID); 00133 } 00134 break; 00135 } 00136 00137 return (ret); 00138 } 00139 00140 /* 00141 * CDB___os_closehandle -- 00142 * Close a file. 00143 * 00144 * PUBLIC: int CDB___os_closehandle __P((DB_FH *)); 00145 */ 00146 int 00147 CDB___os_closehandle(fhp) 00148 DB_FH *fhp; 00149 { 00150 int ret; 00151 00152 /* Don't close file descriptors that were never opened. */ 00153 DB_ASSERT(F_ISSET(fhp, DB_FH_VALID) && fhp->fd != -1); 00154 00155 ret = CDB___db_jump.j_close != NULL ? 00156 CDB___db_jump.j_close(fhp->fd) : close(fhp->fd); 00157 00158 /* 00159 * Smash the POSIX file descriptor -- it's never tested, but we want 00160 * to catch any mistakes. 00161 */ 00162 fhp->fd = -1; 00163 F_CLR(fhp, DB_FH_VALID); 00164 00165 return (ret == 0 ? 0 : CDB___os_get_errno()); 00166 }