Release 970112
Sat Jan 11 18:17:59 1997 Alexandre Julliard <julliard@lrc.epfl.ch>
* [controls/menu.c]
Updated to new Win32 types.
* [controls/listbox.c]
Fixed Winfile extended selection bug.
* [files/directory.c]
Changed DIR_SearchPath to return both long and short file names.
* [files/dos_fs.c]
Implemented VFAT ioctl to retrieve the original short filenames
from a VFAT filesystem (Linux only for now).
Replaced DOSFS_GetUnixFileName()/DOSFS_GetDosTrueName() by
DOS_GetFullName().
Properly implemented GetShortPathName() and GetFullPathName().
Made all functions re-entrant.
* [files/file.c] [misc/main.c]
Replaced -allowreadonly option by -failreadonly. The default is
now to report success when opening a read-only file for writing.
* [objects/metafile.c]
Fixed bug in DIB bitmaps pointer calculation.
* [scheduler/process.c]
Implemented environment strings and Get/SetStdHandle with process
environment block.
* [tools/build.c]
Rewrote BuildContext32() to avoid instructions that may not be
supported by all assemblers.
Fri Jan 10 17:11:09 1997 David Faure <david.faure@ifhamy.insa-lyon.fr>
* [windows/event.c]
Created table keyc2vkey, which associate a vkey(+extended bit) to
any keycode. Changed EVENT_event_to_vkey to use this table to
return the correct vkey. Changed EVENT_ToAscii to get the keycode
from this table too. Assigned OEM specific vkeys arbitrarily.
Fri Jan 10 09:26:17 1997 John Harvey <john@division.co.uk>
* [misc/winsock.c] [misc/winsoc_async.c]
Fixed svr4 header files.
Changed bzero() to memset().
* [tools/fnt2bdf.c]
Removed bcopy() and used memcpy() instead.
* [debugger/msc.c]
Include string.h instead of strings.h
* [debugger/stabs.c]
Include string.h instead of strings.h.
Define __ELF__ for svr4 systems.
* [loader/signal.c]
Use wait() instead of wait4() which doesnt exist on Unixware.
* [memory/global.c]
Use sysconf() instead of getpagesize() for svr4 systems.
Thu Jan 9 21:07:20 1997 Robert Pouliot <krynos@clic.net>
* [Make.rules.in] [Makefile.in] [make_os2.sh] [rc/Makefile.in]
[tools/Makefile.in] [documentation/wine_os2.txt]
Patches for OS/2 support. Note that it doesn't compile yet.
Tue Jan 7 20:03:53 1997 Eric Youngdale <eric@sub2304.jic.com>
* [debugger/*]
Many more debugger improvements (see debugger/README for details).
Tue Jan 7 15:12:21 1997 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [windows/graphics.c] [objects/text.c] [graphics/x11drv/*]
[graphics/metafiledrv/*]
Moved some device dependent code into the resp. subdirs.
* [include/gdi.h] [include/metafiledrv.h] [include/x11drv.h]
Prototypes added,
DC_FUNCTIONS: GetPixel added, some unnecessary functions removed.
* [objects/region.c]
CreatePolyPolygonRgn32 added.
* [files/dos_fs.c]
QueryDosDevice added.
* [misc/lstr.c]
FormatMessage: broken heap management fixed.
* [scheduler/process.c] [scheduler/thread.c]
Get/SetThreadPriority/PriorityClass added.
Mon Jan 6 21:55:30 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
* [misc/keyboard.c]
ToAscii : Use EVENT_ToAscii instead.
* [windows/event.c]
keypad_key : Do not convert XK_Mode_switch to VK_MENU; recognize
keypad cursor keys.
EVENT_event_to_vkey : New function, to transform a X keycode
into a MSwin vkey + extended bit.
EVENT_ToAscii : New function, to transform a vkey + extended bit
(+ key state table) into ascii char(s), using XLookupString, and
recognizing dead chars.
EVENT_key : Transform AltGr into Ctrl+Alt sequence; call
EVENT_event_to_vkey for keycode to vkey conversion; fixed
previous, context and extended bits.
* [windows/keyboard.c]
Include stddebug.h, to get -debugmsg messages.
GetKeyState : Handle VK_MBUTTON case.
GetKeyboardState, SetKeyboardState : Debugging messages added.
* [windows/message.c]
TranslateMessage : Handle dead chars.
Mon Jan 6 20:10:11 1997 Dominik Strasser <bm424953@muenchen.org>
* [if1632/crtdll.spec] [misc/crtdll.c]
C++ functions new/delete/set_new_handler implemented.
Mon Jan 6 15:48:15 1997 Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
* [controls/edit.c] [include/windows.h]
Moved the edit control to 32 bits.
Included new (win95) message definitions in windows.h
Implemented EM_SCROLLCARET, EM_SETMARGINS, EM_GETMARGINS,
EM_GETLIMITTEXT, EM_POSFROMCHAR, EM_CHARFROMPOS.
Broke EM_SETWORDBREAKPROC (internal wordwrap still works).
Fixed some bugs, introduced a couple of others.
Text buffer is now initially in 32-bit heap.
* [controls/EDIT.TODO] [controls/combo.c] [controls/widgets.c]
[if1632/wprocs.spec] [library/miscstubs.c] [windows/defdlg.c]
[misc/commdlg.c]
Updated to work with 32-bit edit control.
Sat Jan 4 22:07:27 1997 O.Flebbe <O.Flebbe@science-computing.uni-tuebingen.de>
* [loader/pe_image.c]
Use mmap rather then malloc. Better workaround for clean
segments.
diff --git a/files/directory.c b/files/directory.c
index 157fea4..1c64f74 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -6,13 +6,13 @@
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include "windows.h"
#include "winerror.h"
-#include "dos_fs.h"
#include "drive.h"
#include "file.h"
#include "heap.h"
@@ -43,25 +43,20 @@
char **dos_path, char **unix_path )
{
char path[MAX_PATHNAME_LEN];
- const char *dos_name ,*unix_name;
+ DOS_FULL_NAME full_name;
+
BY_HANDLE_FILE_INFORMATION info;
PROFILE_GetWineIniString( "wine", keyname, defval, path, sizeof(path) );
- if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) ||
- !FILE_Stat( unix_name, &info ) ||
+ if (!DOSFS_GetFullName( path, TRUE, &full_name ) ||
+ !FILE_Stat( full_name.long_name, &info ) ||
!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
fprintf(stderr, "Invalid path '%s' for %s directory\n", path, keyname);
return 0;
}
- if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE )))
- {
- fprintf( stderr, "Could not get DOS name for %s directory '%s'\n",
- keyname, unix_name );
- return 0;
- }
- *unix_path = HEAP_strdupA( SystemHeap, 0, unix_name );
- *dos_path = HEAP_strdupA( SystemHeap, 0, dos_name );
+ *unix_path = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
+ *dos_path = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
return 1;
}
@@ -72,7 +67,7 @@
void DIR_ParseWindowsPath( char *path )
{
char *p;
- const char *dos_name ,*unix_name;
+ DOS_FULL_NAME full_name;
BY_HANDLE_FILE_INFORMATION info;
int i;
@@ -87,22 +82,18 @@
MAX_PATH_ELEMENTS );
break;
}
- if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) ||
- !FILE_Stat( unix_name, &info ) ||
+ if (!DOSFS_GetFullName( path, TRUE, &full_name ) ||
+ !FILE_Stat( full_name.long_name, &info ) ||
!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
fprintf(stderr,"Warning: invalid dir '%s' in path, deleting it.\n",
path );
continue;
}
- if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE )))
- {
- fprintf( stderr, "Warning: could not get DOS name for '%s' in path, deleting it.\n",
- unix_name );
- continue;
- }
- DIR_UnixPath[DIR_PathElements] = HEAP_strdupA(SystemHeap,0,unix_name);
- DIR_DosPath[DIR_PathElements] = HEAP_strdupA(SystemHeap,0,dos_name);
+ DIR_UnixPath[DIR_PathElements] = HEAP_strdupA( SystemHeap, 0,
+ full_name.long_name );
+ DIR_DosPath[DIR_PathElements] = HEAP_strdupA( SystemHeap, 0,
+ full_name.short_name );
DIR_PathElements++;
}
@@ -137,9 +128,8 @@
}
else
{
- cwd = DOSFS_GetDosTrueName( path, TRUE );
DRIVE_SetCurrentDrive( drive );
- DRIVE_Chdir( drive, cwd + 2 );
+ DRIVE_Chdir( drive, cwd );
}
if (!(DIR_GetPath( "windows", "c:\\windows",
@@ -344,7 +334,8 @@
*/
BOOL32 CreateDirectory32A( LPCSTR path, LPSECURITY_ATTRIBUTES lpsecattribs )
{
- const char *unixName;
+ DOS_FULL_NAME full_name;
+ LPCSTR unixName;
dprintf_file( stddeb, "CreateDirectory32A(%s,%p)\n", path, lpsecattribs );
if ((unixName = DOSFS_IsDevice( path )) != NULL)
@@ -353,8 +344,8 @@
DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
return FALSE;
}
- if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) return 0;
- if ((mkdir( unixName, 0777 ) == -1) && (errno != EEXIST))
+ if (!DOSFS_GetFullName( path, FALSE, &full_name )) return 0;
+ if ((mkdir( full_name.long_name, 0777 ) == -1) && (errno != EEXIST))
{
FILE_SetDosError();
return FALSE;
@@ -409,7 +400,8 @@
*/
BOOL32 RemoveDirectory32A( LPCSTR path )
{
- const char *unixName;
+ DOS_FULL_NAME full_name;
+ LPCSTR unixName;
dprintf_file(stddeb, "RemoveDirectory: '%s'\n", path );
@@ -419,8 +411,8 @@
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
return FALSE;
}
- if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return FALSE;
- if (rmdir( unixName ) == -1)
+ if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
+ if (rmdir( full_name.long_name ) == -1)
{
FILE_SetDosError();
return FALSE;
@@ -442,6 +434,56 @@
/***********************************************************************
+ * DIR_TryPath
+ *
+ * Helper function for DIR_SearchPath.
+ */
+static BOOL32 DIR_TryPath( LPCSTR unix_dir, LPCSTR dos_dir, LPCSTR name,
+ DOS_FULL_NAME *full_name )
+{
+ LPSTR p_l = full_name->long_name + strlen(unix_dir) + 1;
+ LPSTR p_s = full_name->short_name + strlen(dos_dir) + 1;
+
+ if ((p_s >= full_name->short_name + sizeof(full_name->short_name) - 14) ||
+ (p_l >= full_name->long_name + sizeof(full_name->long_name) - 1))
+ {
+ DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
+ return FALSE;
+ }
+ if (!DOSFS_FindUnixName( unix_dir, name, p_l,
+ sizeof(full_name->long_name) - (p_l - full_name->long_name),
+ p_s, DRIVE_GetFlags( dos_dir[0] - 'A' ) ))
+ return FALSE;
+ strcpy( full_name->long_name, unix_dir );
+ p_l[-1] = '/';
+ strcpy( full_name->short_name, dos_dir );
+ p_s[-1] = '\\';
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * DIR_TryModulePath
+ *
+ * Helper function for DIR_SearchPath.
+ */
+static BOOL32 DIR_TryModulePath( LPCSTR name, DOS_FULL_NAME *full_name )
+{
+ /* FIXME: for now, GetModuleFileName32A can't return more */
+ /* than OFS_MAXPATHNAME. This may change with Win32. */
+ char buffer[OFS_MAXPATHNAME];
+ LPSTR p;
+
+ if (!GetCurrentTask()) return FALSE;
+ GetModuleFileName32A( GetCurrentTask(), buffer, sizeof(buffer) );
+ if (!(p = strrchr( buffer, '\\' ))) return FALSE;
+ if (sizeof(buffer) - (++p - buffer) <= strlen(name)) return FALSE;
+ strcpy( p, name );
+ return DOSFS_GetFullName( buffer, TRUE, full_name );
+}
+
+
+/***********************************************************************
* DIR_SearchPath
*
* Implementation of SearchPath32A. 'win32' specifies whether the search
@@ -450,17 +492,24 @@
* FIXME: should return long path names.
*/
DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
- DWORD buflen, LPSTR buffer, LPSTR *lastpart,
- BOOL32 win32 )
+ DOS_FULL_NAME *full_name, BOOL32 win32 )
{
DWORD len;
- LPSTR tmp;
+ LPCSTR p;
int i;
+ LPSTR tmp = NULL;
+ BOOL32 ret = TRUE;
/* First check the supplied parameters */
- if (strchr( name, '.' )) ext = NULL; /* Ignore the specified extension */
+ if (!(p = strrchr( name, '\\' ))) p = name;
+ if (!(p = strrchr( p, '/' ))) p = name;
+ if (strchr( p, '.' )) ext = NULL; /* Ignore the specified extension */
+ if ((*name && (name[1] == ':')) ||
+ strchr( name, '/' ) || strchr( name, '\\' ))
+ path = NULL; /* Ignore path if name already contains a path */
if (path && !*path) path = NULL; /* Ignore empty path */
+
len = strlen(name);
if (ext) len += strlen(ext);
if (path) len += strlen(path) + 1;
@@ -482,110 +531,52 @@
}
else strcpy( tmp, name );
if (ext) strcat( tmp, ext );
+ name = tmp;
}
- else tmp = (LPSTR)name;
/* If we have an explicit path, everything's easy */
- if (path || (*tmp && (tmp[1] == ':')) ||
- strchr( tmp, '/' ) || strchr( tmp, '\\' ))
+ if (path || (*name && (name[1] == ':')) ||
+ strchr( name, '/' ) || strchr( name, '\\' ))
{
- if (!DOSFS_GetUnixFileName( tmp, TRUE )) goto not_found;
- lstrcpyn32A( buffer, tmp, buflen );
- if (tmp != name) HeapFree( GetProcessHeap(), 0, tmp );
- return len;
+ ret = DOSFS_GetFullName( name, TRUE, full_name );
+ goto done;
}
/* Try the path of the current executable (for Win32 search order) */
- if (win32 && GetCurrentTask())
- {
- LPSTR p;
- GetModuleFileName32A( GetCurrentTask(), buffer, buflen );
- if ((p = strrchr( buffer, '\\' )))
- {
- lstrcpyn32A( p + 1, tmp, (INT32)buflen - (p - buffer) );
- if (DOSFS_GetUnixFileName( buffer, TRUE ))
- {
- *p = '\0';
- goto found;
- }
- }
- }
+ if (win32 && DIR_TryModulePath( name, full_name )) goto done;
/* Try the current directory */
- if (DOSFS_GetUnixFileName( tmp, TRUE ))
- {
- GetCurrentDirectory32A( buflen, buffer );
- goto found;
- }
+ if (DOSFS_GetFullName( name, TRUE, full_name )) goto done;
/* Try the Windows directory */
- if (DOSFS_FindUnixName( DIR_WindowsUnixDir, name, NULL, 0,
- DRIVE_GetFlags( DIR_WindowsDosDir[0] - 'A' ) ))
- {
- lstrcpyn32A( buffer, DIR_WindowsDosDir, buflen );
- goto found;
- }
+ if (DIR_TryPath( DIR_WindowsUnixDir, DIR_WindowsDosDir, name, full_name ))
+ goto done;
/* Try the Windows system directory */
- if (DOSFS_FindUnixName( DIR_SystemUnixDir, name, NULL, 0,
- DRIVE_GetFlags( DIR_SystemDosDir[0] - 'A' ) ))
- {
- lstrcpyn32A( buffer, DIR_SystemDosDir, buflen );
- goto found;
- }
+ if (DIR_TryPath( DIR_SystemUnixDir, DIR_SystemDosDir, name, full_name ))
+ goto done;
/* Try the path of the current executable (for Win16 search order) */
- if (!win32 && GetCurrentTask())
- {
- LPSTR p;
- GetModuleFileName32A( GetCurrentTask(), buffer, buflen );
- if ((p = strrchr( buffer, '\\' )))
- {
- lstrcpyn32A( p + 1, tmp, (INT32)buflen - (p - buffer) );
- if (DOSFS_GetUnixFileName( buffer, TRUE ))
- {
- *p = '\0';
- goto found;
- }
- }
- }
+ if (!win32 && DIR_TryModulePath( name, full_name )) goto done;
+
/* Try all directories in path */
for (i = 0; i < DIR_PathElements; i++)
{
- if (DOSFS_FindUnixName( DIR_UnixPath[i], name, NULL, 0,
- DRIVE_GetFlags( DIR_DosPath[i][0] - 'A' ) ))
- {
- lstrcpyn32A( buffer, DIR_DosPath[i], buflen );
- goto found;
- }
+ if (DIR_TryPath( DIR_UnixPath[i], DIR_DosPath[i], name, full_name ))
+ goto done;
}
-not_found:
- if (tmp != name) HeapFree( GetProcessHeap(), 0, tmp );
- SetLastError( ERROR_FILE_NOT_FOUND );
- DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
- return 0;
-
-found:
- len = strlen(buffer);
- if (lastpart) *lastpart = buffer + len + 1;
- if (len + 1 < buflen)
- {
- buffer += len;
- *buffer++ = '\\';
- buflen -= len + 1;
- lstrcpyn32A( buffer, tmp, buflen );
- }
- len += strlen(tmp) + 1;
- if (tmp != name) HeapFree( GetProcessHeap(), 0, tmp );
- return len;
+ ret = FALSE;
+done:
+ if (tmp) HeapFree( GetProcessHeap(), 0, tmp );
+ return ret;
}
@@ -595,7 +586,17 @@
DWORD SearchPath32A( LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen,
LPSTR buffer, LPSTR *lastpart )
{
- return DIR_SearchPath( path, name, ext, buflen, buffer, lastpart, TRUE );
+ LPSTR p, res;
+ DOS_FULL_NAME full_name;
+
+ if (!DIR_SearchPath( path, name, ext, &full_name, TRUE )) return 0;
+ lstrcpyn32A( buffer, full_name.short_name, buflen );
+ res = full_name.long_name +
+ strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' ));
+ if (*res && (buflen > 3)) lstrcpyn32A( buffer + 3, res + 1, buflen - 3 );
+ for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
+ if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1;
+ return *res ? strlen(res) + 2 : 3;
}
@@ -605,25 +606,30 @@
DWORD SearchPath32W( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
LPWSTR buffer, LPWSTR *lastpart )
{
+ LPWSTR p;
+ LPSTR res;
+ DOS_FULL_NAME full_name;
+
LPSTR pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
LPSTR extA = HEAP_strdupWtoA( GetProcessHeap(), 0, ext );
- LPSTR lastpartA;
- LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, buflen + 1 );
-
- DWORD ret = DIR_SearchPath( pathA, nameA, extA, buflen, bufferA,
- &lastpartA, TRUE );
- lstrcpyAtoW( buffer, bufferA );
- if (lastpart)
- {
- if (lastpartA) *lastpart = buffer + (lastpartA - bufferA);
- else *lastpart = NULL;
- }
- HeapFree( GetProcessHeap(), 0, bufferA );
+ DWORD ret = DIR_SearchPath( pathA, nameA, extA, &full_name, TRUE );
HeapFree( GetProcessHeap(), 0, extA );
HeapFree( GetProcessHeap(), 0, nameA );
HeapFree( GetProcessHeap(), 0, pathA );
- return ret;
+ if (!ret) return 0;
+
+ lstrcpynAtoW( buffer, full_name.short_name, buflen );
+ res = full_name.long_name +
+ strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' ));
+ if (*res && (buflen > 3)) lstrcpynAtoW( buffer + 3, res + 1, buflen - 3 );
+ for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
+ if (lastpart)
+ {
+ for (p = *lastpart = buffer; *p; p++)
+ if (*p == '\\') *lastpart = p + 1;
+ }
+ return *res ? strlen(res) + 2 : 3;
}
diff --git a/files/dos_fs.c b/files/dos_fs.c
index fb3c0e7..9b081a0 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -22,7 +22,6 @@
#include "windows.h"
#include "winerror.h"
-#include "dos_fs.h"
#include "drive.h"
#include "file.h"
#include "heap.h"
@@ -31,13 +30,12 @@
#include "debug.h"
/* Define the VFAT ioctl to get both short and long file names */
-#if 0 /* not working yet */
+/* FIXME: is it possible to get this to work on other systems? */
#ifdef linux
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, long)
#else /* linux */
#undef VFAT_IOCTL_READDIR_BOTH /* just in case... */
#endif /* linux */
-#endif
/* Chars we don't want to see in DOS file names */
#define INVALID_DOS_CHARS "*?<>|\"+=,;[] \345"
@@ -58,6 +56,7 @@
{ "COM4", "" }
};
+
#define GET_DRIVE(path) \
(((path)[1] == ':') ? toupper((path)[0]) - 'A' : DOSFS_CurDrive)
@@ -134,47 +133,17 @@
/***********************************************************************
- * DOSFS_CheckDotDot
- *
- * Remove all '.' and '..' at the beginning of 'name'.
- */
-static const char * DOSFS_CheckDotDot( const char *name, char *buffer,
- char sep , int *len )
-{
- char *p = buffer + strlen(buffer);
-
- while (*name == '.')
- {
- if (IS_END_OF_NAME(name[1]))
- {
- name++;
- while ((*name == '\\') || (*name == '/')) name++;
- }
- else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
- {
- name += 2;
- while ((*name == '\\') || (*name == '/')) name++;
- while ((p > buffer) && (*p != sep)) { p--; (*len)++; }
- *p = '\0'; /* Remove trailing separator */
- }
- else break;
- }
- return name;
-}
-
-
-/***********************************************************************
* DOSFS_ToDosFCBFormat
*
* Convert a file name to DOS FCB format (8+3 chars, padded with blanks),
* expanding wild cards and converting to upper-case in the process.
* File name can be terminated by '\0', '\\' or '/'.
- * Return NULL if the name is not a valid DOS name.
+ * Return FALSE if the name is not a valid DOS name.
+ * 'buffer' must be at least 12 characters long.
*/
-const char *DOSFS_ToDosFCBFormat( const char *name )
+BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer )
{
static const char invalid_chars[] = INVALID_DOS_CHARS;
- static char buffer[12];
const char *p = name;
int i;
@@ -188,7 +157,7 @@
buffer[1] = '.';
p++;
}
- return (!*p || (*p == '/') || (*p == '\\')) ? buffer : NULL;
+ return (!*p || (*p == '/') || (*p == '\\'));
}
for (i = 0; i < 8; i++)
@@ -208,7 +177,7 @@
buffer[i] = '?';
break;
default:
- if (strchr( invalid_chars, *p )) return NULL;
+ if (strchr( invalid_chars, *p )) return FALSE;
buffer[i] = toupper(*p);
p++;
break;
@@ -223,7 +192,7 @@
else
{
/* Check if name too long */
- if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return NULL;
+ if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return FALSE;
}
if (*p == '.') p++; /* Skip dot */
@@ -237,7 +206,7 @@
buffer[i] = ' ';
break;
case '.':
- return NULL; /* Second extension not allowed */
+ return FALSE; /* Second extension not allowed */
case '?':
p++;
/* fall through */
@@ -245,14 +214,14 @@
buffer[i] = '?';
break;
default:
- if (strchr( invalid_chars, *p )) return NULL;
+ if (strchr( invalid_chars, *p )) return FALSE;
buffer[i] = toupper(*p);
p++;
break;
}
}
buffer[11] = '\0';
- return buffer;
+ return TRUE;
}
@@ -262,11 +231,10 @@
* Convert a file name from FCB to DTA format (name.ext, null-terminated)
* converting to upper-case in the process.
* File name can be terminated by '\0', '\\' or '/'.
- * Return NULL if the name is not a valid DOS name.
+ * 'buffer' must be at least 13 characters long.
*/
-const char *DOSFS_ToDosDTAFormat( const char *name )
+static void DOSFS_ToDosDTAFormat( LPCSTR name, LPSTR buffer )
{
- static char buffer[13];
char *p;
memcpy( buffer, name, 8 );
@@ -276,7 +244,6 @@
for (p += 3; p[-1] == ' '; p--);
if (p[-1] == '.') p--;
*p = '\0';
- return buffer;
}
@@ -397,13 +364,11 @@
#ifdef VFAT_IOCTL_READDIR_BOTH
if (dir->fd != -1)
{
- LPCSTR fcb_name;
if (ioctl( dir->fd, VFAT_IOCTL_READDIR_BOTH, (long)dir->dirent ) == -1)
return FALSE;
if (!dir->dirent[0].d_reclen) return FALSE;
- fcb_name = DOSFS_ToDosFCBFormat( dir->dirent[0].d_name );
- if (fcb_name) strcpy( dir->short_name, fcb_name );
- else dir->short_name[0] = '\0';
+ if (!DOSFS_ToDosFCBFormat( dir->dirent[0].d_name, dir->short_name ))
+ dir->short_name[0] = '\0';
*short_name = dir->short_name;
if (dir->dirent[1].d_name[0]) *long_name = dir->dirent[1].d_name;
else *long_name = dir->dirent[0].d_name;
@@ -419,80 +384,20 @@
/***********************************************************************
- * DOSFS_ToDosDateTime
- *
- * Convert a Unix time in the DOS date/time format.
- */
-void DOSFS_ToDosDateTime( time_t unixtime, WORD *pDate, WORD *pTime )
-{
- struct tm *tm = localtime( &unixtime );
- if (pTime)
- *pTime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
- if (pDate)
- *pDate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
- + tm->tm_mday;
-}
-
-/***********************************************************************
- * DOSFS_DosDateTimeToUnixTime
- *
- * Convert from the DOS (FAT) date/time format into Unix time
- * (borrowed from files/file.c)
- */
-time_t DOSFS_DosDateTimeToUnixTime( WORD date, WORD time )
-{
- struct tm newtm;
-
- 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;
- return mktime( &newtm );
-}
-
-
-/***********************************************************************
- * DOSFS_UnixTimeToFileTime
- *
- * Convert a Unix time to FILETIME format.
- */
-void DOSFS_UnixTimeToFileTime( time_t unixtime, FILETIME *filetime )
-{
- /* FIXME :-) */
- filetime->dwLowDateTime = unixtime;
- filetime->dwHighDateTime = 0;
-}
-
-
-/***********************************************************************
- * DOSFS_FileTimeToUnixTime
- *
- * Convert a FILETIME format to Unix time.
- */
-time_t DOSFS_FileTimeToUnixTime( const FILETIME *filetime )
-{
- /* FIXME :-) */
- return filetime->dwLowDateTime;
-}
-
-
-/***********************************************************************
* DOSFS_Hash
*
* Transform a Unix file name into a hashed DOS name. If the name is a valid
* DOS name, it is converted to upper-case; otherwise it is replaced by a
* hashed version that fits in 8.3 format.
* File name can be terminated by '\0', '\\' or '/'.
+ * 'buffer' must be at least 13 characters long.
*/
-static const char *DOSFS_Hash( const char *name, int dir_format,
- int ignore_case )
+static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL32 dir_format,
+ BOOL32 ignore_case )
{
static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
- static char buffer[13];
const char *p, *ext;
char *dst;
unsigned short hash;
@@ -508,7 +413,7 @@
buffer[0] = '.';
if (!dir_format) buffer[1] = buffer[2] = '\0';
if (name[1] == '.') buffer[1] = '.';
- return buffer;
+ return;
}
/* Simply copy the name, converting to uppercase */
@@ -523,55 +428,53 @@
*dst++ = toupper(*name);
}
if (!dir_format) *dst = '\0';
+ return;
+ }
+
+ /* Compute the hash code of the file name */
+ /* If you know something about hash functions, feel free to */
+ /* insert a better algorithm here... */
+ if (ignore_case)
+ {
+ for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+ hash = (hash<<3) ^ (hash>>5) ^ tolower(*p) ^ (tolower(p[1]) << 8);
+ hash = (hash<<3) ^ (hash>>5) ^ tolower(*p); /* Last character*/
}
else
{
- /* Compute the hash code of the file name */
- /* If you know something about hash functions, feel free to */
- /* insert a better algorithm here... */
- if (ignore_case)
- {
- for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
- hash = (hash << 3) ^ (hash >> 5) ^ tolower(*p) ^ (tolower(p[1]) << 8);
- hash = (hash << 3) ^ (hash >> 5) ^ tolower(*p); /* Last character*/
- }
- else
- {
- for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
- hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
- hash = (hash << 3) ^ (hash >> 5) ^ *p; /* Last character */
- }
-
- /* Find last dot for start of the extension */
- for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
- if (*p == '.') ext = p;
- if (ext && IS_END_OF_NAME(ext[1]))
- ext = NULL; /* Empty extension ignored */
-
- /* Copy first 4 chars, replacing invalid chars with '_' */
- for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
- {
- if (IS_END_OF_NAME(*p) || (p == ext)) break;
- *dst++ = strchr( invalid_chars, *p ) ? '_' : toupper(*p);
- }
- /* Pad to 5 chars with '~' */
- while (i-- >= 0) *dst++ = '~';
-
- /* Insert hash code converted to 3 ASCII chars */
- *dst++ = hash_chars[(hash >> 10) & 0x1f];
- *dst++ = hash_chars[(hash >> 5) & 0x1f];
- *dst++ = hash_chars[hash & 0x1f];
-
- /* Copy the first 3 chars of the extension (if any) */
- if (ext)
- {
- if (!dir_format) *dst++ = '.';
- for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
- *dst++ = strchr( invalid_chars, *ext ) ? '_' : toupper(*ext);
- }
- if (!dir_format) *dst = '\0';
+ for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+ hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
+ hash = (hash << 3) ^ (hash >> 5) ^ *p; /* Last character */
}
- return buffer;
+
+ /* Find last dot for start of the extension */
+ for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
+ if (*p == '.') ext = p;
+ if (ext && IS_END_OF_NAME(ext[1]))
+ ext = NULL; /* Empty extension ignored */
+
+ /* Copy first 4 chars, replacing invalid chars with '_' */
+ for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
+ {
+ if (IS_END_OF_NAME(*p) || (p == ext)) break;
+ *dst++ = strchr( invalid_chars, *p ) ? '_' : toupper(*p);
+ }
+ /* Pad to 5 chars with '~' */
+ while (i-- >= 0) *dst++ = '~';
+
+ /* Insert hash code converted to 3 ASCII chars */
+ *dst++ = hash_chars[(hash >> 10) & 0x1f];
+ *dst++ = hash_chars[(hash >> 5) & 0x1f];
+ *dst++ = hash_chars[hash & 0x1f];
+
+ /* Copy the first 3 chars of the extension (if any) */
+ if (ext)
+ {
+ if (!dir_format) *dst++ = '.';
+ for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
+ *dst++ = strchr( invalid_chars, *ext ) ? '_' : toupper(*ext);
+ }
+ if (!dir_format) *dst = '\0';
}
@@ -581,31 +484,34 @@
* Find the Unix file name in a given directory that corresponds to
* a file name (either in Unix or DOS format).
* File name can be terminated by '\0', '\\' or '/'.
- * Return 1 if OK, 0 if no file name matches.
+ * Return TRUE if OK, FALSE if no file name matches.
+ *
+ * 'long_buf' must be at least 'long_len' characters long. If the long name
+ * turns out to be larger than that, the function returns FALSE.
+ * 'short_buf' must be at least 13 characters long.
*/
-BOOL32 DOSFS_FindUnixName( const char *path, const char *name,
- char *buffer, int maxlen, UINT32 drive_flags )
+BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
+ INT32 long_len, LPSTR short_buf, BOOL32 ignore_case)
{
DOS_DIR *dir;
LPCSTR long_name, short_name;
- char dos_name[12];
+ char dos_name[12], tmp_buf[13];
BOOL32 ret;
const char *p = strchr( name, '/' );
int len = p ? (int)(p - name) : strlen(name);
+ if ((p = strchr( name, '\\' ))) len = MIN( (int)(p - name), len );
+ if (long_len < len + 1) return FALSE;
dprintf_dosfs( stddeb, "DOSFS_FindUnixName: %s,%s\n", path, name );
- if ((p = strchr( name, '\\' ))) len = MIN( (int)(p - name), len );
-
- dos_name[0] = '\0';
- if ((p = DOSFS_ToDosFCBFormat( name ))) strcpy( dos_name, p );
+ if (!DOSFS_ToDosFCBFormat( name, dos_name )) dos_name[0] = '\0';
if (!(dir = DOSFS_OpenDir( path )))
{
dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s): can't open dir\n",
path, name );
- return 0;
+ return FALSE;
}
while ((ret = DOSFS_ReadDir( dir, &long_name, &short_name )))
@@ -613,7 +519,7 @@
/* Check against Unix name */
if (len == strlen(long_name))
{
- if (drive_flags & DRIVE_CASE_SENSITIVE)
+ if (!ignore_case)
{
if (!lstrncmp32A( long_name, name, len )) break;
}
@@ -626,14 +532,29 @@
{
/* Check against hashed DOS name */
if (!short_name)
- short_name = DOSFS_Hash( long_name, TRUE,
- !(drive_flags & DRIVE_CASE_SENSITIVE) );
+ {
+ DOSFS_Hash( long_name, tmp_buf, TRUE, ignore_case );
+ short_name = tmp_buf;
+ }
if (!strcmp( dos_name, short_name )) break;
}
}
- if (ret && buffer) lstrcpyn32A( buffer, long_name, maxlen );
- dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s) -> %s\n",
- path, name, ret ? long_name : "** Not found **" );
+ if (ret)
+ {
+ if (long_buf) strcpy( long_buf, long_name );
+ if (short_buf)
+ {
+ if (short_name)
+ DOSFS_ToDosDTAFormat( short_name, short_buf );
+ else
+ DOSFS_Hash( long_name, short_buf, FALSE, ignore_case );
+ }
+ dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s) -> %s (%s)\n",
+ path, name, long_name, short_buf ? short_buf : "***");
+ }
+ else
+ dprintf_dosfs(stddeb,"DOSFS_FindUnixName(%s,%s) -> ** Not found **\n",
+ path, name );
DOSFS_CloseDir( dir );
return ret;
}
@@ -702,168 +623,278 @@
/***********************************************************************
- * DOSFS_GetUnixFileName
+ * DOSFS_GetFullName
*
- * Convert a file name (DOS or mixed DOS/Unix format) to a valid Unix name.
- * Return NULL if one of the path components does not exist. The last path
+ * Convert a file name (DOS or mixed DOS/Unix format) to a valid
+ * Unix name / short DOS name pair.
+ * Return FALSE if one of the path components does not exist. The last path
* component is only checked if 'check_last' is non-zero.
+ * The buffers pointed to by 'long_buf' and 'short_buf' must be
+ * at least MAX_PATHNAME_LEN long.
*/
-const char * DOSFS_GetUnixFileName( const char * name, int check_last )
+BOOL32 DOSFS_GetFullName( LPCSTR name, BOOL32 check_last, DOS_FULL_NAME *full )
{
- static char buffer[MAX_PATHNAME_LEN];
- int drive, len;
BOOL32 found;
UINT32 flags;
- char *p, *root;
+ char *p_l, *p_s, *root;
- dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: %s\n", name );
+ dprintf_dosfs( stddeb, "DOSFS_GetFullName: %s (last=%d)\n",
+ name, check_last );
- if ((drive = DOSFS_GetPathDrive( &name )) == -1) return NULL;
- flags = DRIVE_GetFlags(drive);
- lstrcpyn32A( buffer, DRIVE_GetRoot(drive), MAX_PATHNAME_LEN );
- if (buffer[1]) root = buffer + strlen(buffer);
- else root = buffer; /* root directory */
+ if ((full->drive = DOSFS_GetPathDrive( &name )) == -1) return FALSE;
+ flags = DRIVE_GetFlags( full->drive );
- if ((*name == '\\') || (*name == '/'))
+ lstrcpyn32A( full->long_name, DRIVE_GetRoot( full->drive ),
+ sizeof(full->long_name) );
+ if (full->long_name[1]) root = full->long_name + strlen(full->long_name);
+ else root = full->long_name; /* root directory */
+
+ strcpy( full->short_name, "A:\\" );
+ full->short_name[0] += full->drive;
+
+ if ((*name == '\\') || (*name == '/')) /* Absolute path */
{
while ((*name == '\\') || (*name == '/')) name++;
}
- else
+ else /* Relative path */
{
- lstrcpyn32A( root + 1, DRIVE_GetUnixCwd(drive),
- MAX_PATHNAME_LEN - (int)(root - buffer) - 1 );
+ lstrcpyn32A( root + 1, DRIVE_GetUnixCwd( full->drive ),
+ sizeof(full->long_name) - (root - full->long_name) - 1 );
if (root[1]) *root = '/';
+ lstrcpyn32A( full->short_name + 3, DRIVE_GetDosCwd( full->drive ),
+ sizeof(full->short_name) - 3 );
}
- p = buffer[1] ? buffer + strlen(buffer) : buffer;
- len = MAX_PATHNAME_LEN - strlen(buffer);
+ p_l = full->long_name[1] ? full->long_name + strlen(full->long_name)
+ : full->long_name;
+ p_s = full->short_name[3] ? full->short_name + strlen(full->short_name)
+ : full->short_name + 2;
found = TRUE;
+
while (*name && found)
{
- const char *newname = DOSFS_CheckDotDot( name, root, '/', &len );
- if (newname != name)
+ /* Check for '.' and '..' */
+
+ if (*name == '.')
{
- p = root + strlen(root);
- name = newname;
- continue;
+ if (IS_END_OF_NAME(name[1]))
+ {
+ name++;
+ while ((*name == '\\') || (*name == '/')) name++;
+ continue;
+ }
+ else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
+ {
+ name += 2;
+ while ((*name == '\\') || (*name == '/')) name++;
+ while ((p_l > root) && (*p_l != '/')) p_l--;
+ while ((p_s > full->short_name + 2) && (*p_s != '\\')) p_s--;
+ *p_l = *p_s = '\0'; /* Remove trailing separator */
+ continue;
+ }
}
- if (len <= 1)
+
+ /* Make sure buffers are large enough */
+
+ if ((p_s >= full->short_name + sizeof(full->short_name) - 14) ||
+ (p_l >= full->long_name + sizeof(full->long_name) - 1))
{
DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
- return NULL;
+ return FALSE;
}
- if ((found = DOSFS_FindUnixName( buffer, name, p+1, len-1, flags )))
+
+ /* Get the long and short name matching the file name */
+
+ if ((found = DOSFS_FindUnixName( full->long_name, name, p_l + 1,
+ sizeof(full->long_name) - (p_l - full->long_name) - 1,
+ p_s + 1, !(flags & DRIVE_CASE_SENSITIVE) )))
{
- *p = '/';
- len -= strlen(p);
- p += strlen(p);
+ *p_l++ = '/';
+ p_l += strlen(p_l);
+ *p_s++ = '\\';
+ p_s += strlen(p_s);
while (!IS_END_OF_NAME(*name)) name++;
}
else if (!check_last)
{
- *p++ = '/';
- for (len--; !IS_END_OF_NAME(*name) && (len > 1); name++, len--)
- *p++ = tolower(*name);
- *p = '\0';
+ *p_l++ = '/';
+ *p_s++ = '\\';
+ while (!IS_END_OF_NAME(*name) &&
+ (p_s < full->short_name + sizeof(full->short_name) - 1) &&
+ (p_l < full->long_name + sizeof(full->long_name) - 1))
+ {
+ *p_l++ = *p_s++ = tolower(*name);
+ name++;
+ }
+ *p_l = *p_s = '\0';
}
while ((*name == '\\') || (*name == '/')) name++;
}
+
if (!found)
{
if (check_last)
{
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
- return NULL;
+ return FALSE;
}
if (*name) /* Not last */
{
DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
- return NULL;
+ return FALSE;
}
}
- if (!buffer[0]) strcpy( buffer, "/" );
- dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: returning %s\n", buffer );
- return buffer;
+ if (!full->long_name[0]) strcpy( full->long_name, "/" );
+ if (!full->short_name[2]) strcpy( full->short_name + 2, "\\" );
+ dprintf_dosfs( stddeb, "DOSFS_GetFullName: returning %s = %s\n",
+ full->long_name, full->short_name );
+ return TRUE;
}
/***********************************************************************
- * DOSFS_GetDosTrueName
- *
- * Convert a file name (DOS or Unix format) to a complete DOS name.
- * Return NULL if the path name is invalid or too long.
- * The unix_format flag is a hint that the file name is in Unix format.
+ * GetShortPathName32A (KERNEL32.271)
*/
-const char * DOSFS_GetDosTrueName( const char *name, int unix_format )
+DWORD GetShortPathName32A( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
{
- static char buffer[MAX_PATHNAME_LEN];
- int drive, len;
- UINT32 flags;
+ DOS_FULL_NAME full_name;
+
+ /* FIXME: is it correct to always return a fully qualified short path? */
+ if (!DOSFS_GetFullName( longpath, TRUE, &full_name )) return 0;
+ lstrcpyn32A( shortpath, full_name.short_name, shortlen );
+ return strlen( full_name.short_name );
+}
+
+
+/***********************************************************************
+ * GetShortPathName32W (KERNEL32.272)
+ */
+DWORD GetShortPathName32W( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
+{
+ DOS_FULL_NAME full_name;
+ DWORD ret = 0;
+ LPSTR longpathA = HEAP_strdupWtoA( GetProcessHeap(), 0, longpath );
+
+ /* FIXME: is it correct to always return a fully qualified short path? */
+ if (DOSFS_GetFullName( longpathA, TRUE, &full_name ))
+ {
+ ret = strlen( full_name.short_name );
+ lstrcpynAtoW( shortpath, full_name.short_name, shortlen );
+ }
+ HeapFree( GetProcessHeap(), 0, longpathA );
+ return ret;
+}
+
+
+/***********************************************************************
+ * DOSFS_DoGetFullPathName
+ *
+ * Implementation of GetFullPathName32A/W.
+ */
+static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
+ BOOL32 unicode )
+{
+ char buffer[MAX_PATHNAME_LEN];
+ int drive;
char *p;
- dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName(%s,%d)\n", name, unix_format);
+ dprintf_dosfs( stddeb, "GetFullPathName: converting %s\n", name );
- if ((drive = DOSFS_GetPathDrive( &name )) == -1) return NULL;
+ if ((drive = DOSFS_GetPathDrive( &name )) == -1) return 0;
p = buffer;
*p++ = 'A' + drive;
*p++ = ':';
- if (IS_END_OF_NAME(*name))
+ if (IS_END_OF_NAME(*name)) /* Absolute path */
{
while ((*name == '\\') || (*name == '/')) name++;
}
- else
+ else /* Relative path */
{
*p++ = '\\';
lstrcpyn32A( p, DRIVE_GetDosCwd(drive), sizeof(buffer) - 3 );
if (*p) p += strlen(p); else p--;
}
*p = '\0';
- len = MAX_PATHNAME_LEN - (int)(p - buffer);
- flags = DRIVE_GetFlags(drive);
while (*name)
{
- const char *newname = DOSFS_CheckDotDot( name, buffer+2, '\\', &len );
- if (newname != name)
+ if (*name == '.')
{
- p = buffer + strlen(buffer);
- name = newname;
- continue;
+ if (IS_END_OF_NAME(name[1]))
+ {
+ name++;
+ while ((*name == '\\') || (*name == '/')) name++;
+ continue;
+ }
+ else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
+ {
+ name += 2;
+ while ((*name == '\\') || (*name == '/')) name++;
+ while ((p > buffer + 2) && (*p != '\\')) p--;
+ *p = '\0'; /* Remove trailing separator */
+ continue;
+ }
}
- if (len <= 1)
+ if (p >= buffer + sizeof(buffer) - 1)
{
DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
- return NULL;
+ return 0;
}
*p++ = '\\';
- if (unix_format) /* Hash it into a DOS name */
- {
- lstrcpyn32A( p, DOSFS_Hash( name, FALSE,
- !(flags & DRIVE_CASE_SENSITIVE) ),
- len );
- len -= strlen(p);
- p += strlen(p);
- while (!IS_END_OF_NAME(*name)) name++;
- }
- else /* Already DOS format, simply upper-case it */
- {
- while (!IS_END_OF_NAME(*name) && (len > 1))
- {
- *p++ = toupper(*name);
- name++;
- len--;
- }
- *p = '\0';
- }
+ while (!IS_END_OF_NAME(*name) && (p < buffer + sizeof(buffer) - 1))
+ *p++ = *name++;
+ *p = '\0';
while ((*name == '\\') || (*name == '/')) name++;
}
+
if (!buffer[2])
{
buffer[2] = '\\';
buffer[3] = '\0';
}
- dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName: returning %s\n", buffer );
- return buffer;
+ if (!(DRIVE_GetFlags(drive) & DRIVE_CASE_PRESERVING))
+ CharUpper32A( buffer );
+
+ if (unicode) lstrcpynAtoW( (LPWSTR)result, buffer, len );
+ else lstrcpyn32A( result, buffer, len );
+
+ dprintf_dosfs( stddeb, "GetFullPathName: returning %s\n", buffer );
+ return strlen(buffer);
+}
+
+
+/***********************************************************************
+ * GetFullPathName32A (KERNEL32.272)
+ */
+DWORD GetFullPathName32A(LPCSTR name, DWORD len, LPSTR buffer, LPSTR *lastpart)
+{
+ DWORD ret = DOSFS_DoGetFullPathName( name, len, buffer, FALSE );
+ if (ret && lastpart)
+ {
+ LPSTR p = buffer + strlen(buffer);
+ while ((p > buffer + 2) && (*p != '\\')) p--;
+ *lastpart = p + 1;
+ }
+ return ret;
+}
+
+
+/***********************************************************************
+ * GetFullPathName32W (KERNEL32.273)
+ */
+DWORD GetFullPathName32W( LPCWSTR name, DWORD len, LPWSTR buffer,
+ LPWSTR *lastpart )
+{
+ LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+ DWORD ret = DOSFS_DoGetFullPathName( nameA, len, (LPSTR)buffer, TRUE );
+ HeapFree( GetProcessHeap(), 0, nameA );
+ if (ret && lastpart)
+ {
+ LPWSTR p = buffer + lstrlen32W(buffer);
+ while ((p > buffer + 2) && (*p != '\\')) p--;
+ *lastpart = p + 1;
+ }
+ return ret;
}
@@ -885,6 +916,7 @@
static int cur_pos = 0;
static int drive_root = 0;
char *p;
+ char dos_name[13];
LPCSTR long_name, short_name;
UINT32 flags;
BY_HANDLE_FILE_INFORMATION info;
@@ -893,15 +925,14 @@
{
if (skip) return 0;
entry->dwFileAttributes = FILE_ATTRIBUTE_LABEL;
- DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftCreationTime );
- DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastAccessTime );
- DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastWriteTime );
+ DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftCreationTime, 0 );
+ DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastAccessTime, 0 );
+ DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastWriteTime, 0 );
entry->nFileSizeHigh = 0;
entry->nFileSizeLow = 0;
entry->dwReserved0 = 0;
entry->dwReserved1 = 0;
- strcpy( entry->cFileName,
- DOSFS_ToDosDTAFormat( DRIVE_GetLabel( drive )) );
+ DOSFS_ToDosDTAFormat( DRIVE_GetLabel( drive ), entry->cFileName );
strcpy( entry->cAlternateFileName, entry->cFileName );
return 1;
}
@@ -956,8 +987,11 @@
if (short_mask)
{
if (!short_name)
- short_name = DOSFS_Hash( long_name, TRUE,
- !(flags & DRIVE_CASE_SENSITIVE) );
+ {
+ DOSFS_Hash( long_name, dos_name, TRUE,
+ !(flags & DRIVE_CASE_SENSITIVE) );
+ short_name = dos_name;
+ }
if (!DOSFS_MatchShort( short_mask, short_name )) continue;
}
@@ -973,19 +1007,21 @@
/* We now have a matching entry; fill the result and return */
- if (!short_name)
- short_name = DOSFS_Hash( long_name, TRUE,
- !(flags & DRIVE_CASE_SENSITIVE) );
-
entry->dwFileAttributes = info.dwFileAttributes;
entry->ftCreationTime = info.ftCreationTime;
entry->ftLastAccessTime = info.ftLastAccessTime;
entry->ftLastWriteTime = info.ftLastWriteTime;
entry->nFileSizeHigh = info.nFileSizeHigh;
entry->nFileSizeLow = info.nFileSizeLow;
- strcpy( entry->cAlternateFileName, DOSFS_ToDosDTAFormat(short_name) );
+
+ if (short_name)
+ DOSFS_ToDosDTAFormat( short_name, entry->cAlternateFileName );
+ else
+ DOSFS_Hash( long_name, entry->cAlternateFileName, FALSE,
+ !(flags & DRIVE_CASE_SENSITIVE) );
+
lstrcpyn32A( entry->cFileName, long_name, sizeof(entry->cFileName) );
- if (!(flags & DRIVE_CASE_PRESERVING)) AnsiLower( entry->cFileName );
+ if (!(flags & DRIVE_CASE_PRESERVING)) CharLower32A( entry->cFileName );
dprintf_dosfs( stddeb, "DOSFS_FindNext: returning %s (%s) %02lx %ld\n",
entry->cFileName, entry->cAlternateFileName,
entry->dwFileAttributes, entry->nFileSizeLow );
@@ -1004,17 +1040,17 @@
*/
HANDLE16 FindFirstFile16( LPCSTR path, WIN32_FIND_DATA32A *data )
{
+ DOS_FULL_NAME full_name;
HGLOBAL16 handle;
FIND_FIRST_INFO *info;
- LPCSTR ptr;
if (!path) return 0;
- if (!(ptr = DOSFS_GetUnixFileName( path, FALSE )))
+ if (!DOSFS_GetFullName( path, FALSE, &full_name ))
return INVALID_HANDLE_VALUE16;
if (!(handle = GlobalAlloc16( GMEM_MOVEABLE, sizeof(FIND_FIRST_INFO) )))
return INVALID_HANDLE_VALUE16;
info = (FIND_FIRST_INFO *)GlobalLock16( handle );
- info->path = HEAP_strdupA( SystemHeap, 0, ptr );
+ info->path = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
info->mask = strrchr( info->path, '/' );
*(info->mask++) = '\0';
if (path[0] && (path[1] == ':')) info->drive = toupper(*path) - 'A';
@@ -1156,72 +1192,34 @@
/***********************************************************************
- * GetShortPathName32A (KERNEL32.271)
+ * DOSFS_UnixTimeToFileTime
+ *
+ * Convert a Unix time to FILETIME format.
+ * The FILETIME structure is a 64-bit value representing the number of
+ * 100-nanosecond intervals since January 1, 1601.
+ * 'remainder' is the fraction of 100-ns intervals smaller than 1 second
+ * that couldn't be stored in the time_t value.
*/
-DWORD GetShortPathName32A( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
+void DOSFS_UnixTimeToFileTime( time_t unix_time, FILETIME *filetime,
+ DWORD remainder )
{
- LPCSTR dostruename;
-
- dprintf_dosfs( stddeb, "GetShortPathName32A(%s,%p,%ld)\n",
- longpath, shortpath, shortlen );
-
- dostruename = DOSFS_GetDosTrueName( longpath, TRUE );
- lstrcpyn32A( shortpath, dostruename, shortlen );
- return strlen(dostruename);
+ /* FIXME :-) */
+ filetime->dwLowDateTime = unix_time;
+ filetime->dwHighDateTime = 0;
}
/***********************************************************************
- * GetShortPathNameW (KERNEL32.272)
+ * DOSFS_FileTimeToUnixTime
+ *
+ * Convert a FILETIME format to Unix time.
+ * If not NULL, 'remainder' contains the fractional part of the filetime.
*/
-DWORD GetShortPathName32W( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
+time_t DOSFS_FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder )
{
- LPSTR longpatha = HEAP_strdupWtoA( GetProcessHeap(), 0, longpath );
- LPCSTR dostruename = DOSFS_GetDosTrueName( longpatha, TRUE );
- HeapFree( GetProcessHeap(), 0, longpatha );
- lstrcpynAtoW( shortpath, dostruename, shortlen );
- return strlen(dostruename);
-}
-
-
-/***********************************************************************
- * GetFullPathNameA (KERNEL32.272)
- */
-DWORD GetFullPathName32A( LPCSTR fn, DWORD buflen, LPSTR buf, LPSTR *lastpart)
-{
- dprintf_file(stddeb,"GetFullPathNameA(%s)\n",fn);
- /* FIXME */
- if (buf) {
- lstrcpyn32A(buf,fn,buflen);
- if (lastpart) {
- *lastpart = strrchr(buf,'\\');
- if (!*lastpart) *lastpart=buf;
- }
- }
- return strlen(fn);
-}
-
-/***********************************************************************
- * GetFullPathName32W (KERNEL32.273)
- */
-DWORD GetFullPathName32W(LPCWSTR fn,DWORD buflen,LPWSTR buf,LPWSTR *lastpart) {
- LPWSTR x;
-
- dprintf_file(stddeb,"GetFullPathNameW(%p)\n",fn);
- /* FIXME */
- if (buf) {
- lstrcpyn32W(buf,fn,buflen);
- if (lastpart) {
- x = buf+lstrlen32W(buf)-1;
- while (x>=buf && *x!='\\')
- x--;
- if (x>=buf)
- *lastpart=x;
- else
- *lastpart=buf;
- }
- }
- return lstrlen32W(fn);
+ /* FIXME :-) */
+ if (remainder) *remainder = 0;
+ return filetime->dwLowDateTime;
}
@@ -1230,8 +1228,15 @@
*/
BOOL32 DosDateTimeToFileTime( WORD fatdate, WORD fattime, LPFILETIME ft )
{
- time_t unixtime = DOSFS_DosDateTimeToUnixTime(fatdate,fattime);
- DOSFS_UnixTimeToFileTime(unixtime,ft);
+ struct tm newtm;
+
+ newtm.tm_sec = (fattime & 0x1f) * 2;
+ newtm.tm_min = (fattime >> 5) & 0x3f;
+ newtm.tm_hour = (fattime >> 11);
+ newtm.tm_mday = (fatdate & 0x1f);
+ newtm.tm_mon = ((fatdate >> 5) & 0x0f) - 1;
+ newtm.tm_year = (fatdate >> 9) + 80;
+ DOSFS_UnixTimeToFileTime( mktime( &newtm ), ft, 0 );
return TRUE;
}
@@ -1242,8 +1247,13 @@
BOOL32 FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
LPWORD fattime )
{
- time_t unixtime = DOSFS_FileTimeToUnixTime(ft);
- DOSFS_ToDosDateTime(unixtime,fatdate,fattime);
+ time_t unixtime = DOSFS_FileTimeToUnixTime( ft, NULL );
+ struct tm *tm = localtime( &unixtime );
+ if (fattime)
+ *fattime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
+ if (fatdate)
+ *fatdate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
+ + tm->tm_mday;
return TRUE;
}
@@ -1254,11 +1264,12 @@
BOOL32 LocalFileTimeToFileTime( const FILETIME *localft, LPFILETIME utcft )
{
struct tm *xtm;
+ DWORD remainder;
/* convert from local to UTC. Perhaps not correct. FIXME */
- xtm = gmtime((time_t*)&(localft->dwLowDateTime));
- utcft->dwLowDateTime = mktime(xtm);
- utcft->dwHighDateTime = 0;
+ time_t unixtime = DOSFS_FileTimeToUnixTime( localft, &remainder );
+ xtm = gmtime( &unixtime );
+ DOSFS_UnixTimeToFileTime( mktime(xtm), utcft, remainder );
return TRUE;
}
@@ -1269,11 +1280,12 @@
BOOL32 FileTimeToLocalFileTime( const FILETIME *utcft, LPFILETIME localft )
{
struct tm *xtm;
+ DWORD remainder;
/* convert from UTC to local. Perhaps not correct. FIXME */
- xtm = localtime((time_t*)&(utcft->dwLowDateTime));
- localft->dwLowDateTime = mktime(xtm);
- localft->dwHighDateTime = 0;
+ time_t unixtime = DOSFS_FileTimeToUnixTime( utcft, &remainder );
+ xtm = localtime( &unixtime );
+ DOSFS_UnixTimeToFileTime( mktime(xtm), localft, remainder );
return TRUE;
}
@@ -1284,19 +1296,68 @@
BOOL32 FileTimeToSystemTime( const FILETIME *ft, LPSYSTEMTIME syst )
{
struct tm *xtm;
- time_t xtime = DOSFS_FileTimeToUnixTime(ft);
+ DWORD remainder;
+ time_t xtime = DOSFS_FileTimeToUnixTime( ft, &remainder );
xtm = gmtime(&xtime);
- syst->wYear = xtm->tm_year;
- syst->wMonth = xtm->tm_mon;
- syst->wDayOfWeek = xtm->tm_wday;
- syst->wDay = xtm->tm_mday;
- syst->wHour = xtm->tm_hour;
- syst->wMinute = xtm->tm_min;
- syst->wSecond = xtm->tm_sec;
- syst->wMilliseconds = 0; /* FIXME */
+ syst->wYear = xtm->tm_year;
+ syst->wMonth = xtm->tm_mon;
+ syst->wDayOfWeek = xtm->tm_wday;
+ syst->wDay = xtm->tm_mday;
+ syst->wHour = xtm->tm_hour;
+ syst->wMinute = xtm->tm_min;
+ syst->wSecond = xtm->tm_sec;
+ syst->wMilliseconds = remainder / 10000;
return TRUE;
}
+/***********************************************************************
+ * QueryDosDeviceA (KERNEL32.413)
+ *
+ * returns array of strings terminated by \0, terminated by \0
+ */
+DWORD
+QueryDosDevice32A(LPCSTR devname,LPSTR target,DWORD bufsize)
+{
+ LPSTR s;
+ char buffer[200];
+
+ dprintf_dosfs(stddeb,"QueryDosDevice(%s,...)\n",devname?devname:"<null>");
+ if (!devname) {
+ /* return known MSDOS devices */
+ lstrcpy32A(buffer,"CON COM1 COM2 LPT1 NUL ");
+ while ((s=strchr(buffer,' ')))
+ *s='\0';
+
+ lstrcpyn32A(target,buffer,bufsize);
+ return strlen(buffer);
+ }
+ lstrcpy32A(buffer,"\\DEV\\");
+ lstrcat32A(buffer,devname);
+ if (s=strchr(buffer,':'))
+ *s='\0';
+ lstrcpyn32A(target,buffer,bufsize);
+ return strlen(buffer);
+}
+
+
+/***********************************************************************
+ * QueryDosDeviceW (KERNEL32.414)
+ *
+ * returns array of strings terminated by \0, terminated by \0
+ */
+DWORD
+QueryDosDevice32W(LPCWSTR devname,LPWSTR target,DWORD bufsize)
+{
+ LPSTR devnameA = devname?HEAP_strdupWtoA(GetProcessHeap(),0,devname):NULL;
+ LPSTR targetA = (LPSTR)HEAP_xalloc(GetProcessHeap(),0,bufsize);
+ DWORD ret = QueryDosDevice32A(devnameA,targetA,bufsize);
+
+ lstrcpynAtoW(target,targetA,bufsize);
+ if (devnameA) HeapFree(GetProcessHeap(),0,devnameA);
+ if (targetA) HeapFree(GetProcessHeap(),0,targetA);
+ return ret;
+}
+
/***********************************************************************
* SystemTimeToFileTime (KERNEL32.526)
@@ -1312,6 +1373,6 @@
xtm.tm_hour = syst->wHour;
xtm.tm_min = syst->wMinute;
xtm.tm_sec = syst->wSecond;
- DOSFS_UnixTimeToFileTime(mktime(&xtm),ft);
+ DOSFS_UnixTimeToFileTime( mktime(&xtm), ft, syst->wMilliseconds * 10000 );
return TRUE;
}
diff --git a/files/drive.c b/files/drive.c
index b876675..d59e02b 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -25,7 +25,6 @@
#include "windows.h"
#include "winbase.h"
-#include "dos_fs.h"
#include "drive.h"
#include "file.h"
#include "heap.h"
@@ -410,8 +409,9 @@
*/
int DRIVE_Chdir( int drive, const char *path )
{
+ DOS_FULL_NAME full_name;
char buffer[MAX_PATHNAME_LEN];
- const char *unix_cwd, *dos_cwd;
+ LPSTR unix_cwd;
BY_HANDLE_FILE_INFORMATION info;
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
@@ -420,31 +420,30 @@
buffer[0] += drive;
lstrcpyn32A( buffer + 2, path, sizeof(buffer) - 2 );
- if (!(unix_cwd = DOSFS_GetUnixFileName( buffer, TRUE ))) return 0;
- if (!FILE_Stat( unix_cwd, &info )) return 0;
+ if (!DOSFS_GetFullName( buffer, TRUE, &full_name )) return 0;
+ if (!FILE_Stat( full_name.long_name, &info )) return 0;
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
return 0;
}
- unix_cwd += strlen( DOSDrives[drive].root );
+ unix_cwd = full_name.long_name + strlen( DOSDrives[drive].root );
while (*unix_cwd == '/') unix_cwd++;
- buffer[2] = '/';
- lstrcpyn32A( buffer + 3, unix_cwd, sizeof(buffer) - 3 );
- if (!(dos_cwd = DOSFS_GetDosTrueName( buffer, TRUE ))) return 0;
dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:): unix_cwd=%s dos_cwd=%s\n",
- 'A' + drive, unix_cwd, dos_cwd + 3 );
+ 'A' + drive, unix_cwd, full_name.short_name + 3 );
HeapFree( SystemHeap, 0, DOSDrives[drive].dos_cwd );
HeapFree( SystemHeap, 0, DOSDrives[drive].unix_cwd );
- DOSDrives[drive].dos_cwd = HEAP_strdupA( SystemHeap, 0, dos_cwd + 3 );
+ DOSDrives[drive].dos_cwd = HEAP_strdupA( SystemHeap, 0,
+ full_name.short_name + 3 );
DOSDrives[drive].unix_cwd = HEAP_strdupA( SystemHeap, 0, unix_cwd );
if (pTask && (pTask->curdrive & 0x80) &&
((pTask->curdrive & ~0x80) == drive))
{
- lstrcpyn32A( pTask->curdir, dos_cwd + 2, sizeof(pTask->curdir) );
+ lstrcpyn32A( pTask->curdir, full_name.short_name + 2,
+ sizeof(pTask->curdir) );
DRIVE_LastTask = GetCurrentTask();
}
return 1;
diff --git a/files/file.c b/files/file.c
index f841b81..048e58d 100644
--- a/files/file.c
+++ b/files/file.c
@@ -20,7 +20,6 @@
#include "windows.h"
#include "winerror.h"
-#include "dos_fs.h"
#include "drive.h"
#include "file.h"
#include "global.h"
@@ -212,11 +211,8 @@
if ((file->unix_handle = open( name, mode, 0666 )) == -1)
{
- if (Options.allowReadOnly && (mode == O_RDWR))
- {
- if ((file->unix_handle = open( name, O_RDONLY )) != -1)
- fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", name );
- }
+ if (!Options.failReadOnly && (mode == O_RDWR))
+ file->unix_handle = open( name, O_RDONLY );
}
if ((file->unix_handle == -1) || (fstat( file->unix_handle, &st ) == -1))
{
@@ -243,6 +239,7 @@
*/
HFILE32 FILE_Open( LPCSTR path, INT32 mode )
{
+ DOS_FULL_NAME full_name;
const char *unixName;
dprintf_file(stddeb, "FILE_Open: '%s' %04x\n", path, mode );
@@ -257,9 +254,11 @@
}
}
else /* check for filename, don't check for last entry if creating */
- if (!(unixName = DOSFS_GetUnixFileName( path, !(mode & O_CREAT) )))
+ {
+ if (!DOSFS_GetFullName( path, !(mode & O_CREAT), &full_name ))
return HFILE_ERROR32;
-
+ unixName = full_name.long_name;
+ }
return FILE_OpenUnixFile( unixName, mode );
}
@@ -272,6 +271,7 @@
HFILE32 handle;
DOS_FILE *file;
const char *unixName;
+ DOS_FULL_NAME full_name;
dprintf_file(stddeb, "FILE_Create: '%s' %04x %d\n", path, mode, unique );
@@ -285,12 +285,12 @@
if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
return INVALID_HANDLE_VALUE32;
- if (!(unixName = DOSFS_GetUnixFileName( path, FALSE )))
+ if (!DOSFS_GetFullName( path, FALSE, &full_name ))
{
CloseHandle( handle );
return INVALID_HANDLE_VALUE32;
}
- if ((file->unix_handle = open( unixName,
+ if ((file->unix_handle = open( full_name.long_name,
O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
mode )) == -1)
{
@@ -301,7 +301,7 @@
/* File created OK, now fill the DOS_FILE */
- file->unix_name = HEAP_strdupA( SystemHeap, 0, unixName );
+ file->unix_name = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
return handle;
}
@@ -317,9 +317,9 @@
if (S_ISDIR(st->st_mode))
info->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
- DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftCreationTime );
- DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftLastWriteTime );
- DOSFS_UnixTimeToFileTime( st->st_atime, &info->ftLastAccessTime );
+ DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftCreationTime, 0 );
+ DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftLastWriteTime, 0 );
+ DOSFS_UnixTimeToFileTime( st->st_atime, &info->ftLastAccessTime, 0 );
info->dwVolumeSerialNumber = 0; /* FIXME */
info->nFileSizeHigh = 0;
@@ -385,9 +385,11 @@
*/
DWORD GetFileAttributes32A( LPCSTR name )
{
+ DOS_FULL_NAME full_name;
BY_HANDLE_FILE_INFORMATION info;
- if (!FILE_Stat( name, &info )) return -1;
+ if (!DOSFS_GetFullName( name, TRUE, &full_name )) return -1;
+ if (!FILE_Stat( full_name.long_name, &info )) return -1;
return info.dwFileAttributes;
}
@@ -500,8 +502,9 @@
UINT32 GetTempFileName32A( LPCSTR path, LPCSTR prefix, UINT32 unique,
LPSTR buffer)
{
- LPSTR p;
+ DOS_FULL_NAME full_name;
int i;
+ LPSTR p;
UINT32 num = unique ? (unique & 0xffff) : time(NULL) & 0xffff;
if (!path) return 0;
@@ -511,36 +514,38 @@
for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
sprintf( p, "%04x.tmp", num );
- if (unique)
- {
- lstrcpyn32A( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
- dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
- if (-1==access(DOSFS_GetUnixFileName(buffer,TRUE),W_OK))
- fprintf(stderr,"Warning: GetTempFileName returns '%s', which doesn't seem to be writeable. Please check your configuration file if this generates a failure.\n",buffer);
- return unique;
- }
-
/* Now try to create it */
- do
+ if (!unique)
{
- HFILE32 handle;
- if ((handle = FILE_Create(buffer,0666,TRUE)) != INVALID_HANDLE_VALUE32)
- { /* We created it */
- dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer );
- CloseHandle( handle );
- break;
- }
- if (DOS_ExtendedError != ER_FileExists) break; /* No need to go on */
- num++;
- sprintf( p, "%04x.tmp", num );
- } while (num != (unique & 0xffff));
+ do
+ {
+ HFILE32 handle = FILE_Create( buffer, 0666, TRUE );
+ if (handle != INVALID_HANDLE_VALUE32)
+ { /* We created it */
+ dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer);
+ CloseHandle( handle );
+ break;
+ }
+ if (DOS_ExtendedError != ER_FileExists)
+ break; /* No need to go on */
+ num++;
+ sprintf( p, "%04x.tmp", num );
+ } while (num != (unique & 0xffff));
+ }
- lstrcpyn32A( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
+ /* Get the full path name */
+
+ if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
+ {
+ if (access( full_name.long_name, W_OK ) == -1)
+ fprintf( stderr,
+ "Warning: GetTempFileName returns '%s', which doesn't seem to be writeable.\n"
+ "Please check your configuration file if this generates a failure.\n",
+ buffer);
+ }
dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
- if (-1==access(DOSFS_GetUnixFileName(buffer,TRUE),W_OK))
- fprintf(stderr,"Warning: GetTempFileName returns '%s', which doesn't seem to be writeable. Please check your configuration file if this generates a failure.\n",buffer);
- return num;
+ return unique ? unique : num;
}
@@ -576,7 +581,7 @@
HFILE32 hFileRet;
FILETIME filetime;
WORD filedatetime[2];
- const char *unixName, *dosName;
+ DOS_FULL_NAME full_name;
char *p;
int unixMode;
@@ -589,9 +594,10 @@
if (mode & OF_PARSE)
{
- if (!(dosName = DOSFS_GetDosTrueName( name, FALSE ))) goto error;
- lstrcpyn32A( ofs->szPathName, dosName, sizeof(ofs->szPathName) );
- ofs->fFixedDisk = (GetDriveType16( dosName[0]-'A' ) != DRIVE_REMOVABLE);
+ if (!GetFullPathName32A( name, sizeof(ofs->szPathName),
+ ofs->szPathName, NULL )) goto error;
+ ofs->fFixedDisk = (GetDriveType16( ofs->szPathName[0]-'A' )
+ != DRIVE_REMOVABLE);
dprintf_file( stddeb, "OpenFile(%s): OF_PARSE, res = '%s'\n",
name, ofs->szPathName );
return 0;
@@ -604,8 +610,8 @@
{
if ((hFileRet = FILE_Create(name,0666,FALSE))== INVALID_HANDLE_VALUE32)
goto error;
- lstrcpyn32A( ofs->szPathName, DOSFS_GetDosTrueName( name, FALSE ),
- sizeof(ofs->szPathName) );
+ GetFullPathName32A( name, sizeof(ofs->szPathName),
+ ofs->szPathName, NULL );
goto success;
}
@@ -614,11 +620,7 @@
if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
{
/* First try the file name as is */
- if ((unixName = DOSFS_GetUnixFileName( name, TRUE )) != NULL)
- {
- lstrcpyn32A( ofs->szPathName, name, sizeof(ofs->szPathName) );
- goto found;
- }
+ if (DOSFS_GetFullName( name, TRUE, &full_name )) goto found;
/* Now remove the path */
if (name[0] && (name[1] == ':')) name += 2;
if ((p = strrchr( name, '\\' ))) name = p + 1;
@@ -628,20 +630,17 @@
/* Now look for the file */
- if (!DIR_SearchPath( NULL, name, NULL, sizeof(ofs->szPathName),
- ofs->szPathName, NULL, win32 ))
- goto not_found;
- if (!(unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )))
- goto not_found;
+ if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 )) goto not_found;
found:
- dprintf_file( stddeb, "OpenFile: found '%s'\n", unixName );
- lstrcpyn32A(ofs->szPathName, DOSFS_GetDosTrueName( ofs->szPathName, FALSE),
- sizeof(ofs->szPathName) );
+ dprintf_file( stddeb, "OpenFile: found %s = %s\n",
+ full_name.long_name, full_name.short_name );
+ lstrcpyn32A( ofs->szPathName, full_name.short_name,
+ sizeof(ofs->szPathName) );
if (mode & OF_DELETE)
{
- if (unlink( unixName ) == -1) goto not_found;
+ if (unlink( full_name.long_name ) == -1) goto not_found;
dprintf_file( stddeb, "OpenFile(%s): OF_DELETE return = OK\n", name);
return 1;
}
@@ -657,8 +656,8 @@
unixMode = O_RDONLY; break;
}
- if ((hFileRet = FILE_OpenUnixFile( unixName, unixMode )) == HFILE_ERROR32)
- goto not_found;
+ hFileRet = FILE_OpenUnixFile( full_name.long_name, unixMode );
+ if (hFileRet == HFILE_ERROR32) goto not_found;
GetFileTime( hFileRet, NULL, NULL, &filetime );
FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
@@ -715,7 +714,7 @@
*/
HFILE16 _lclose16( HFILE16 hFile )
{
- dprintf_file( stddeb, "_lclose: handle %d\n", hFile );
+ dprintf_file( stddeb, "_lclose16: handle %d\n", hFile );
return CloseHandle( hFile ) ? 0 : HFILE_ERROR16;
}
@@ -725,7 +724,7 @@
*/
HFILE32 _lclose32( HFILE32 hFile )
{
- dprintf_file( stddeb, "_lclose: handle %d\n", hFile );
+ dprintf_file( stddeb, "_lclose32: handle %d\n", hFile );
return CloseHandle( hFile ) ? 0 : HFILE_ERROR32;
}
@@ -817,11 +816,44 @@
/***********************************************************************
+ * SetFilePointer (KERNEL32.492)
+ */
+DWORD SetFilePointer( HFILE32 hFile, LONG distance, LONG *highword,
+ DWORD method )
+{
+ DOS_FILE *file;
+ int origin, result;
+
+ if (highword && *highword)
+ {
+ fprintf( stderr, "SetFilePointer: 64-bit offsets not supported yet\n");
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0xffffffff;
+ }
+ dprintf_file( stddeb, "SetFilePointer: handle %d offset %ld origin %ld\n",
+ hFile, distance, method );
+
+ if (!(file = FILE_GetFile( hFile ))) return 0xffffffff;
+ switch(method)
+ {
+ case 1: origin = SEEK_CUR; break;
+ case 2: origin = SEEK_END; break;
+ default: origin = SEEK_SET; break;
+ }
+
+ if ((result = lseek( file->unix_handle, distance, origin )) == -1)
+ FILE_SetDosError();
+ FILE_ReleaseFile( file );
+ return (DWORD)result;
+}
+
+
+/***********************************************************************
* _llseek16 (KERNEL.84)
*/
LONG _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
{
- return _llseek32( hFile, lOffset, nOrigin );
+ return SetFilePointer( hFile, lOffset, NULL, nOrigin );
}
@@ -830,24 +862,7 @@
*/
LONG _llseek32( HFILE32 hFile, LONG lOffset, INT32 nOrigin )
{
- DOS_FILE *file;
- int origin, result;
-
- dprintf_file( stddeb, "_llseek: handle %d, offset %ld, origin %d\n",
- hFile, lOffset, nOrigin);
-
- if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR32;
- switch(nOrigin)
- {
- case 1: origin = SEEK_CUR; break;
- case 2: origin = SEEK_END; break;
- default: origin = SEEK_SET; break;
- }
-
- if ((result = lseek( file->unix_handle, lOffset, origin )) == -1)
- FILE_SetDosError();
- FILE_ReleaseFile( file );
- return result;
+ return SetFilePointer( hFile, lOffset, NULL, nOrigin );
}
@@ -961,47 +976,27 @@
HGLOBAL16 hPDB = GetCurrentPDB();
PDB *pdb = (PDB *)GlobalLock16( hPDB );
BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
- WORD i;
dprintf_file( stddeb, "SetHandleCount(%d)\n", count );
if (count < 20) count = 20; /* No point in going below 20 */
else if (count > 254) count = 254;
- /* If shrinking the table, make sure all extra file handles are closed */
- if (count < pdb->nbFiles)
- {
- for (i = count; i < pdb->nbFiles; i++)
- if (files[i] != 0xff) /* File open */
- {
- DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError,
- SA_Abort, EL_Disk );
- return pdb->nbFiles;
- }
- }
-
if (count == 20)
{
if (pdb->nbFiles > 20)
{
memcpy( pdb->fileHandles, files, 20 );
-#ifdef WINELIB
- GlobalFree32( (HGLOBAL32)pdb->fileHandlesPtr );
- pdb->fileHandlesPtr = (SEGPTR)pdb->fileHandles;
-#else
- GlobalFree16( GlobalHandle16( SELECTOROF(pdb->fileHandlesPtr) ));
+ GlobalFree16( pdb->hFileHandles );
pdb->fileHandlesPtr = (SEGPTR)MAKELONG( 0x18,
GlobalHandleToSel( hPDB ) );
-#endif
+ pdb->hFileHandles = 0;
pdb->nbFiles = 20;
}
}
else /* More than 20, need a new file handles table */
{
BYTE *newfiles;
-#ifdef WINELIB
- newfiles = (BYTE *)GlobalAlloc32( GMEM_FIXED, count );
-#else
HGLOBAL16 newhandle = GlobalAlloc16( GMEM_MOVEABLE, count );
if (!newhandle)
{
@@ -1009,21 +1004,16 @@
return pdb->nbFiles;
}
newfiles = (BYTE *)GlobalLock16( newhandle );
-#endif /* WINELIB */
+
if (count > pdb->nbFiles)
{
memcpy( newfiles, files, pdb->nbFiles );
memset( newfiles + pdb->nbFiles, 0xff, count - pdb->nbFiles );
}
else memcpy( newfiles, files, count );
-#ifdef WINELIB
- if (pdb->nbFiles > 20) GlobalFree32( (HGLOBAL32)pdb->fileHandlesPtr );
- pdb->fileHandlesPtr = (SEGPTR)newfiles;
-#else
- if (pdb->nbFiles > 20)
- GlobalFree16( GlobalHandle16( SELECTOROF(pdb->fileHandlesPtr) ));
+ if (pdb->nbFiles > 20) GlobalFree16( pdb->hFileHandles );
pdb->fileHandlesPtr = WIN16_GlobalLock16( newhandle );
-#endif /* WINELIB */
+ pdb->hFileHandles = newhandle;
pdb->nbFiles = count;
}
return pdb->nbFiles;
@@ -1095,6 +1085,7 @@
*/
BOOL32 DeleteFile32A( LPCSTR path )
{
+ DOS_FULL_NAME full_name;
const char *unixName;
dprintf_file(stddeb, "DeleteFile: '%s'\n", path );
@@ -1106,8 +1097,8 @@
return FALSE;
}
- if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return FALSE;
- if (unlink( unixName ) == -1)
+ if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
+ if (unlink( full_name.long_name ) == -1)
{
FILE_SetDosError();
return FALSE;
@@ -1153,6 +1144,99 @@
}
+/**************************************************************************
+ * MoveFile32A (KERNEL32.387)
+ */
+BOOL32 MoveFile32A( LPCSTR fn1, LPCSTR fn2 )
+{
+ DOS_FULL_NAME full_name1, full_name2;
+
+ dprintf_file( stddeb, "MoveFile32A(%s,%s)\n", fn1, fn2 );
+
+ if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
+ if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
+ /* FIXME: should not replace an existing file */
+ /* FIXME: should handle renaming across devices */
+ if (rename( full_name1.long_name, full_name2.long_name ) == -1)
+ {
+ FILE_SetDosError();
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/**************************************************************************
+ * MoveFile32W (KERNEL32.390)
+ */
+BOOL32 MoveFile32W( LPCWSTR fn1, LPCWSTR fn2 )
+{
+ LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
+ LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
+ BOOL32 res = MoveFile32A( afn1, afn2 );
+ HeapFree( GetProcessHeap(), 0, afn1 );
+ HeapFree( GetProcessHeap(), 0, afn2 );
+ return res;
+}
+
+
+/**************************************************************************
+ * CopyFile32A (KERNEL32.36)
+ */
+BOOL32 CopyFile32A( LPCSTR source, LPCSTR dest, BOOL32 fail_if_exists )
+{
+ HFILE32 h1, h2;
+ BY_HANDLE_FILE_INFORMATION info;
+ UINT32 count;
+ BOOL32 ret = FALSE;
+ int mode;
+ char buffer[2048];
+
+ if ((h1 = _lopen32( source, OF_READ )) == HFILE_ERROR32) return FALSE;
+ if (!GetFileInformationByHandle( h1, &info ))
+ {
+ CloseHandle( h1 );
+ return FALSE;
+ }
+ mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
+ if ((h2 = FILE_Create( dest, mode, fail_if_exists )) == HFILE_ERROR32)
+ {
+ CloseHandle( h1 );
+ return FALSE;
+ }
+ while ((count = _lread32( h2, buffer, sizeof(buffer) )) > 0)
+ {
+ char *p = buffer;
+ while (count > 0)
+ {
+ INT32 res = _lwrite32( h2, p, count );
+ if (res <= 0) goto done;
+ p += res;
+ count -= res;
+ }
+ }
+ ret = TRUE;
+done:
+ CloseHandle( h1 );
+ CloseHandle( h2 );
+ return ret;
+}
+
+
+/**************************************************************************
+ * CopyFile32W (KERNEL32.37)
+ */
+BOOL32 CopyFile32W( LPCWSTR source, LPCWSTR dest, BOOL32 fail_if_exists )
+{
+ LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, source );
+ LPSTR destA = HEAP_strdupWtoA( GetProcessHeap(), 0, dest );
+ BOOL32 ret = CopyFile32A( sourceA, destA, fail_if_exists );
+ HeapFree( GetProcessHeap(), 0, sourceA );
+ HeapFree( GetProcessHeap(), 0, destA );
+ return ret;
+}
+
+
/***********************************************************************
* SetFileTime (KERNEL32.493)
*/
@@ -1172,11 +1256,11 @@
lpLastWriteTime
);
if (lpLastAccessTime)
- utimbuf.actime = DOSFS_FileTimeToUnixTime(lpLastAccessTime);
+ utimbuf.actime = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
else
utimbuf.actime = 0; /* FIXME */
if (lpLastWriteTime)
- utimbuf.modtime = DOSFS_FileTimeToUnixTime(lpLastWriteTime);
+ utimbuf.modtime = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
else
utimbuf.modtime = 0; /* FIXME */
if (-1==utime(file->unix_name,&utimbuf))
diff --git a/files/profile.c b/files/profile.c
index 393fe48..06b8b70 100644
--- a/files/profile.c
+++ b/files/profile.c
@@ -11,7 +11,7 @@
#include <string.h>
#include "windows.h"
-#include "dos_fs.h"
+#include "file.h"
#include "heap.h"
#include "stddebug.h"
#include "debug.h"
@@ -36,6 +36,8 @@
BOOL32 changed;
PROFILESECTION *section;
char *dos_name;
+ char *unix_name;
+ char *filename;
} PROFILE;
@@ -332,8 +334,7 @@
FILE *file = NULL;
if (!CurProfile.changed || !CurProfile.dos_name) return TRUE;
- if (!(unix_name = DOSFS_GetUnixFileName( CurProfile.dos_name, FALSE )) ||
- !(file = fopen( unix_name, "w" )))
+ if (!(unix_name = CurProfile.unix_name) || !(file = fopen(unix_name, "w")))
{
/* Try to create it in $HOME/.wine */
/* FIXME: this will need a more general solution */
@@ -343,7 +344,7 @@
strcat( buffer, "/.wine/" );
p = buffer + strlen(buffer);
strcpy( p, strrchr( CurProfile.dos_name, '\\' ) + 1 );
- AnsiLower( p );
+ CharLower32A( p );
file = fopen( buffer, "w" );
unix_name = buffer;
}
@@ -372,24 +373,32 @@
*/
static BOOL32 PROFILE_Open( LPCSTR filename )
{
+ DOS_FULL_NAME full_name;
char buffer[MAX_PATHNAME_LEN];
- const char *dos_name, *unix_name;
char *newdos_name, *p;
FILE *file = NULL;
+ if (CurProfile.filename && !strcmp( filename, CurProfile.filename ))
+ {
+ dprintf_profile( stddeb, "PROFILE_Open(%s): already opened\n",
+ filename );
+ return TRUE;
+ }
+
if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
strchr( filename, ':' ))
{
- if (!(dos_name = DOSFS_GetDosTrueName( filename, FALSE))) return FALSE;
+ if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
}
else
{
GetWindowsDirectory32A( buffer, sizeof(buffer) );
strcat( buffer, "\\" );
strcat( buffer, filename );
- if (!(dos_name = DOSFS_GetDosTrueName( buffer, FALSE ))) return FALSE;
+ if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
}
- if (CurProfile.dos_name && !strcmp( dos_name, CurProfile.dos_name ))
+ if (CurProfile.dos_name &&
+ !strcmp( full_name.short_name, CurProfile.dos_name ))
{
dprintf_profile( stddeb, "PROFILE_Open(%s): already opened\n",
filename );
@@ -398,12 +407,15 @@
/* Flush the previous profile */
- newdos_name = HEAP_strdupA( SystemHeap, 0, dos_name );
+ newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
PROFILE_FlushFile();
PROFILE_Free( CurProfile.section );
if (CurProfile.dos_name) HeapFree( SystemHeap, 0, CurProfile.dos_name );
+ if (CurProfile.unix_name) HeapFree( SystemHeap, 0, CurProfile.unix_name );
+ if (CurProfile.filename) HeapFree( SystemHeap, 0, CurProfile.filename );
CurProfile.section = NULL;
CurProfile.dos_name = newdos_name;
+ CurProfile.filename = HEAP_strdupA( SystemHeap, 0, filename );
/* Try to open the profile file, first in $HOME/.wine */
@@ -414,15 +426,22 @@
strcat( buffer, "/.wine/" );
p = buffer + strlen(buffer);
strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
- AnsiLower( p );
+ CharLower32A( p );
if ((file = fopen( buffer, "r" )))
- dprintf_profile( stddeb, "Found it in %s\n", buffer );
+ {
+ dprintf_profile( stddeb, "PROFILE_Open(%s): found it in %s\n",
+ filename, buffer );
+ CurProfile.unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
+ }
}
- if (!file && ((unix_name = DOSFS_GetUnixFileName( dos_name, TRUE ))))
+ if (!file)
{
- if ((file = fopen( unix_name, "r" )))
- dprintf_profile( stddeb, "Found it in %s\n", unix_name );
+ CurProfile.unix_name = HEAP_strdupA( SystemHeap, 0,
+ full_name.long_name );
+ if ((file = fopen( full_name.long_name, "r" )))
+ dprintf_profile( stddeb, "PROFILE_Open(%s): found it in %s\n",
+ filename, full_name.long_name );
}
if (file)
@@ -435,7 +454,6 @@
/* Does not exist yet, we will create it in PROFILE_FlushFile */
fprintf( stderr, "Warning: profile file %s not found\n", newdos_name );
}
- dprintf_profile( stddeb, "PROFILE_Open(%s): successful\n", filename );
return TRUE;
}