2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
|
|
|
* MODULE: llio.h
|
|
|
|
* DESCRIPTION: Low-level I/O routines
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2002-02-16 03:21:35 +01:00
|
|
|
*
|
|
|
|
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "EPSON" define
|
2002-02-16 04:05:21 +01:00
|
|
|
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "DELTA" port
|
2002-02-16 04:27:33 +01:00
|
|
|
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "IMP" port
|
2002-02-16 03:21:35 +01:00
|
|
|
*
|
2002-10-28 04:47:47 +01:00
|
|
|
* 2002.10.27 Sean Leyne - Completed removal of "DELTA" port
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/ib_stdio.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "../jrd/common.h"
|
|
|
|
#include "../jrd/llio.h"
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "gen/codes.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/iberr_proto.h"
|
|
|
|
#include "../jrd/llio_proto.h"
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
#include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef NETWARE_386
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <share.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fileengd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef NETWARE_386
|
|
|
|
# ifndef WIN_NT
|
|
|
|
# ifndef VMS
|
|
|
|
# include <fcntl.h>
|
2002-02-16 04:27:33 +01:00
|
|
|
# include <sys/file.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
# else
|
|
|
|
# include <file.h>
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2002-08-26 14:18:16 +02:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
#include <windows.h>
|
|
|
|
#ifdef TEXT
|
|
|
|
#undef TEXT
|
|
|
|
#endif
|
|
|
|
#define TEXT SCHAR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef O_SYNC
|
|
|
|
#define O_SYNC 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EINTR
|
|
|
|
#define EINTR 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define IO_RETRY 20
|
|
|
|
#define BUFSIZE 32768
|
|
|
|
|
|
|
|
static void io_error(STATUS *, TEXT *, TEXT *, STATUS);
|
|
|
|
|
|
|
|
#ifdef SHLIB_DEFS
|
|
|
|
#define fsync (*_libgds_fsync)
|
|
|
|
|
|
|
|
extern int fsync();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_allocate_file_space(
|
|
|
|
STATUS * status_vector,
|
|
|
|
TEXT * filename,
|
|
|
|
SLONG size, UCHAR fill_char, USHORT overwrite)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ a l l o c a t e _ f i l e _ s p a c e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open (create if necessary) the given file and write 'size'
|
|
|
|
* number of bytes to it. Each byte is initialized to
|
|
|
|
* the passed fill_char. If 'overwrite' is FALSE and the file
|
2002-02-16 03:21:35 +01:00
|
|
|
* already exists, return FAILURE.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
* This routine may be used to make sure that the file already
|
|
|
|
* has enough space allocated to it.
|
|
|
|
*
|
|
|
|
* Other side benefit of using this routine could be that once the
|
|
|
|
* space is allocated, file system would not update the inode every
|
|
|
|
* time something is written to the file unless the file size grows
|
|
|
|
* beyond the given 'size'. So 'write' performance should improve.
|
|
|
|
*
|
|
|
|
* If there is any error, return FAILURE else return SUCCESS.
|
|
|
|
* In case of an error, status_vector would be updated.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SLONG fd;
|
|
|
|
SCHAR buffer[BUFSIZE];
|
|
|
|
SLONG times;
|
|
|
|
SLONG last_size, length;
|
|
|
|
USHORT open_mode;
|
|
|
|
|
|
|
|
if (overwrite)
|
|
|
|
open_mode = LLIO_OPEN_RW;
|
|
|
|
else
|
|
|
|
open_mode = LLIO_OPEN_NEW_RW;
|
|
|
|
|
|
|
|
if (LLIO_open(status_vector, filename, open_mode, TRUE, &fd))
|
|
|
|
return FAILURE;
|
|
|
|
|
|
|
|
memset(buffer, (int) fill_char, BUFSIZE);
|
|
|
|
times = size / BUFSIZE + 1; /* For the while loop below */
|
|
|
|
last_size = size % BUFSIZE;
|
|
|
|
while (times--) {
|
|
|
|
length = (times != 0) ? BUFSIZE : last_size;
|
|
|
|
if (LLIO_write(status_vector, fd, filename, 0L, LLIO_SEEK_NONE,
|
|
|
|
reinterpret_cast < UCHAR * >(buffer), length, 0)) {
|
|
|
|
LLIO_close(0, fd);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LLIO_close(0, fd);
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
#define IO_DEFINED
|
|
|
|
int LLIO_close(STATUS * status_vector, SLONG file_desc)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ c l o s e ( W I N _ N T )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Close a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
return (CloseHandle((HANDLE) file_desc) ? SUCCESS : FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_open(
|
|
|
|
STATUS * status_vector,
|
|
|
|
TEXT * filename,
|
|
|
|
USHORT open_mode, USHORT share_flag, SLONG * file_desc)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ o p e n ( W I N _ N T )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
DWORD access, create, attributes;
|
|
|
|
|
|
|
|
access = GENERIC_READ | GENERIC_WRITE;
|
|
|
|
attributes = 0;
|
|
|
|
switch (open_mode) {
|
|
|
|
case LLIO_OPEN_R:
|
|
|
|
access = GENERIC_READ;
|
|
|
|
create = OPEN_EXISTING;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_RW:
|
|
|
|
create = OPEN_ALWAYS;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_SYNC_RW:
|
|
|
|
create = OPEN_ALWAYS;
|
|
|
|
attributes = FILE_FLAG_WRITE_THROUGH;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_TRUNC_RW:
|
|
|
|
create = TRUNCATE_EXISTING;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_EXISTING_RW:
|
|
|
|
create = OPEN_EXISTING;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_SYNC_W:
|
|
|
|
access = GENERIC_WRITE;
|
|
|
|
create = OPEN_ALWAYS;
|
|
|
|
attributes = FILE_FLAG_WRITE_THROUGH;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_NEW_RW:
|
|
|
|
create = CREATE_NEW;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*file_desc = reinterpret_cast < SLONG > (CreateFile(filename,
|
|
|
|
access,
|
|
|
|
FILE_SHARE_READ |
|
|
|
|
FILE_SHARE_WRITE,
|
|
|
|
NULL, create,
|
|
|
|
FILE_ATTRIBUTE_NORMAL
|
|
|
|
|
|
|
|
|
FILE_FLAG_RANDOM_ACCESS
|
|
|
|
| attributes, 0));
|
|
|
|
if ((HANDLE) * file_desc == INVALID_HANDLE_VALUE
|
|
|
|
&& open_mode == LLIO_OPEN_WITH_TRUNC_RW) *file_desc =
|
|
|
|
reinterpret_cast < SLONG >
|
|
|
|
(CreateFile
|
|
|
|
(filename, access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
|
|
|
CREATE_NEW,
|
|
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | attributes,
|
|
|
|
0));
|
|
|
|
if ((HANDLE) * file_desc == INVALID_HANDLE_VALUE) {
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "CreateFile", filename, isc_io_open_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_read(
|
|
|
|
STATUS * status_vector,
|
|
|
|
SLONG file_desc,
|
|
|
|
TEXT * filename,
|
|
|
|
SLONG offset,
|
|
|
|
USHORT whence,
|
|
|
|
UCHAR * buffer, SLONG length, SLONG * length_read)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ r e a d ( W I N _ N T )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Read a record from a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
DWORD len;
|
|
|
|
|
|
|
|
if ((whence != LLIO_SEEK_NONE) &&
|
|
|
|
(LLIO_seek(status_vector, file_desc, filename, offset, whence) ==
|
|
|
|
FAILURE)) return FAILURE;
|
|
|
|
|
|
|
|
if (buffer)
|
|
|
|
if (!ReadFile((HANDLE) file_desc, buffer, length, &len, NULL)) {
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "ReadFile", filename,
|
|
|
|
isc_io_read_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length_read)
|
|
|
|
*length_read = len;
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_seek(
|
|
|
|
STATUS * status_vector,
|
|
|
|
SLONG file_desc, TEXT * filename, SLONG offset, USHORT whence)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ s e e k ( W I N _ N T )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Seek to the given offset.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
DWORD method;
|
|
|
|
|
|
|
|
if (whence != LLIO_SEEK_NONE) {
|
|
|
|
switch (whence) {
|
|
|
|
case LLIO_SEEK_BEGIN:
|
|
|
|
method = FILE_BEGIN;
|
|
|
|
break;
|
|
|
|
case LLIO_SEEK_CURRENT:
|
|
|
|
method = FILE_CURRENT;
|
|
|
|
break;
|
|
|
|
case LLIO_SEEK_END:
|
|
|
|
method = FILE_END;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (SetFilePointer((HANDLE) file_desc, offset, NULL, method) == -1) {
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "SetFilePointer", filename,
|
|
|
|
isc_io_access_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_sync(STATUS * status_vector, SLONG file_desc)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ s y n c ( W I N _ N T )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Flush the buffers in a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
return (FlushFileBuffers((HANDLE) file_desc) ? SUCCESS : FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_write(
|
|
|
|
STATUS * status_vector,
|
|
|
|
SLONG file_desc,
|
|
|
|
TEXT * filename,
|
|
|
|
SLONG offset,
|
|
|
|
USHORT whence, UCHAR * buffer, SLONG length, SLONG * length_written)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ w r i t e ( W I N _ N T )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Write a record to a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
DWORD len;
|
|
|
|
|
|
|
|
if ((whence != LLIO_SEEK_NONE) &&
|
|
|
|
(LLIO_seek(status_vector, file_desc, filename, offset, whence) ==
|
|
|
|
FAILURE)) return FAILURE;
|
|
|
|
|
|
|
|
if (buffer)
|
|
|
|
if (!WriteFile((HANDLE) file_desc, buffer, length, &len, NULL)) {
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "WriteFile", filename,
|
|
|
|
isc_io_write_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length_written)
|
|
|
|
*length_written = len;
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void io_error(
|
|
|
|
STATUS * status_vector,
|
|
|
|
TEXT * op, TEXT * filename, STATUS operation)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i o _ e r r o r ( W I N _ N T )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Fill up the status_vector with error info.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
IBERR_build_status(status_vector, isc_io_error, gds_arg_string, op,
|
|
|
|
gds_arg_string, filename, isc_arg_gds, operation,
|
|
|
|
gds_arg_win32, GetLastError(), 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef IO_DEFINED
|
|
|
|
int LLIO_close(STATUS * status_vector, SLONG file_desc)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ c l o s e ( g e n e r i c )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Close a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
return ((close((int) file_desc) != -1) ? SUCCESS : FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef NETWARE_386
|
|
|
|
int LLIO_open(
|
|
|
|
STATUS * status_vector,
|
|
|
|
TEXT * filename,
|
|
|
|
USHORT open_mode, USHORT share_flag, SLONG * file_desc)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ o p e n ( N E T W A R E _ 3 8 6 )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int oldmask;
|
|
|
|
int access;
|
|
|
|
int share;
|
|
|
|
int permission;
|
|
|
|
int flagBits;
|
|
|
|
|
|
|
|
access = O_BINARY;
|
|
|
|
share = SH_DENYNO;
|
|
|
|
permission = 0;
|
|
|
|
flagBits = 0;
|
|
|
|
|
|
|
|
switch (open_mode) {
|
|
|
|
case LLIO_OPEN_R:
|
|
|
|
access |= O_RDONLY;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_RW:
|
|
|
|
access |= O_RDWR | O_CREAT;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_SYNC_RW:
|
|
|
|
access |= O_RDWR;
|
|
|
|
flagBits = FILE_WRITE_THROUGH_BIT;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_TRUNC_RW:
|
|
|
|
access |= O_RDWR | O_CREAT | O_TRUNC;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_EXISTING_RW:
|
|
|
|
access |= O_RDWR;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_SYNC_W:
|
|
|
|
access |= O_WRONLY | O_CREAT;
|
|
|
|
flagBits = FILE_WRITE_THROUGH_BIT;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_NEW_RW:
|
|
|
|
access |= O_CREAT | O_EXCL | O_RDWR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (share_flag)
|
|
|
|
oldmask = umask(0);
|
|
|
|
*file_desc = FEsopen(filename, access, share, permission,
|
|
|
|
flagBits, PrimaryDataStream);
|
|
|
|
if (share_flag)
|
|
|
|
umask(oldmask);
|
|
|
|
if (*file_desc == -1) {
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "FEsopen", filename, isc_io_open_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef NETWARE_386
|
|
|
|
int LLIO_open(
|
|
|
|
STATUS * status_vector,
|
|
|
|
TEXT * filename,
|
|
|
|
USHORT open_mode, USHORT share_flag, SLONG * file_desc)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ o p e n ( g e n e r i c )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int oldmask;
|
|
|
|
int mode;
|
|
|
|
|
|
|
|
switch (open_mode) {
|
|
|
|
case LLIO_OPEN_R:
|
|
|
|
mode = O_RDONLY;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_RW:
|
|
|
|
mode = O_RDWR | O_CREAT;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_SYNC_RW:
|
|
|
|
mode = O_RDWR | O_CREAT | O_SYNC;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_TRUNC_RW:
|
|
|
|
mode = O_RDWR | O_CREAT | O_TRUNC;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_EXISTING_RW:
|
|
|
|
mode = O_RDWR;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_WITH_SYNC_W:
|
|
|
|
mode = O_WRONLY | O_CREAT | O_SYNC;
|
|
|
|
break;
|
|
|
|
case LLIO_OPEN_NEW_RW:
|
|
|
|
mode = O_CREAT | O_EXCL | O_RDWR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (share_flag)
|
|
|
|
oldmask = umask(0);
|
|
|
|
*file_desc = open(filename, mode, 0666);
|
|
|
|
if (share_flag)
|
|
|
|
umask(oldmask);
|
|
|
|
if (*file_desc == -1) {
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "open", filename, isc_io_open_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_read(
|
|
|
|
STATUS * status_vector,
|
|
|
|
SLONG file_desc,
|
|
|
|
TEXT * filename,
|
|
|
|
SLONG offset,
|
|
|
|
USHORT whence,
|
|
|
|
UCHAR * buffer, SLONG length, SLONG * length_read)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ r e a d ( g e n e r i c )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Read a record from a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int len, i;
|
|
|
|
UCHAR *p;
|
|
|
|
|
|
|
|
if ((whence != LLIO_SEEK_NONE) &&
|
|
|
|
(LLIO_seek(status_vector, file_desc, filename, offset, whence) ==
|
|
|
|
FAILURE)) return FAILURE;
|
|
|
|
|
|
|
|
if (p = buffer)
|
|
|
|
for (i = 0; length && i++ < IO_RETRY;) {
|
|
|
|
if ((len = read((int) file_desc, p, (int) length)) == -1) {
|
|
|
|
if (SYSCALL_INTERRUPTED(errno) && i < IO_RETRY)
|
|
|
|
continue;
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "read", filename,
|
|
|
|
isc_io_read_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
if (!len)
|
|
|
|
break;
|
|
|
|
length -= len;
|
|
|
|
p += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length_read)
|
|
|
|
*length_read = p - buffer;
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_seek(
|
|
|
|
STATUS * status_vector,
|
|
|
|
SLONG file_desc, TEXT * filename, SLONG offset, USHORT whence)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ s e e k ( g e n e r i c )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Seek to the given offset.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
if (whence != LLIO_SEEK_NONE) {
|
|
|
|
switch (whence) {
|
|
|
|
case LLIO_SEEK_BEGIN:
|
|
|
|
whence = SEEK_SET;
|
|
|
|
break;
|
|
|
|
case LLIO_SEEK_CURRENT:
|
|
|
|
whence = SEEK_CUR;
|
|
|
|
break;
|
|
|
|
case LLIO_SEEK_END:
|
|
|
|
whence = SEEK_END;
|
|
|
|
break;
|
|
|
|
}
|
2001-07-12 07:46:06 +02:00
|
|
|
|
|
|
|
/* Darwin - Add the offset cast because the types are different
|
|
|
|
* between the implicit declaration and the actual declaration,
|
|
|
|
* causing problems with the stack frame, etc. Bad.
|
|
|
|
*/
|
|
|
|
if (lseek((int) file_desc, LSEEK_OFFSET_CAST offset, (int) whence) == -1) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "lseek", filename, isc_io_access_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_sync(STATUS * status_vector, SLONG file_desc)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ s y n c ( g e n e r i c )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Flush the buffers in a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2002-10-28 04:47:47 +01:00
|
|
|
#if defined NETWARE_386
|
2001-05-23 15:26:42 +02:00
|
|
|
return SUCCESS;
|
|
|
|
#else
|
|
|
|
return (fsync((int) file_desc) != -1) ? SUCCESS : FAILURE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int LLIO_write(
|
|
|
|
STATUS * status_vector,
|
|
|
|
SLONG file_desc,
|
|
|
|
TEXT * filename,
|
|
|
|
SLONG offset,
|
|
|
|
USHORT whence, UCHAR * buffer, SLONG length, SLONG * length_written)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* L L I O _ w r i t e ( g e n e r i c )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Write a record to a file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int len, i;
|
|
|
|
UCHAR *p;
|
|
|
|
|
|
|
|
if ((whence != LLIO_SEEK_NONE) &&
|
|
|
|
(LLIO_seek(status_vector, file_desc, filename, offset, whence) ==
|
|
|
|
FAILURE)) return FAILURE;
|
|
|
|
|
|
|
|
if (p = buffer)
|
|
|
|
for (i = 0; length && i++ < IO_RETRY;) {
|
|
|
|
if ((len = write((int) file_desc, p, (int) length)) == -1) {
|
|
|
|
if (SYSCALL_INTERRUPTED(errno) && i < IO_RETRY)
|
|
|
|
continue;
|
|
|
|
if (status_vector)
|
|
|
|
io_error(status_vector, "write", filename,
|
|
|
|
isc_io_write_err);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
if (!len)
|
|
|
|
break;
|
|
|
|
length -= len;
|
|
|
|
p += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length_written)
|
|
|
|
*length_written = p - buffer;
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void io_error(
|
|
|
|
STATUS * status_vector,
|
|
|
|
TEXT * op, TEXT * filename, STATUS operation)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i o _ e r r o r ( g e n e r i c )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Fill up the status_vector with error info.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
IBERR_build_status(status_vector, isc_io_error, gds_arg_string, op,
|
|
|
|
gds_arg_string, filename, isc_arg_gds, operation,
|
|
|
|
gds_arg_unix, errno, 0);
|
|
|
|
}
|
|
|
|
#endif
|