00001 /* Copyright (C) 2000 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #include "mysys_priv.h" 00018 #include "mysys_err.h" 00019 #include <my_dir.h> 00020 #include <errno.h> 00021 #if defined(__WIN__) 00022 #include <share.h> 00023 #endif 00024 00025 /* 00026 Open a file 00027 00028 SYNOPSIS 00029 my_open() 00030 FileName Fully qualified file name 00031 Flags Read | write 00032 MyFlags Special flags 00033 00034 RETURN VALUE 00035 File descriptor 00036 */ 00037 00038 File my_open(const char *FileName, int Flags, myf MyFlags) 00039 /* Path-name of file */ 00040 /* Read | write .. */ 00041 /* Special flags */ 00042 { 00043 File fd; 00044 DBUG_ENTER("my_open"); 00045 DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", 00046 FileName, Flags, MyFlags)); 00047 #if defined(__WIN__) 00048 /* 00049 Check that we don't try to open or create a file name that may 00050 cause problems for us in the future (like PRN) 00051 */ 00052 if (check_if_legal_filename(FileName)) 00053 { 00054 errno= EACCES; 00055 DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN, 00056 EE_FILENOTFOUND, MyFlags)); 00057 } 00058 #ifndef __WIN__ 00059 if (Flags & O_SHARE) 00060 fd = sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, 00061 MY_S_IREAD | MY_S_IWRITE); 00062 else 00063 fd = open((my_string) FileName, Flags | O_BINARY, 00064 MY_S_IREAD | MY_S_IWRITE); 00065 #else 00066 fd= my_sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, 00067 MY_S_IREAD | MY_S_IWRITE); 00068 #endif 00069 00070 #elif !defined(NO_OPEN_3) 00071 fd = open(FileName, Flags, my_umask); /* Normal unix */ 00072 #else 00073 fd = open((my_string) FileName, Flags); 00074 #endif 00075 DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_OPEN, 00076 EE_FILENOTFOUND, MyFlags)); 00077 } /* my_open */ 00078 00079 00080 /* 00081 Close a file 00082 00083 SYNOPSIS 00084 my_close() 00085 fd File sescriptor 00086 myf Special Flags 00087 00088 */ 00089 00090 int my_close(File fd, myf MyFlags) 00091 { 00092 int err; 00093 DBUG_ENTER("my_close"); 00094 DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); 00095 00096 pthread_mutex_lock(&THR_LOCK_open); 00097 do 00098 { 00099 err= close(fd); 00100 } while (err == -1 && errno == EINTR); 00101 00102 if (err) 00103 { 00104 DBUG_PRINT("error",("Got error %d on close",err)); 00105 my_errno=errno; 00106 if (MyFlags & (MY_FAE | MY_WME)) 00107 my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG),my_filename(fd),errno); 00108 } 00109 if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN) 00110 { 00111 my_free(my_file_info[fd].name, MYF(0)); 00112 #if defined(THREAD) && !defined(HAVE_PREAD) 00113 pthread_mutex_destroy(&my_file_info[fd].mutex); 00114 #endif 00115 my_file_info[fd].type = UNOPEN; 00116 } 00117 my_file_opened--; 00118 pthread_mutex_unlock(&THR_LOCK_open); 00119 DBUG_RETURN(err); 00120 } /* my_close */ 00121 00122 00123 /* 00124 Register file in my_file_info[] 00125 00126 SYNOPSIS 00127 my_register_filename() 00128 fd 00129 FileName 00130 type_file_type 00131 */ 00132 00133 File my_register_filename(File fd, const char *FileName, enum file_type 00134 type_of_file, uint error_message_number, myf MyFlags) 00135 { 00136 if ((int) fd >= 0) 00137 { 00138 if ((uint) fd >= my_file_limit) 00139 { 00140 #if defined(THREAD) && !defined(HAVE_PREAD) 00141 (void) my_close(fd,MyFlags); 00142 my_errno=EMFILE; 00143 if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) 00144 my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG), 00145 FileName, my_errno); 00146 return(-1); 00147 #endif 00148 thread_safe_increment(my_file_opened,&THR_LOCK_open); 00149 return(fd); /* safeguard */ 00150 } 00151 pthread_mutex_lock(&THR_LOCK_open); 00152 if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) 00153 { 00154 my_file_opened++; 00155 my_file_info[fd].type = type_of_file; 00156 #if defined(THREAD) && !defined(HAVE_PREAD) 00157 pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST); 00158 #endif 00159 pthread_mutex_unlock(&THR_LOCK_open); 00160 DBUG_PRINT("exit",("fd: %d",fd)); 00161 return(fd); 00162 } 00163 pthread_mutex_unlock(&THR_LOCK_open); 00164 (void) my_close(fd, MyFlags); 00165 my_errno=ENOMEM; 00166 } 00167 else 00168 my_errno=errno; 00169 DBUG_PRINT("error",("Got error %d on open",my_errno)); 00170 if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) 00171 my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG), 00172 FileName, my_errno); 00173 return(fd); 00174 } 00175 00176 #ifdef __WIN__ 00177 00178 extern void __cdecl _dosmaperr(unsigned long); 00179 00180 /* 00181 Open a file with sharing. Similar to _sopen() from libc, but allows managing 00182 share delete on win32 00183 00184 SYNOPSIS 00185 my_sopen() 00186 path fully qualified file name 00187 oflag operation flags 00188 shflag share flag 00189 pmode permission flags 00190 00191 RETURN VALUE 00192 File descriptor of opened file if success 00193 -1 and sets errno if fails. 00194 */ 00195 00196 File my_sopen(const char *path, int oflag, int shflag, int pmode) 00197 { 00198 int fh; /* handle of opened file */ 00199 int mask; 00200 HANDLE osfh; /* OS handle of opened file */ 00201 DWORD fileaccess; /* OS file access (requested) */ 00202 DWORD fileshare; /* OS file sharing mode */ 00203 DWORD filecreate; /* OS method of opening/creating */ 00204 DWORD fileattrib; /* OS file attribute flags */ 00205 SECURITY_ATTRIBUTES SecurityAttributes; 00206 00207 SecurityAttributes.nLength= sizeof(SecurityAttributes); 00208 SecurityAttributes.lpSecurityDescriptor= NULL; 00209 SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT); 00210 00211 /* 00212 * decode the access flags 00213 */ 00214 switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { 00215 case _O_RDONLY: /* read access */ 00216 fileaccess= GENERIC_READ; 00217 break; 00218 case _O_WRONLY: /* write access */ 00219 fileaccess= GENERIC_WRITE; 00220 break; 00221 case _O_RDWR: /* read and write access */ 00222 fileaccess= GENERIC_READ | GENERIC_WRITE; 00223 break; 00224 default: /* error, bad oflag */ 00225 errno= EINVAL; 00226 _doserrno= 0L; /* not an OS error */ 00227 return -1; 00228 } 00229 00230 /* 00231 * decode sharing flags 00232 */ 00233 switch (shflag) { 00234 case _SH_DENYRW: /* exclusive access except delete */ 00235 fileshare= FILE_SHARE_DELETE; 00236 break; 00237 case _SH_DENYWR: /* share read and delete access */ 00238 fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE; 00239 break; 00240 case _SH_DENYRD: /* share write and delete access */ 00241 fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE; 00242 break; 00243 case _SH_DENYNO: /* share read, write and delete access */ 00244 fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 00245 break; 00246 case _SH_DENYRWD: /* exclusive access */ 00247 fileshare= 0L; 00248 break; 00249 case _SH_DENYWRD: /* share read access */ 00250 fileshare= FILE_SHARE_READ; 00251 break; 00252 case _SH_DENYRDD: /* share write access */ 00253 fileshare= FILE_SHARE_WRITE; 00254 break; 00255 case _SH_DENYDEL: /* share read and write access */ 00256 fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE; 00257 break; 00258 default: /* error, bad shflag */ 00259 errno= EINVAL; 00260 _doserrno= 0L; /* not an OS error */ 00261 return -1; 00262 } 00263 00264 /* 00265 * decode open/create method flags 00266 */ 00267 switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) { 00268 case 0: 00269 case _O_EXCL: /* ignore EXCL w/o CREAT */ 00270 filecreate= OPEN_EXISTING; 00271 break; 00272 00273 case _O_CREAT: 00274 filecreate= OPEN_ALWAYS; 00275 break; 00276 00277 case _O_CREAT | _O_EXCL: 00278 case _O_CREAT | _O_TRUNC | _O_EXCL: 00279 filecreate= CREATE_NEW; 00280 break; 00281 00282 case _O_TRUNC: 00283 case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */ 00284 filecreate= TRUNCATE_EXISTING; 00285 break; 00286 00287 case _O_CREAT | _O_TRUNC: 00288 filecreate= CREATE_ALWAYS; 00289 break; 00290 00291 default: 00292 /* this can't happen ... all cases are covered */ 00293 errno= EINVAL; 00294 _doserrno= 0L; 00295 return -1; 00296 } 00297 00298 /* 00299 * decode file attribute flags if _O_CREAT was specified 00300 */ 00301 fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */ 00302 if (oflag & _O_CREAT) 00303 { 00304 _umask((mask= _umask(0))); 00305 00306 if (!((pmode & ~mask) & _S_IWRITE)) 00307 fileattrib= FILE_ATTRIBUTE_READONLY; 00308 } 00309 00310 /* 00311 * Set temporary file (delete-on-close) attribute if requested. 00312 */ 00313 if (oflag & _O_TEMPORARY) 00314 { 00315 fileattrib|= FILE_FLAG_DELETE_ON_CLOSE; 00316 fileaccess|= DELETE; 00317 } 00318 00319 /* 00320 * Set temporary file (delay-flush-to-disk) attribute if requested. 00321 */ 00322 if (oflag & _O_SHORT_LIVED) 00323 fileattrib|= FILE_ATTRIBUTE_TEMPORARY; 00324 00325 /* 00326 * Set sequential or random access attribute if requested. 00327 */ 00328 if (oflag & _O_SEQUENTIAL) 00329 fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN; 00330 else if (oflag & _O_RANDOM) 00331 fileattrib|= FILE_FLAG_RANDOM_ACCESS; 00332 00333 /* 00334 * try to open/create the file 00335 */ 00336 if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, 00337 filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE) 00338 { 00339 /* 00340 * OS call to open/create file failed! map the error, release 00341 * the lock, and return -1. note that it's not necessary to 00342 * call _free_osfhnd (it hasn't been used yet). 00343 */ 00344 _dosmaperr(GetLastError()); /* map error */ 00345 return -1; /* return error to caller */ 00346 } 00347 00348 fh= _open_osfhandle((intptr_t)osfh, oflag & (_O_APPEND | _O_RDONLY | _O_TEXT)); 00349 00350 return fh; /* return handle */ 00351 } 00352 #endif /* __WIN__ */ 00353 00354 00355 #ifdef EXTRA_DEBUG 00356 00357 void my_print_open_files(void) 00358 { 00359 if (my_file_opened | my_stream_opened) 00360 { 00361 uint i; 00362 for (i= 0 ; i < my_file_limit ; i++) 00363 { 00364 if (my_file_info[i].type != UNOPEN) 00365 { 00366 fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i); 00367 fputc('\n', stderr); 00368 } 00369 } 00370 } 00371 } 00372 00373 #endif
1.4.7

