my_open.c 10.2 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4
/* Copyright (C) 2000 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6 7

   This program is distributed in the hope that it will be useful,
unknown's avatar
unknown committed
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
unknown's avatar
unknown committed
9 10 11 12 13 14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
unknown's avatar
unknown committed
15 16 17

#include "mysys_priv.h"
#include "mysys_err.h"
unknown's avatar
unknown committed
18
#include <my_dir.h>
unknown's avatar
unknown committed
19
#include <errno.h>
unknown's avatar
unknown committed
20
#if defined(__WIN__)
unknown's avatar
unknown committed
21 22 23
#include <share.h>
#endif

unknown's avatar
unknown committed
24 25 26 27 28 29 30 31 32 33 34 35
/*
  Open a file

  SYNOPSIS
    my_open()
      FileName	Fully qualified file name
      Flags	Read | write 
      MyFlags	Special flags

  RETURN VALUE
    File descriptor
*/
unknown's avatar
unknown committed
36 37 38 39 40 41 42 43 44 45

File my_open(const char *FileName, int Flags, myf MyFlags)
				/* Path-name of file */
				/* Read | write .. */
				/* Special flags */
{
  File fd;
  DBUG_ENTER("my_open");
  DBUG_PRINT("my",("Name: '%s'  Flags: %d  MyFlags: %d",
		   FileName, Flags, MyFlags));
unknown's avatar
unknown committed
46
#if defined(__WIN__)
unknown's avatar
unknown committed
47
  /* 
unknown's avatar
unknown committed
48 49
    Check that we don't try to open or create a file name that may
    cause problems for us in the future (like PRN)
unknown's avatar
unknown committed
50
  */  
unknown's avatar
unknown committed
51 52 53 54 55 56
  if (check_if_legal_filename(FileName))
  {
    errno= EACCES;
    DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN,
                                     EE_FILENOTFOUND, MyFlags));
  }
57
#ifndef __WIN__
unknown's avatar
unknown committed
58
  if (Flags & O_SHARE)
59
    fd = sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
unknown's avatar
unknown committed
60
	       MY_S_IREAD | MY_S_IWRITE);
unknown's avatar
unknown committed
61
  else
62
    fd = open((char *) FileName, Flags | O_BINARY,
unknown's avatar
unknown committed
63
	      MY_S_IREAD | MY_S_IWRITE);
64
#else
65
  fd= my_sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
66 67 68
	       MY_S_IREAD | MY_S_IWRITE);
#endif

unknown's avatar
unknown committed
69
#elif !defined(NO_OPEN_3)
unknown's avatar
unknown committed
70
  fd = open(FileName, Flags, my_umask);	/* Normal unix */
unknown's avatar
unknown committed
71
#else
72
  fd = open((char *) FileName, Flags);
unknown's avatar
unknown committed
73
#endif
74

unknown's avatar
unknown committed
75 76 77 78 79
  DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_OPEN,
				   EE_FILENOTFOUND, MyFlags));
} /* my_open */


unknown's avatar
unknown committed
80 81 82 83 84 85 86
/*
  Close a file

  SYNOPSIS
    my_close()
      fd	File sescriptor
      myf	Special Flags
87

unknown's avatar
unknown committed
88
*/
unknown's avatar
unknown committed
89 90 91 92 93 94 95 96

int my_close(File fd, myf MyFlags)
{
  int err;
  DBUG_ENTER("my_close");
  DBUG_PRINT("my",("fd: %d  MyFlags: %d",fd, MyFlags));

  pthread_mutex_lock(&THR_LOCK_open);
97 98 99 100 101 102
  do
  {
    err= close(fd);
  } while (err == -1 && errno == EINTR);

  if (err)
unknown's avatar
unknown committed
103 104 105 106 107 108
  {
    DBUG_PRINT("error",("Got error %d on close",err));
    my_errno=errno;
    if (MyFlags & (MY_FAE | MY_WME))
      my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG),my_filename(fd),errno);
  }
109
  if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN)
unknown's avatar
unknown committed
110 111 112 113 114 115 116
  {
    my_free(my_file_info[fd].name, MYF(0));
#if defined(THREAD) && !defined(HAVE_PREAD)
    pthread_mutex_destroy(&my_file_info[fd].mutex);
#endif
    my_file_info[fd].type = UNOPEN;
  }
117
  my_file_opened--;
unknown's avatar
unknown committed
118 119 120 121
  pthread_mutex_unlock(&THR_LOCK_open);
  DBUG_RETURN(err);
} /* my_close */

unknown's avatar
unknown committed
122

unknown's avatar
unknown committed
123 124 125 126 127
/*
  Register file in my_file_info[]
   
  SYNOPSIS
    my_register_filename()
128 129 130 131 132 133 134 135 136 137
    fd			   File number opened, -1 if error on open
    FileName		   File name
    type_file_type	   How file was created
    error_message_number   Error message number if caller got error (fd == -1)
    MyFlags		   Flags for my_close()

  RETURN
    -1   error
     #   Filenumber

unknown's avatar
unknown committed
138 139
*/

unknown's avatar
unknown committed
140 141 142
File my_register_filename(File fd, const char *FileName, enum file_type
			  type_of_file, uint error_message_number, myf MyFlags)
{
143
  DBUG_ENTER("my_register_filename");
unknown's avatar
unknown committed
144 145
  if ((int) fd >= 0)
  {
146
    if ((uint) fd >= my_file_limit)
147 148
    {
#if defined(THREAD) && !defined(HAVE_PREAD)
149 150
      my_errno= EMFILE;
#else
151
      thread_safe_increment(my_file_opened,&THR_LOCK_open);
152 153
      DBUG_RETURN(fd);				/* safeguard */
#endif
154
    }
155
    else
unknown's avatar
unknown committed
156
    {
157 158 159 160 161
      pthread_mutex_lock(&THR_LOCK_open);
      if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags)))
      {
        my_file_opened++;
        my_file_info[fd].type = type_of_file;
162
#if defined(THREAD) && !defined(HAVE_PREAD)
163
        pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST);
164
#endif
165 166 167 168
        pthread_mutex_unlock(&THR_LOCK_open);
        DBUG_PRINT("exit",("fd: %d",fd));
        DBUG_RETURN(fd);
      }
unknown's avatar
unknown committed
169
      pthread_mutex_unlock(&THR_LOCK_open);
170
      my_errno= ENOMEM;
unknown's avatar
unknown committed
171
    }
unknown's avatar
unknown committed
172
    (void) my_close(fd, MyFlags);
unknown's avatar
unknown committed
173 174
  }
  else
175 176 177 178 179 180 181 182 183 184
    my_errno= errno;

  DBUG_PRINT("error",("Got error %d on open", my_errno));
  if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
  {
    if (my_errno == EMFILE)
      error_message_number= EE_OUT_OF_FILERESOURCES;
    DBUG_PRINT("error",("print err: %d",error_message_number));
    my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG),
             FileName, my_errno);
185
  }
186
  DBUG_RETURN(-1);
unknown's avatar
unknown committed
187
}
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

#ifdef __WIN__

extern void __cdecl _dosmaperr(unsigned long);

/*
  Open a file with sharing. Similar to _sopen() from libc, but allows managing
  share delete on win32

  SYNOPSIS
    my_sopen()
      path    fully qualified file name
      oflag   operation flags
      shflag	share flag
      pmode   permission flags

  RETURN VALUE
    File descriptor of opened file if success
    -1 and sets errno if fails.
*/

File my_sopen(const char *path, int oflag, int shflag, int pmode)
{
  int  fh;                                /* handle of opened file */
  int mask;
  HANDLE osfh;                            /* OS handle of opened file */
  DWORD fileaccess;                       /* OS file access (requested) */
  DWORD fileshare;                        /* OS file sharing mode */
  DWORD filecreate;                       /* OS method of opening/creating */
  DWORD fileattrib;                       /* OS file attribute flags */
  SECURITY_ATTRIBUTES SecurityAttributes;

  SecurityAttributes.nLength= sizeof(SecurityAttributes);
  SecurityAttributes.lpSecurityDescriptor= NULL;
  SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);

  /*
   * decode the access flags
   */
  switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
    case _O_RDONLY:         /* read access */
      fileaccess= GENERIC_READ;
      break;
    case _O_WRONLY:         /* write access */
      fileaccess= GENERIC_WRITE;
      break;
    case _O_RDWR:           /* read and write access */
      fileaccess= GENERIC_READ | GENERIC_WRITE;
      break;
    default:                /* error, bad oflag */
      errno= EINVAL;
      _doserrno= 0L;        /* not an OS error */
      return -1;
  }

  /*
   * decode sharing flags
   */
  switch (shflag) {
    case _SH_DENYRW:        /* exclusive access except delete */
      fileshare= FILE_SHARE_DELETE;
      break;
    case _SH_DENYWR:        /* share read and delete access */
      fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
      break;
    case _SH_DENYRD:        /* share write and delete access */
      fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
      break;
    case _SH_DENYNO:        /* share read, write and delete access */
      fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
      break;
    case _SH_DENYRWD:       /* exclusive access */
      fileshare= 0L;
      break;
    case _SH_DENYWRD:       /* share read access */
      fileshare= FILE_SHARE_READ;
      break;
    case _SH_DENYRDD:       /* share write access */
      fileshare= FILE_SHARE_WRITE;
      break;
    case _SH_DENYDEL:       /* share read and write access */
      fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
      break;
    default:                /* error, bad shflag */
      errno= EINVAL;
      _doserrno= 0L;        /* not an OS error */
      return -1;
  }

  /*
   * decode open/create method flags
   */
  switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
    case 0:
282
    case _O_EXCL:                   /* ignore EXCL w/o CREAT */
283 284 285 286 287 288 289 290 291 292 293 294 295
      filecreate= OPEN_EXISTING;
      break;

    case _O_CREAT:
      filecreate= OPEN_ALWAYS;
      break;

    case _O_CREAT | _O_EXCL:
    case _O_CREAT | _O_TRUNC | _O_EXCL:
      filecreate= CREATE_NEW;
      break;

    case _O_TRUNC:
296
    case _O_TRUNC | _O_EXCL:        /* ignore EXCL w/o CREAT */
297 298 299 300 301 302 303 304
      filecreate= TRUNCATE_EXISTING;
      break;

    case _O_CREAT | _O_TRUNC:
      filecreate= CREATE_ALWAYS;
      break;

    default:
305
      /* this can't happen ... all cases are covered */
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
      errno= EINVAL;
      _doserrno= 0L;
      return -1;
  }

  /*
   * decode file attribute flags if _O_CREAT was specified
   */
  fileattrib= FILE_ATTRIBUTE_NORMAL;     /* default */
  if (oflag & _O_CREAT) 
  {
    _umask((mask= _umask(0)));
    
    if (!((pmode & ~mask) & _S_IWRITE))
      fileattrib= FILE_ATTRIBUTE_READONLY;
  }

  /*
   * Set temporary file (delete-on-close) attribute if requested.
   */
  if (oflag & _O_TEMPORARY) 
  {
    fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
    fileaccess|= DELETE;
  }

  /*
   * Set temporary file (delay-flush-to-disk) attribute if requested.
   */
  if (oflag & _O_SHORT_LIVED)
    fileattrib|= FILE_ATTRIBUTE_TEMPORARY;

  /*
   * Set sequential or random access attribute if requested.
   */
  if (oflag & _O_SEQUENTIAL)
    fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
  else if (oflag & _O_RANDOM)
    fileattrib|= FILE_FLAG_RANDOM_ACCESS;

  /*
   * try to open/create the file
   */
  if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, 
350
                        filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
351 352 353 354 355 356 357 358 359 360
  {
    /*
     * OS call to open/create file failed! map the error, release
     * the lock, and return -1. note that it's not necessary to
     * call _free_osfhnd (it hasn't been used yet).
     */
    _dosmaperr(GetLastError());     /* map error */
    return -1;                      /* return error to caller */
  }

361 362 363 364 365 366
  if ((fh= _open_osfhandle((intptr_t)osfh, 
                           oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1)
  {
    _dosmaperr(GetLastError());     /* map error */
    CloseHandle(osfh);
  }
367 368 369 370

  return fh;                        /* return handle */
}
#endif /* __WIN__ */
unknown's avatar
unknown committed
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391


#ifdef EXTRA_DEBUG

void my_print_open_files(void)
{
  if (my_file_opened | my_stream_opened)
  {
    uint i;
    for (i= 0 ; i < my_file_limit ; i++)
    {
      if (my_file_info[i].type != UNOPEN)
      {
        fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i);
        fputc('\n', stderr);
      }
    }
  }
}

#endif