Release 960309
Fri Mar 8 19:07:18 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure.in]
Quote '[' and ']' in the test program for the strength-reduce
bug. This should work much better...
* [files/file.c]
Augmented DOS_FILE structure. Most internal functions now return a
DOS_FILE* instead of a Unix handle.
Added a local file array to replace the PDB list upon startup, to
allow using file I/O functions before the first task is created.
Added FILE_SetDateTime() and FILE_Sync() functions.
* [loader/module.c]
Use the DOS file I/O functions in MODULE_LoadExeHeader().
* [objects/bitblt.c]
Use visible region instead of GC clip region to clip source
area. This fixes the card drawing bug in freecell.
* [objects/region.c]
Fixed CombineRgn() to allow src and dest regions to be the same.
Fri Mar 8 16:32:23 1996 Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl>
* [controls/EDIT.TODO]
Updated so it reflects the current status.
* [controls/edit.c]
Implemented internal EDIT_WordBreakProc().
Implemented ES_READONLY.
Implemented WM_LBUTTONDBLCLK to select whole words.
Fixed a lot of types in the function definitions.
Wed Mar 6 19:55:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [debugger/info.c]
Added "walk window" command to walk window list.
* [windows/mdi.c]
Added proper(?) WM_MDISETMENU message handling.
Wed Mar 6 09:27:12 1996 Martin von Loewis <loewis@informatik.hu-berlin.de>
* [if1632/callback.c][if1632/relay32.c]
RELAY32_CallWindowProcConvStruct: new function.
* [win32/struct32.c][win32/Makefile.in][win32/param.c][win32/user32.c]
struct32.c: new file. Moved all structure conversions into that file
PARAM32_POINT32to16,MSG16to32,USER32_RECT32to16:
renamed to STRUCT32_POINT32to16, ...
WIN32_POINT,WIN32_MSG,WIN32_RECT,WIN32_PAINTSTRUCT: renamed to
POINT32, ...
New conversion functions for NCCALCSIZE_PARAMS, WINDOWPOS,
CREATESTRUCT.
* [include/windows.h][misc/exec.c]
WINHELP, MULTIKEYHELP, HELPWININFO: new structures
WinHelp: Reimplemented. Thanks to Peter Balch
(100710.2566@compuserve.com) for his valuable research.
* [win32/winprocs.c]
WIN32_CallWindowProcTo16: new function, call in
USER32_DefWindowProcA,...
Mon Mar 4 23:22:40 1996 Jim Peterson <jspeter@birch.ee.vt.edu>
* [include/wintypes.h]
Added "#define __export".
* [objects/bitblt.c]
Put in a few hacks to make bitblt-ing work when upside-down and/or
mirrored. BITBLT_StretchImage should really be checked over
thoroughly.
* [programs/progman/main.c]
Added "#include <resource.h>" for definition of HAVE_WINE_CONSTRUCTOR.
* [rc/parser.h] [rc/parser.l] [rc/parser.y] [rc/winerc.c]
Eliminated shift/reduce conflict in style definition.
Added crude error message support: "stdin:%d: parse error before '%s'".
Implemented string table support to the best of my ability (it works
with LoadString() calls).
* [windows/nonclient.c]
Fixed bug in NC_DoSizeMove() that made system menu pop up when title
bar of non-iconized window was clicked (checked for iconization).
Mon Mar 04 20:55:19 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [if1632/lzexpand.spec] [if1632/relay.c]
[include/lzexpand.h][misc/lzexpand.c]
LZEXPAND.DLL added.
Sun Mar 03 18:10:22 1996 Albrecht Kleine <kleine@ak.sax.de>
* [windows/win.c]
Prevent usage of invalid HWNDs in WIN_EnumChildWin(),
this prevents too early termination of EnumChildWindows().
diff --git a/files/file.c b/files/file.c
index 8ea3d1e..a16f929 100644
--- a/files/file.c
+++ b/files/file.c
@@ -8,11 +8,13 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
+#include <utime.h>
#include "windows.h"
#include "directory.h"
@@ -25,91 +27,115 @@
#include "task.h"
#include "stddebug.h"
#include "debug.h"
+#include "xmalloc.h"
#define MAX_OPEN_FILES 64 /* Max. open files for all tasks; must be <255 */
-typedef struct
+typedef struct tagDOS_FILE
{
- int unix_handle;
- int mode;
+ struct tagDOS_FILE *next;
+ int count; /* Usage count (0 if free) */
+ int unix_handle;
+ int mode;
+ char *unix_name;
+ WORD filedate;
+ WORD filetime;
} DOS_FILE;
/* Global files array */
-static DOS_FILE DOSFiles[MAX_OPEN_FILES];
+static DOS_FILE DOSFiles[MAX_OPEN_FILES] = { { 0, }, };
+static DOS_FILE *FILE_First = DOSFiles;
+static DOS_FILE *FILE_LastUsed = DOSFiles;
+
+/* Small file handles array for boot-up, before the first PDB is created */
+#define MAX_BOOT_HANDLES 4
+static BYTE bootFileHandles[MAX_BOOT_HANDLES] = { 0xff, 0xff, 0xff, 0xff };
/***********************************************************************
- * FILE_AllocDOSFile
+ * FILE_Alloc
*
- * Allocate a file from the DOS files array.
+ * Allocate a DOS file.
*/
-static BYTE FILE_AllocDOSFile( int unix_handle )
+static DOS_FILE *FILE_Alloc(void)
{
- BYTE i;
- for (i = 0; i < MAX_OPEN_FILES; i++) if (!DOSFiles[i].mode)
+ DOS_FILE *file = FILE_First;
+ if (file) FILE_First = file->next;
+ else if (FILE_LastUsed >= &DOSFiles[MAX_OPEN_FILES-1])
{
- DOSFiles[i].unix_handle = unix_handle;
- DOSFiles[i].mode = 1;
- return i;
+ DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
+ return NULL;
}
- return 0xff;
+ else file = ++FILE_LastUsed;
+ file->count = 1;
+ file->unix_handle = -1;
+ file->unix_name = NULL;
+ return file;
}
/***********************************************************************
- * FILE_FreeDOSFile
+ * FILE_Close
*
- * Free a file from the DOS files array.
+ * Close a DOS file.
*/
-static BOOL FILE_FreeDOSFile( BYTE handle )
+static BOOL FILE_Close( DOS_FILE *file )
{
- if (handle >= MAX_OPEN_FILES) return FALSE;
- if (!DOSFiles[handle].mode) return FALSE;
- DOSFiles[handle].mode = 0;
+ if (!file->count) return FALSE;
+ if (--file->count > 0) return TRUE;
+ /* Now really close the file */
+ if (file->unix_handle != -1) close( file->unix_handle );
+ if (file->unix_name) free( file->unix_name );
+ file->next = FILE_First;
+ FILE_First = file;
return TRUE;
}
/***********************************************************************
- * FILE_GetUnixHandle
+ * FILE_GetPDBFiles
*
- * Return the Unix handle for a global DOS file handle.
+ * Return a pointer to the current PDB files array.
*/
-static int FILE_GetUnixHandle( BYTE handle )
+static void FILE_GetPDBFiles( BYTE **files, WORD *nbFiles )
{
- if (handle >= MAX_OPEN_FILES) return -1;
- if (!DOSFiles[handle].mode) return -1;
- return DOSFiles[handle].unix_handle;
+ PDB *pdb;
+
+ if ((pdb = (PDB *)GlobalLock( GetCurrentPDB() )) != NULL)
+ {
+ *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+ *nbFiles = pdb->nbFiles;
+ }
+ else
+ {
+ *files = bootFileHandles;
+ *nbFiles = MAX_BOOT_HANDLES;
+ }
}
/***********************************************************************
* FILE_AllocTaskHandle
*
- * Allocate a per-task file handle.
+ * Allocate a task file handle for a DOS file.
*/
-static HFILE FILE_AllocTaskHandle( int unix_handle )
+static HFILE FILE_AllocTaskHandle( DOS_FILE *dos_file )
{
- PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
BYTE *files, *fp;
- WORD i;
+ WORD i, nbFiles;
- if (!pdb)
- {
- fprintf(stderr,"FILE_MakeTaskHandle: internal error, no current PDB.\n");
- exit(1);
- }
- files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+ FILE_GetPDBFiles( &files, &nbFiles );
fp = files + 1; /* Don't use handle 0, as some programs don't like it */
- for (i = pdb->nbFiles - 1; (i > 0) && (*fp != 0xff); i--, fp++);
- if (!i || (*fp = FILE_AllocDOSFile( unix_handle )) == 0xff)
+ for (i = nbFiles - 1; (i > 0) && (*fp != 0xff); i--, fp++);
+ if (!i)
{ /* No more handles or files */
DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
return -1;
}
+ *fp = dos_file ? (BYTE)(dos_file - DOSFiles) : 0;
dprintf_file(stddeb,
- "FILE_AllocTaskHandle: returning task handle %d, file %d for unix handle %d file %d of %d \n",
- (fp - files), *fp, unix_handle, pdb->nbFiles - i, pdb->nbFiles );
+ "FILE_AllocTaskHandle: returning task handle %d, dos_file %d, file %d of %d \n",
+ (fp - files), *fp, nbFiles - i, nbFiles );
return (HFILE)(fp - files);
}
@@ -121,19 +147,13 @@
*/
static void FILE_FreeTaskHandle( HFILE handle )
{
- PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
BYTE *files;
-
- if (!pdb)
- {
- fprintf(stderr,"FILE_FreeTaskHandle: internal error, no current PDB.\n");
- exit(1);
- }
- files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+ WORD nbFiles;
+
+ FILE_GetPDBFiles( &files, &nbFiles );
dprintf_file( stddeb,"FILE_FreeTaskHandle: dos=%d file=%d\n",
handle, files[handle] );
- if ((handle < 0) || (handle >= (INT)pdb->nbFiles) ||
- !FILE_FreeDOSFile( files[handle] ))
+ if ((handle < 0) || (handle >= (INT)nbFiles))
{
fprintf( stderr, "FILE_FreeTaskHandle: invalid file handle %d\n",
handle );
@@ -144,29 +164,49 @@
/***********************************************************************
- * FILE_GetUnixTaskHandle
+ * FILE_SetTaskHandle
*
- * Return the Unix file handle associated to a task file handle.
+ * Set the value of a task handle (no error checking).
*/
-int FILE_GetUnixTaskHandle( HFILE handle )
+static void FILE_SetTaskHandle( HFILE handle, DOS_FILE *file )
{
- PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
BYTE *files;
- int unix_handle;
+ WORD nbFiles;
- if (!pdb)
- {
- fprintf(stderr,"FILE_GetUnixHandle: internal error, no current PDB.\n");
- exit(1);
- }
- files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
- if ((handle < 0) || (handle >= (INT)pdb->nbFiles) ||
- ((unix_handle = FILE_GetUnixHandle( files[handle] )) == -1))
+ FILE_GetPDBFiles( &files, &nbFiles );
+ files[handle] = (BYTE)(file - DOSFiles);
+}
+
+
+/***********************************************************************
+ * FILE_GetFile
+ *
+ * Return the DOS file associated to a task file handle.
+ */
+static DOS_FILE *FILE_GetFile( HFILE handle )
+{
+ BYTE *files;
+ WORD nbFiles;
+ DOS_FILE *file;
+
+ FILE_GetPDBFiles( &files, &nbFiles );
+ if ((handle < 0) || (handle >= (INT)nbFiles) ||
+ (files[handle] >= MAX_OPEN_FILES) ||
+ !(file = &DOSFiles[files[handle]])->count)
{
DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
- return -1;
+ return NULL;
}
- return unix_handle;
+ return file;
+}
+
+
+int FILE_GetUnixHandle( HFILE hFile )
+{
+ DOS_FILE *file;
+
+ if (!(file = FILE_GetFile( hFile ))) return -1;
+ return file->unix_handle;
}
@@ -180,22 +220,14 @@
BYTE *files;
WORD count;
PDB *pdb = (PDB *)GlobalLock( hPDB );
- int unix_handle;
if (!pdb) return;
files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
dprintf_file(stddeb,"FILE_CloseAllFiles: closing %d files\n",pdb->nbFiles);
for (count = pdb->nbFiles; count > 0; count--, files++)
{
- if (*files != 0xff)
- {
- if ((unix_handle = FILE_GetUnixHandle( *files )) != -1)
- {
- close( unix_handle );
- FILE_FreeDOSFile( *files );
- }
- *files = 0xff;
- }
+ if (*files < MAX_OPEN_FILES) FILE_Close( &DOSFiles[*files] );
+ *files = 0xff;
}
}
@@ -251,42 +283,45 @@
/***********************************************************************
* FILE_OpenUnixFile
*/
-static int FILE_OpenUnixFile( const char *name, int mode )
+static DOS_FILE *FILE_OpenUnixFile( const char *name, int mode )
{
- int handle;
+ DOS_FILE *file;
struct stat st;
- if ((handle = open( name, mode )) == -1)
+ if (!(file = FILE_Alloc())) return NULL;
+ if ((file->unix_handle = open( name, mode )) == -1)
{
if (Options.allowReadOnly && (mode == O_RDWR))
{
- if ((handle = open( name, O_RDONLY )) != -1)
+ if ((file->unix_handle = open( name, O_RDONLY )) != -1)
fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", name );
}
}
- if (handle != -1) /* Make sure it's not a directory */
+ if ((file->unix_handle == -1) || (fstat( file->unix_handle, &st ) == -1))
{
- if ((fstat( handle, &st ) == -1))
- {
- FILE_SetDosError();
- close( handle );
- handle = -1;
- }
- else if (S_ISDIR(st.st_mode))
- {
- DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
- close( handle );
- handle = -1;
- }
+ FILE_SetDosError();
+ FILE_Close( file );
+ return NULL;
}
- return handle;
+ if (S_ISDIR(st.st_mode))
+ {
+ DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
+ FILE_Close( file );
+ return NULL;
+ }
+
+ /* File opened OK, now fill the DOS_FILE */
+
+ file->unix_name = xstrdup( name );
+ DOSFS_ToDosDateTime( st.st_mtime, &file->filedate, &file->filetime );
+ return file;
}
/***********************************************************************
* FILE_Open
*/
-int FILE_Open( LPCSTR path, int mode )
+static DOS_FILE *FILE_Open( LPCSTR path, int mode )
{
const char *unixName;
@@ -298,10 +333,10 @@
{
dprintf_file(stddeb, "FILE_Open: Non-existing device\n");
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
- return -1;
+ return NULL;
}
}
- else if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return -1;
+ else if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return NULL;
return FILE_OpenUnixFile( unixName, mode );
}
@@ -309,10 +344,10 @@
/***********************************************************************
* FILE_Create
*/
-int FILE_Create( LPCSTR path, int mode, int unique )
+static DOS_FILE *FILE_Create( LPCSTR path, int mode, int unique )
{
+ DOS_FILE *file;
const char *unixName;
- int handle;
dprintf_file(stddeb, "FILE_Create: '%s' %04x %d\n", path, mode, unique );
@@ -320,15 +355,30 @@
{
dprintf_file(stddeb, "FILE_Create: creating device '%s'!\n", unixName);
DOS_ERROR( ER_AccessDenied, EC_NotFound, SA_Abort, EL_Disk );
- return -1;
+ return NULL;
}
- if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) return -1;
- if ((handle = open( unixName,
- O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
- mode )) == -1)
+ if (!(file = FILE_Alloc())) return NULL;
+
+ if (!(unixName = DOSFS_GetUnixFileName( path, FALSE )))
+ {
+ FILE_Close( file );
+ return NULL;
+ }
+ if ((file->unix_handle = open( unixName,
+ O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
+ mode )) == -1)
+ {
FILE_SetDosError();
- return handle;
+ FILE_Close( file );
+ return NULL;
+ }
+
+ /* File created OK, now fill the DOS_FILE */
+
+ file->unix_name = xstrdup( unixName );
+ DOSFS_ToDosDateTime( time(NULL), &file->filedate, &file->filetime );
+ return file;
}
@@ -375,36 +425,78 @@
}
if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0);
if (psize) *psize = S_ISDIR(st.st_mode) ? 0 : st.st_size;
- DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime );
+ DOSFS_ToDosDateTime( st.st_mtime, pdate, ptime );
return 1;
}
/***********************************************************************
- * FILE_Fstat
+ * FILE_GetDateTime
*
- * Stat a DOS handle. Return 1 if OK.
+ * Get the date and time of a file.
*/
-int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize,
- WORD *pdate, WORD *ptime )
+int FILE_GetDateTime( HFILE hFile, WORD *pdate, WORD *ptime, BOOL refresh )
{
- struct stat st;
- int handle;
+ DOS_FILE *file;
- if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return 0;
- if (fstat( handle, &st ) == -1)
+ if (!(file = FILE_GetFile( hFile ))) return 0;
+ if (refresh)
{
- FILE_SetDosError();
- return 0;
+ struct stat st;
+ if (fstat( file->unix_handle, &st ) == -1)
+ {
+ FILE_SetDosError();
+ return 0;
+ }
+ DOSFS_ToDosDateTime( st.st_mtime, &file->filedate, &file->filetime );
}
- if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0);
- if (psize) *psize = S_ISDIR(st.st_mode) ? 0 : st.st_size;
- DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime );
+ *pdate = file->filedate;
+ *ptime = file->filetime;
return 1;
}
/***********************************************************************
+ * FILE_SetDateTime
+ *
+ * Set the date and time of a file.
+ */
+int FILE_SetDateTime( HFILE hFile, WORD date, WORD time )
+{
+ DOS_FILE *file;
+ struct tm newtm;
+ struct utimbuf filetime;
+
+ if (!(file = FILE_GetFile( hFile ))) return 0;
+ newtm.tm_sec = (time & 0x1f) * 2;
+ newtm.tm_min = (time >> 5) & 0x3f;
+ newtm.tm_hour = (time >> 11);
+ newtm.tm_mday = (date & 0x1f);
+ newtm.tm_mon = ((date >> 5) & 0x0f) - 1;
+ newtm.tm_year = (date >> 9) + 80;
+
+ filetime.actime = filetime.modtime = mktime( &newtm );
+ if (utime( file->unix_name, &filetime ) != -1) return 1;
+ FILE_SetDosError();
+ return 0;
+}
+
+
+/***********************************************************************
+ * FILE_Sync
+ */
+int FILE_Sync( HFILE hFile )
+{
+ DOS_FILE *file;
+
+ if (!(file = FILE_GetFile( hFile ))) return 0;
+ if (fsync( file->unix_handle ) != -1) return 1;
+ FILE_SetDosError();
+ return 0;
+}
+
+
+/***********************************************************************
* FILE_MakeDir
*/
int FILE_MakeDir( LPCSTR path )
@@ -461,20 +553,14 @@
*/
HFILE FILE_Dup( HFILE hFile )
{
- int handle, newhandle;
- HFILE dosHandle;
+ DOS_FILE *file;
+ HFILE handle;
- if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR;
- dprintf_file( stddeb, "FILE_Dup for handle %d\n",handle);
- if ((newhandle = dup(handle)) == -1)
- {
- FILE_SetDosError();
- return HFILE_ERROR;
- }
- if ((dosHandle = FILE_AllocTaskHandle( newhandle )) == HFILE_ERROR)
- close( newhandle );
- dprintf_file( stddeb, "FILE_Dup return handle %d\n",dosHandle);
- return dosHandle;
+ dprintf_file( stddeb, "FILE_Dup for handle %d\n", hFile );
+ if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR;
+ if ((handle = FILE_AllocTaskHandle( file )) != HFILE_ERROR) file->count++;
+ dprintf_file( stddeb, "FILE_Dup return handle %d\n", handle );
+ return handle;
}
@@ -485,73 +571,138 @@
*/
HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 )
{
+ DOS_FILE *file;
PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
- BYTE *files;
- int handle, newhandle;
+ BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
- if ((handle = FILE_GetUnixTaskHandle( hFile1 )) == -1) return HFILE_ERROR;
- dprintf_file( stddeb, "FILE_Dup2 for handle %d\n",handle);
+ dprintf_file( stddeb, "FILE_Dup2 for handle %d\n", hFile1 );
+ if (!(file = FILE_GetFile( hFile1 ))) return HFILE_ERROR;
+
if ((hFile2 < 0) || (hFile2 >= (INT)pdb->nbFiles))
{
DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
return HFILE_ERROR;
}
-
- if ((newhandle = dup(handle)) == -1)
+ if (files[hFile2] < MAX_OPEN_FILES)
{
- FILE_SetDosError();
- return HFILE_ERROR;
+ dprintf_file( stddeb, "FILE_Dup2 closing old handle2 %d\n",
+ files[hFile2] );
+ FILE_Close( &DOSFiles[files[hFile2]] );
}
- if (newhandle >= 0xff)
- {
- DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
- close( newhandle );
- return HFILE_ERROR;
- }
- files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
- if (files[hFile2] != 0xff)
- {
- dprintf_file( stddeb, "FILE_Dup2 closing old handle2 %d\n",
- files[hFile2]);
- close( files[hFile2] );
- }
- files[hFile2] = (BYTE)newhandle;
- dprintf_file( stddeb, "FILE_Dup2 return handle2 %d\n",newhandle);
+ files[hFile2] = (BYTE)(file - DOSFiles);
+ file->count++;
+ dprintf_file( stddeb, "FILE_Dup2 return handle2 %d\n", hFile2 );
return hFile2;
}
/***********************************************************************
- * FILE_OpenFile
- *
- * Implementation of API function OpenFile(). Returns a Unix file handle.
+ * FILE_Read
*/
-int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
+LONG FILE_Read( HFILE hFile, void *buffer, LONG count )
{
+ DOS_FILE *file;
+ LONG result;
+
+ dprintf_file( stddeb, "FILE_Read: %d %p %ld\n", hFile, buffer, count );
+ if (!(file = FILE_GetFile( hFile ))) return -1;
+ if (!count) return 0;
+ if ((result = read( file->unix_handle, buffer, count )) == -1)
+ FILE_SetDosError();
+ return result;
+}
+
+
+/***********************************************************************
+ * GetTempFileName (KERNEL.97)
+ */
+INT GetTempFileName( BYTE drive, LPCSTR prefix, UINT unique, LPSTR buffer )
+{
+ int i;
+ UINT num = unique ? (unique & 0xffff) : time(NULL) & 0xffff;
+ char *p;
+
+ if (drive & TF_FORCEDRIVE)
+ {
+ sprintf( buffer, "%c:", drive & ~TF_FORCEDRIVE );
+ }
+ else
+ {
+ DIR_GetTempDosDir( buffer, 132 ); /* buffer must be at least 144 */
+ strcat( buffer, "\\" );
+ }
+
+ p = buffer + strlen(buffer);
+ for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
+ sprintf( p, "%04x.tmp", num );
+
+ if (unique)
+ {
+ lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
+ dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
+ return unique;
+ }
+
+ /* Now try to create it */
+
+ do
+ {
+ DOS_FILE *file;
+ if ((file = FILE_Create( buffer, 0666, TRUE )) != NULL)
+ { /* We created it */
+ dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer );
+ FILE_Close( file );
+ break;
+ }
+ if (DOS_ExtendedError != ER_FileExists) break; /* No need to go on */
+ num++;
+ sprintf( p, "%04x.tmp", num );
+ } while (num != (unique & 0xffff));
+
+ lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
+ dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
+ return num;
+}
+
+
+/***********************************************************************
+ * OpenFile (KERNEL.74)
+ */
+HFILE OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
+{
+ DOS_FILE *file;
+ HFILE hFileRet;
+ WORD filedatetime[2];
const char *unixName, *dosName;
char *p;
- int handle, len, i, unixMode;
- struct stat st;
+ int len, i, unixMode;
ofs->cBytes = sizeof(OFSTRUCT);
ofs->nErrCode = 0;
if (mode & OF_REOPEN) name = ofs->szPathName;
- dprintf_file( stddeb, "FILE_Openfile: %s %04x\n", name, mode );
+ dprintf_file( stddeb, "OpenFile: %s %04x\n", name, mode );
+
+ /* First allocate a task handle */
+
+ if ((hFileRet = FILE_AllocTaskHandle( NULL )) == HFILE_ERROR)
+ {
+ ofs->nErrCode = DOS_ExtendedError;
+ dprintf_file( stddeb, "OpenFile: no more task handles.\n" );
+ return HFILE_ERROR;
+ }
/* OF_PARSE simply fills the structure */
if (mode & OF_PARSE)
{
- if (!(dosName = DOSFS_GetDosTrueName( name, FALSE )))
- {
- ofs->nErrCode = DOS_ExtendedError;
- dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name);
- return -1;
- }
+ if (!(dosName = DOSFS_GetDosTrueName( name, FALSE ))) goto error;
lstrcpyn( ofs->szPathName, dosName, sizeof(ofs->szPathName) );
ofs->fFixedDisk = (GetDriveType( dosName[0]-'A' ) != DRIVE_REMOVABLE);
- dprintf_file( stddeb, "FILE_Openfile: %s return = 0\n", name);
- return 0;
+ dprintf_file( stddeb, "OpenFile(%s): OF_PARSE, res = '%s', %d\n",
+ name, ofs->szPathName, hFileRet );
+ /* Return the handle, but close it first */
+ FILE_FreeTaskHandle( hFileRet );
+ return hFileRet;
}
/* OF_CREATE is completely different from all other options, so
@@ -559,25 +710,10 @@
if (mode & OF_CREATE)
{
- if ((unixName = DOSFS_GetUnixFileName( name, FALSE )) == NULL)
- {
- ofs->nErrCode = DOS_ExtendedError;
- dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name);
- return -1;
- }
- dprintf_file( stddeb, "FILE_OpenFile: creating '%s'\n", unixName );
- handle = open( unixName, O_TRUNC | O_RDWR | O_CREAT, 0666 );
- if (handle == -1)
- {
- FILE_SetDosError();
- ofs->nErrCode = DOS_ExtendedError;
- dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name);
- return -1;
- }
+ if (!(file = FILE_Create( name, 0666, FALSE ))) goto error;
lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( name, FALSE ),
sizeof(ofs->szPathName) );
- dprintf_file( stddeb, "FILE_Openfile: %s return = %d \n", name, handle);
- return handle;
+ goto success;
}
/* Now look for the file */
@@ -638,30 +774,25 @@
for (i = 0; ; i++)
{
- if (!DIR_GetDosPath( i, ofs->szPathName, len )) break;
+ if (!DIR_GetDosPath( i, ofs->szPathName, len )) goto not_found;
strcat( ofs->szPathName, "\\" );
strcat( ofs->szPathName, name );
if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE)) != NULL)
- goto found;
+ break;
}
-not_found:
- dprintf_file( stddeb, "FILE_OpenFile: '%s' not found\n", name );
- DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
- ofs->nErrCode = ER_FileNotFound;
- dprintf_file( stddeb, "FILE_Openfile: %s return =-1\n", name);
- return -1;
-
found:
- dprintf_file( stddeb, "FILE_OpenFile: found '%s'\n", unixName );
+ dprintf_file( stddeb, "OpenFile: found '%s'\n", unixName );
lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( ofs->szPathName, FALSE ),
sizeof(ofs->szPathName) );
if (mode & OF_DELETE)
{
if (unlink( unixName ) == -1) goto not_found;
- dprintf_file( stddeb, "FILE_Openfile: %s return = 0\n", name);
- return 0;
+ dprintf_file( stddeb, "OpenFile(%s): OF_DELETE return = OK\n", name);
+ /* Return the handle, but close it first */
+ FILE_FreeTaskHandle( hFileRet );
+ return hFileRet;
}
switch(mode & 3)
@@ -675,119 +806,45 @@
unixMode = O_RDONLY; break;
}
- if ((handle = FILE_OpenUnixFile( unixName, unixMode )) == -1)
- goto not_found;
-
- if (fstat( handle, &st ) != -1)
+ if (!(file = FILE_OpenUnixFile( unixName, unixMode ))) goto not_found;
+ filedatetime[0] = file->filedate;
+ filedatetime[1] = file->filetime;
+ if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
{
- if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
+ if (memcmp( ofs->reserved, filedatetime, sizeof(ofs->reserved) ))
{
- if (memcmp( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) ))
- {
- dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name);
- close( handle );
- return -1;
- }
+ FILE_Close( file );
+ dprintf_file( stddeb, "OpenFile(%s): OF_VERIFY failed\n", name );
+ /* FIXME: what error here? */
+ DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+ goto error;
}
- memcpy( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) );
}
+ memcpy( ofs->reserved, filedatetime, sizeof(ofs->reserved) );
if (mode & OF_EXIST)
{
- close( handle );
- return 0;
- }
- dprintf_file( stddeb, "FILE_Openfile: %s return = %d\n", name,handle);
-
- return handle;
-}
-
-
-/***********************************************************************
- * FILE_Read
- */
-LONG FILE_Read( HFILE hFile, LPSTR buffer, LONG count )
-{
- int handle;
- LONG result;
-
- dprintf_file( stddeb, "FILE_Read: %d %p %ld\n", hFile, buffer, count );
- if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return -1;
- if (!count) return 0;
- if ((result = read( handle, buffer, count )) == -1) FILE_SetDosError();
- return result;
-}
-
-
-/***********************************************************************
- * GetTempFileName (KERNEL.97)
- */
-INT GetTempFileName( BYTE drive, LPCSTR prefix, UINT unique, LPSTR buffer )
-{
- int i, handle;
- UINT num = unique ? (unique & 0xffff) : time(NULL) & 0xffff;
- char *p;
-
- if (drive & TF_FORCEDRIVE)
- {
- sprintf( buffer, "%c:", drive & ~TF_FORCEDRIVE );
- }
- else
- {
- DIR_GetTempDosDir( buffer, 132 ); /* buffer must be at least 144 */
- strcat( buffer, "\\" );
+ FILE_Close( file );
+ /* Return the handle, but close it first */
+ FILE_FreeTaskHandle( hFileRet );
+ return hFileRet;
}
- p = buffer + strlen(buffer);
- for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
- sprintf( p, "%04x.tmp", num );
+success: /* We get here if the open was successful */
+ dprintf_file( stddeb, "OpenFile(%s): OK, return = %d\n", name, hFileRet );
+ FILE_SetTaskHandle( hFileRet, file );
+ return hFileRet;
- if (unique)
- {
- lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
- dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
- return unique;
- }
+not_found: /* We get here if the file does not exist */
+ dprintf_file( stddeb, "OpenFile: '%s' not found\n", name );
+ DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+ /* fall through */
- /* Now try to create it */
-
- do
- {
- if ((handle = FILE_Create( buffer, 0666, TRUE )) != -1)
- { /* We created it */
- dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer );
- close( handle );
- break;
- }
- if (DOS_ExtendedError != ER_FileExists) break; /* No need to go on */
- num++;
- sprintf( p, "%04x.tmp", num );
- } while (num != (unique & 0xffff));
-
- lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
- dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
- return num;
-}
-
-
-/***********************************************************************
- * OpenFile (KERNEL.74)
- */
-HFILE OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
-{
- int unixHandle;
- HFILE handle;
-
- dprintf_file( stddeb, "OpenFile %s \n",name);
- if ((unixHandle = FILE_OpenFile( name, ofs, mode )) == -1)
- return HFILE_ERROR;
- if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
- {
- ofs->nErrCode = DOS_ExtendedError;
- if (unixHandle) close( unixHandle );
- }
- if (!unixHandle) FILE_FreeTaskHandle( handle );
- return handle;
+error: /* We get here if there was an error opening the file */
+ ofs->nErrCode = DOS_ExtendedError;
+ dprintf_file( stddeb, "OpenFile(%s): return = HFILE_ERROR\n", name );
+ FILE_FreeTaskHandle( hFileRet );
+ return HFILE_ERROR;
}
@@ -796,18 +853,12 @@
*/
HFILE _lclose( HFILE hFile )
{
- int handle;
+ DOS_FILE *file;
-
- if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR;
- dprintf_file( stddeb, "_lclose: doshandle %d unixhandle %d\n", hFile,handle );
- if (handle <= 2)
- {
- fprintf( stderr, "_lclose: internal error: closing handle %d\n", handle );
- exit(1);
- }
+ dprintf_file( stddeb, "_lclose: handle %d\n", hFile );
+ if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR;
+ FILE_Close( file );
FILE_FreeTaskHandle( hFile );
- close( handle );
return 0;
}
@@ -826,15 +877,15 @@
*/
INT _lcreat( LPCSTR path, INT attr )
{
- int unixHandle, mode;
+ DOS_FILE *file;
HFILE handle;
+ int mode;
dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr );
mode = (attr & 1) ? 0444 : 0666;
- if ((unixHandle = FILE_Create( path, mode, FALSE )) == -1)
- return HFILE_ERROR;
- if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
- close( unixHandle );
+ if (!(file = FILE_Create( path, mode, FALSE ))) return HFILE_ERROR;
+ if ((handle = FILE_AllocTaskHandle( file )) == HFILE_ERROR)
+ FILE_Close( file );
return handle;
}
@@ -844,15 +895,15 @@
*/
INT _lcreat_uniq( LPCSTR path, INT attr )
{
- int unixHandle, mode;
+ DOS_FILE *file;
HFILE handle;
+ int mode;
dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr );
mode = (attr & 1) ? 0444 : 0666;
- if ((unixHandle = FILE_Create( path, mode, TRUE )) == -1)
- return HFILE_ERROR;
- if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
- close( unixHandle );
+ if (!(file = FILE_Create( path, mode, TRUE ))) return HFILE_ERROR;
+ if ((handle = FILE_AllocTaskHandle( file )) == HFILE_ERROR)
+ FILE_Close( file );
return handle;
}
@@ -862,12 +913,13 @@
*/
LONG _llseek( HFILE hFile, LONG lOffset, INT nOrigin )
{
- int handle, origin, result;
+ DOS_FILE *file;
+ int origin, result;
dprintf_file( stddeb, "_llseek: handle %d, offset %ld, origin %d\n",
hFile, lOffset, nOrigin);
- if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR;
+ if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR;
switch(nOrigin)
{
case 1: origin = SEEK_CUR; break;
@@ -875,8 +927,9 @@
default: origin = SEEK_SET; break;
}
- if ((result = lseek( handle, lOffset, origin )) == -1) FILE_SetDosError();
- return (result == -1) ? HFILE_ERROR : result;
+ if ((result = lseek( file->unix_handle, lOffset, origin )) == -1)
+ FILE_SetDosError();
+ return result;
}
@@ -885,7 +938,7 @@
*/
HFILE _lopen( LPCSTR path, INT mode )
{
- int unixHandle;
+ DOS_FILE *file;
int unixMode;
HFILE handle;
@@ -904,9 +957,9 @@
unixMode = O_RDONLY;
break;
}
- if ((unixHandle = FILE_Open( path, unixMode )) == -1) return HFILE_ERROR;
- if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
- close( unixHandle );
+ if (!(file = FILE_Open( path, unixMode ))) return HFILE_ERROR;
+ if ((handle = FILE_AllocTaskHandle( file )) == HFILE_ERROR)
+ FILE_Close( file );
return handle;
}
@@ -944,20 +997,21 @@
*/
LONG _hwrite( HFILE hFile, LPCSTR buffer, LONG count )
{
- int handle;
+ DOS_FILE *file;
LONG result;
dprintf_file( stddeb, "_hwrite: %d %p %ld\n", hFile, buffer, count );
- if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR;
+ if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR;
if (count == 0) /* Expand or truncate at current position */
- result = ftruncate( handle, lseek( handle, 0, SEEK_CUR ) );
+ result = ftruncate( file->unix_handle,
+ lseek( file->unix_handle, 0, SEEK_CUR ) );
else
- result = write( handle, buffer, count );
+ result = write( file->unix_handle, buffer, count );
if (result == -1) FILE_SetDosError();
- return (result == -1) ? HFILE_ERROR : result;
+ return result;
}