mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 12:49:45 +00:00
Removed a number of internal file functions that are no longer used.
This commit is contained in:
parent
57b0cbff26
commit
c349d7d297
@ -19,7 +19,6 @@ SPEC_SRCS16 = \
|
||||
|
||||
C_SRCS = \
|
||||
$(TOPOBJDIR)/files/directory.c \
|
||||
$(TOPOBJDIR)/files/dos_fs.c \
|
||||
$(TOPOBJDIR)/files/drive.c \
|
||||
$(TOPOBJDIR)/files/file.c \
|
||||
$(TOPOBJDIR)/files/smb.c \
|
||||
|
@ -244,3 +244,34 @@ BOOL WINAPI SwitchToThread(void)
|
||||
Sleep(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MulDiv (KERNEL32.@)
|
||||
* RETURNS
|
||||
* Result of multiplication and division
|
||||
* -1: Overflow occurred or Divisor was 0
|
||||
*/
|
||||
INT WINAPI MulDiv( INT nMultiplicand, INT nMultiplier, INT nDivisor)
|
||||
{
|
||||
LONGLONG ret;
|
||||
|
||||
if (!nDivisor) return -1;
|
||||
|
||||
/* We want to deal with a positive divisor to simplify the logic. */
|
||||
if (nDivisor < 0)
|
||||
{
|
||||
nMultiplicand = - nMultiplicand;
|
||||
nDivisor = -nDivisor;
|
||||
}
|
||||
|
||||
/* If the result is positive, we "add" to round. else, we subtract to round. */
|
||||
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
|
||||
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
|
||||
ret = (((LONGLONG)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
|
||||
else
|
||||
ret = (((LONGLONG)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
|
||||
|
||||
if ((ret > 2147483647) || (ret < -2147483647)) return -1;
|
||||
return ret;
|
||||
}
|
||||
|
@ -891,3 +891,57 @@ BOOL WINAPI GetDaylightFlag(void)
|
||||
struct tm *ptm = localtime( &t);
|
||||
return ptm->tm_isdst > 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DosDateTimeToFileTime (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI DosDateTimeToFileTime( WORD fatdate, WORD fattime, LPFILETIME ft)
|
||||
{
|
||||
struct tm newtm;
|
||||
#ifndef HAVE_TIMEGM
|
||||
struct tm *gtm;
|
||||
time_t time1, time2;
|
||||
#endif
|
||||
|
||||
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;
|
||||
#ifdef HAVE_TIMEGM
|
||||
RtlSecondsSince1970ToTime( timegm(&newtm), (LARGE_INTEGER *)ft );
|
||||
#else
|
||||
time1 = mktime(&newtm);
|
||||
gtm = gmtime(&time1);
|
||||
time2 = mktime(gtm);
|
||||
RtlSecondsSince1970ToTime( 2*time1-time2, (LARGE_INTEGER *)ft );
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FileTimeToDosDateTime (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
|
||||
LPWORD fattime )
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
ULONG t;
|
||||
time_t unixtime;
|
||||
struct tm* tm;
|
||||
|
||||
li.u.LowPart = ft->dwLowDateTime;
|
||||
li.u.HighPart = ft->dwHighDateTime;
|
||||
RtlTimeToSecondsSince1970( &li, &t );
|
||||
unixtime = t;
|
||||
tm = gmtime( &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;
|
||||
}
|
||||
|
@ -223,8 +223,6 @@ int DIR_Init(void)
|
||||
TRACE("SystemDir = %s\n", debugstr_w(DIR_System) );
|
||||
TRACE("TempDir = %s\n", debugstr_w(tmp_dir) );
|
||||
TRACE("SYSTEMROOT = %s\n", debugstr_w(DIR_Windows) );
|
||||
TRACE("Cwd = %c:\\%s\n",
|
||||
'A' + drive, debugstr_w(DRIVE_GetDosCwd(drive)) );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, tmp_dir );
|
||||
|
||||
|
936
files/dos_fs.c
936
files/dos_fs.c
@ -1,936 +0,0 @@
|
||||
/*
|
||||
* DOS file system functions
|
||||
*
|
||||
* Copyright 1993 Erik Bos
|
||||
* Copyright 1996 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_SYS_ERRNO_H
|
||||
#include <sys/errno.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_IOCTL_H
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#include "ntstatus.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wingdi.h"
|
||||
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "file.h"
|
||||
#include "winreg.h"
|
||||
#include "winternl.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/exception.h"
|
||||
#include "excpt.h"
|
||||
|
||||
#include "smb.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dosfs);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(file);
|
||||
|
||||
/* Define the VFAT ioctl to get both short and long file names */
|
||||
/* FIXME: is it possible to get this to work on other systems? */
|
||||
#ifdef linux
|
||||
/* We want the real kernel dirent structure, not the libc one */
|
||||
typedef struct
|
||||
{
|
||||
long d_ino;
|
||||
long d_off;
|
||||
unsigned short d_reclen;
|
||||
char d_name[256];
|
||||
} KERNEL_DIRENT;
|
||||
|
||||
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, KERNEL_DIRENT [2] )
|
||||
|
||||
/* To avoid blocking on non-directories in DOSFS_OpenDir_VFAT*/
|
||||
#ifndef O_DIRECTORY
|
||||
# define O_DIRECTORY 0200000 /* must be directory */
|
||||
#endif
|
||||
|
||||
#else /* linux */
|
||||
#undef VFAT_IOCTL_READDIR_BOTH /* just in case... */
|
||||
#endif /* linux */
|
||||
|
||||
/* Chars we don't want to see in DOS file names */
|
||||
#define INVALID_DOS_CHARS "*?<>|\"+=,;[] \345"
|
||||
|
||||
/* at some point we may want to allow Winelib apps to set this */
|
||||
static const BOOL is_case_sensitive = FALSE;
|
||||
|
||||
/*
|
||||
* Directory info for DOSFS_ReadDir
|
||||
* contains the names of *all* the files in the directory
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int used;
|
||||
int size;
|
||||
WCHAR names[1];
|
||||
} DOS_DIR;
|
||||
|
||||
|
||||
/* return non-zero if c is the end of a directory name */
|
||||
static inline int is_end_of_name(WCHAR c)
|
||||
{
|
||||
return !c || (c == '/') || (c == '\\');
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_ValidDOSName
|
||||
*
|
||||
* Return 1 if Unix file 'name' is also a valid MS-DOS name
|
||||
* (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
|
||||
* File name can be terminated by '\0', '\\' or '/'.
|
||||
*/
|
||||
static int DOSFS_ValidDOSName( LPCWSTR name )
|
||||
{
|
||||
static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
|
||||
const WCHAR *p = name;
|
||||
const char *invalid = !is_case_sensitive ? (invalid_chars + 26) : invalid_chars;
|
||||
int len = 0;
|
||||
|
||||
if (*p == '.')
|
||||
{
|
||||
/* Check for "." and ".." */
|
||||
p++;
|
||||
if (*p == '.') p++;
|
||||
/* All other names beginning with '.' are invalid */
|
||||
return (is_end_of_name(*p));
|
||||
}
|
||||
while (!is_end_of_name(*p))
|
||||
{
|
||||
if (*p < 256 && strchr( invalid, (char)*p )) return 0; /* Invalid char */
|
||||
if (*p == '.') break; /* Start of the extension */
|
||||
if (++len > 8) return 0; /* Name too long */
|
||||
p++;
|
||||
}
|
||||
if (*p != '.') return 1; /* End of name */
|
||||
p++;
|
||||
if (is_end_of_name(*p)) return 0; /* Empty extension not allowed */
|
||||
len = 0;
|
||||
while (!is_end_of_name(*p))
|
||||
{
|
||||
if (*p < 256 && strchr( invalid, (char)*p )) return 0; /* Invalid char */
|
||||
if (*p == '.') return 0; /* Second extension not allowed */
|
||||
if (++len > 3) return 0; /* Extension too long */
|
||||
p++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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 FALSE if the name is not a valid DOS name.
|
||||
* 'buffer' must be at least 12 characters long.
|
||||
*/
|
||||
static BOOL DOSFS_ToDosFCBFormat( LPCWSTR name, LPWSTR buffer )
|
||||
{
|
||||
static const char invalid_chars[] = INVALID_DOS_CHARS;
|
||||
LPCWSTR p = name;
|
||||
int i;
|
||||
|
||||
/* Check for "." and ".." */
|
||||
if (*p == '.')
|
||||
{
|
||||
p++;
|
||||
buffer[0] = '.';
|
||||
for(i = 1; i < 11; i++) buffer[i] = ' ';
|
||||
buffer[11] = 0;
|
||||
if (*p == '.')
|
||||
{
|
||||
buffer[1] = '.';
|
||||
p++;
|
||||
}
|
||||
return (!*p || (*p == '/') || (*p == '\\'));
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
switch(*p)
|
||||
{
|
||||
case '\0':
|
||||
case '\\':
|
||||
case '/':
|
||||
case '.':
|
||||
buffer[i] = ' ';
|
||||
break;
|
||||
case '?':
|
||||
p++;
|
||||
/* fall through */
|
||||
case '*':
|
||||
buffer[i] = '?';
|
||||
break;
|
||||
default:
|
||||
if (*p < 256 && strchr( invalid_chars, (char)*p )) return FALSE;
|
||||
buffer[i] = toupperW(*p);
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == '*')
|
||||
{
|
||||
/* Skip all chars after wildcard up to first dot */
|
||||
while (*p && (*p != '/') && (*p != '\\') && (*p != '.')) p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if name too long */
|
||||
if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return FALSE;
|
||||
}
|
||||
if (*p == '.') p++; /* Skip dot */
|
||||
|
||||
for (i = 8; i < 11; i++)
|
||||
{
|
||||
switch(*p)
|
||||
{
|
||||
case '\0':
|
||||
case '\\':
|
||||
case '/':
|
||||
buffer[i] = ' ';
|
||||
break;
|
||||
case '.':
|
||||
return FALSE; /* Second extension not allowed */
|
||||
case '?':
|
||||
p++;
|
||||
/* fall through */
|
||||
case '*':
|
||||
buffer[i] = '?';
|
||||
break;
|
||||
default:
|
||||
if (*p < 256 && strchr( invalid_chars, (char)*p )) return FALSE;
|
||||
buffer[i] = toupperW(*p);
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer[11] = '\0';
|
||||
|
||||
/* at most 3 character of the extension are processed
|
||||
* is something behind this ?
|
||||
*/
|
||||
while (*p == '*' || *p == ' ') p++; /* skip wildcards and spaces */
|
||||
return is_end_of_name(*p);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_ToDosDTAFormat
|
||||
*
|
||||
* 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 '/'.
|
||||
* 'buffer' must be at least 13 characters long.
|
||||
*/
|
||||
static void DOSFS_ToDosDTAFormat( LPCWSTR name, LPWSTR buffer )
|
||||
{
|
||||
LPWSTR p;
|
||||
|
||||
memcpy( buffer, name, 8 * sizeof(WCHAR) );
|
||||
p = buffer + 8;
|
||||
while ((p > buffer) && (p[-1] == ' ')) p--;
|
||||
*p++ = '.';
|
||||
memcpy( p, name + 8, 3 * sizeof(WCHAR) );
|
||||
p += 3;
|
||||
while (p[-1] == ' ') p--;
|
||||
if (p[-1] == '.') p--;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_AddDirEntry
|
||||
*
|
||||
* Used to construct an array of filenames in DOSFS_OpenDir
|
||||
*/
|
||||
static BOOL DOSFS_AddDirEntry(DOS_DIR **dir, LPCWSTR name, LPCWSTR dosname)
|
||||
{
|
||||
int extra1 = strlenW(name) + 1;
|
||||
int extra2 = strlenW(dosname) + 1;
|
||||
|
||||
/* if we need more, at minimum double the size */
|
||||
if( (extra1 + extra2 + (*dir)->used) > (*dir)->size)
|
||||
{
|
||||
int more = (*dir)->size;
|
||||
DOS_DIR *t;
|
||||
|
||||
if(more<(extra1+extra2))
|
||||
more = extra1+extra2;
|
||||
|
||||
t = HeapReAlloc(GetProcessHeap(), 0, *dir, sizeof(**dir) +
|
||||
((*dir)->size + more)*sizeof(WCHAR) );
|
||||
if(!t)
|
||||
{
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
ERR("Out of memory caching directory structure %d %d %d\n",
|
||||
(*dir)->size, more, (*dir)->used);
|
||||
return FALSE;
|
||||
}
|
||||
(*dir) = t;
|
||||
(*dir)->size += more;
|
||||
}
|
||||
|
||||
/* at this point, the dir structure is big enough to hold these names */
|
||||
strcpyW(&(*dir)->names[(*dir)->used], name);
|
||||
(*dir)->used += extra1;
|
||||
strcpyW(&(*dir)->names[(*dir)->used], dosname);
|
||||
(*dir)->used += extra2;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_OpenDir_VFAT
|
||||
*/
|
||||
static BOOL DOSFS_OpenDir_VFAT(DOS_DIR **dir, const char *unix_path)
|
||||
{
|
||||
#ifdef VFAT_IOCTL_READDIR_BOTH
|
||||
KERNEL_DIRENT de[2];
|
||||
int fd = open( unix_path, O_RDONLY|O_DIRECTORY );
|
||||
BOOL r = TRUE;
|
||||
|
||||
/* Check if the VFAT ioctl is supported on this directory */
|
||||
|
||||
if ( fd<0 )
|
||||
return FALSE;
|
||||
|
||||
while (1)
|
||||
{
|
||||
WCHAR long_name[MAX_PATH];
|
||||
WCHAR short_name[12];
|
||||
|
||||
r = (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1);
|
||||
if(!r)
|
||||
break;
|
||||
if (!de[0].d_reclen)
|
||||
break;
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, de[0].d_name, -1, long_name, MAX_PATH);
|
||||
if (!DOSFS_ToDosFCBFormat( long_name, short_name ))
|
||||
short_name[0] = '\0';
|
||||
if (de[1].d_name[0])
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, de[1].d_name, -1, long_name, MAX_PATH);
|
||||
else
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, de[0].d_name, -1, long_name, MAX_PATH);
|
||||
r = DOSFS_AddDirEntry(dir, long_name, short_name );
|
||||
if(!r)
|
||||
break;
|
||||
}
|
||||
if(r)
|
||||
{
|
||||
static const WCHAR empty_strW[] = { 0 };
|
||||
DOSFS_AddDirEntry(dir, empty_strW, empty_strW);
|
||||
}
|
||||
close(fd);
|
||||
return r;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif /* VFAT_IOCTL_READDIR_BOTH */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_OpenDir_Normal
|
||||
*
|
||||
* Now use the standard opendir/readdir interface
|
||||
*/
|
||||
static BOOL DOSFS_OpenDir_Normal( DOS_DIR **dir, const char *unix_path )
|
||||
{
|
||||
DIR *unixdir = opendir( unix_path );
|
||||
BOOL r = TRUE;
|
||||
static const WCHAR empty_strW[] = { 0 };
|
||||
|
||||
if(!unixdir)
|
||||
return FALSE;
|
||||
while(1)
|
||||
{
|
||||
WCHAR long_name[MAX_PATH];
|
||||
struct dirent *de = readdir(unixdir);
|
||||
|
||||
if(!de)
|
||||
break;
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, de->d_name, -1, long_name, MAX_PATH);
|
||||
r = DOSFS_AddDirEntry(dir, long_name, empty_strW);
|
||||
if(!r)
|
||||
break;
|
||||
}
|
||||
if(r)
|
||||
DOSFS_AddDirEntry(dir, empty_strW, empty_strW);
|
||||
closedir(unixdir);
|
||||
return r;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_OpenDir
|
||||
*/
|
||||
static DOS_DIR *DOSFS_OpenDir( const char *unix_path )
|
||||
{
|
||||
const int init_size = 0x100;
|
||||
DOS_DIR *dir = HeapAlloc( GetProcessHeap(), 0, sizeof(*dir) + init_size*sizeof (WCHAR));
|
||||
BOOL r;
|
||||
|
||||
TRACE("%s\n",debugstr_a(unix_path));
|
||||
|
||||
if (!dir)
|
||||
{
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
return NULL;
|
||||
}
|
||||
dir->used = 0;
|
||||
dir->size = init_size;
|
||||
|
||||
/* Treat empty path as root directory. This simplifies path split into
|
||||
directory and mask in several other places */
|
||||
if (!*unix_path) unix_path = "/";
|
||||
|
||||
r = DOSFS_OpenDir_VFAT( &dir, unix_path);
|
||||
|
||||
if(!r)
|
||||
r = DOSFS_OpenDir_Normal( &dir, unix_path);
|
||||
|
||||
if(!r)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, dir);
|
||||
return NULL;
|
||||
}
|
||||
dir->used = 0;
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_CloseDir
|
||||
*/
|
||||
static void DOSFS_CloseDir( DOS_DIR *dir )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, dir );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_ReadDir
|
||||
*/
|
||||
static BOOL DOSFS_ReadDir( DOS_DIR *dir, LPCWSTR *long_name,
|
||||
LPCWSTR *short_name )
|
||||
{
|
||||
LPCWSTR sn, ln;
|
||||
|
||||
if (!dir)
|
||||
return FALSE;
|
||||
|
||||
/* the long pathname is first */
|
||||
ln = &dir->names[dir->used];
|
||||
if(ln[0])
|
||||
*long_name = ln;
|
||||
else
|
||||
return FALSE;
|
||||
dir->used += (strlenW(ln) + 1);
|
||||
|
||||
/* followed by the short path name */
|
||||
sn = &dir->names[dir->used];
|
||||
if(sn[0])
|
||||
*short_name = sn;
|
||||
else
|
||||
*short_name = NULL;
|
||||
dir->used += (strlenW(sn) + 1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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 void DOSFS_Hash( LPCWSTR name, LPWSTR buffer, BOOL dir_format )
|
||||
{
|
||||
static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
|
||||
static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
|
||||
|
||||
LPCWSTR p, ext;
|
||||
LPWSTR dst;
|
||||
unsigned short hash;
|
||||
int i;
|
||||
|
||||
if (dir_format)
|
||||
{
|
||||
for(i = 0; i < 11; i++) buffer[i] = ' ';
|
||||
buffer[11] = 0;
|
||||
}
|
||||
|
||||
if (DOSFS_ValidDOSName( name ))
|
||||
{
|
||||
/* Check for '.' and '..' */
|
||||
if (*name == '.')
|
||||
{
|
||||
buffer[0] = '.';
|
||||
if (!dir_format) buffer[1] = buffer[2] = '\0';
|
||||
if (name[1] == '.') buffer[1] = '.';
|
||||
return;
|
||||
}
|
||||
|
||||
/* Simply copy the name, converting to uppercase */
|
||||
|
||||
for (dst = buffer; !is_end_of_name(*name) && (*name != '.'); name++)
|
||||
*dst++ = toupperW(*name);
|
||||
if (*name == '.')
|
||||
{
|
||||
if (dir_format) dst = buffer + 8;
|
||||
else *dst++ = '.';
|
||||
for (name++; !is_end_of_name(*name); name++)
|
||||
*dst++ = toupperW(*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 (!is_case_sensitive)
|
||||
{
|
||||
for (p = name, hash = 0xbeef; !is_end_of_name(p[1]); p++)
|
||||
hash = (hash<<3) ^ (hash>>5) ^ tolowerW(*p) ^ (tolowerW(p[1]) << 8);
|
||||
hash = (hash<<3) ^ (hash>>5) ^ tolowerW(*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++ = (*p < 256 && strchr( invalid_chars, (char)*p )) ? '_' : toupperW(*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++ = (*ext < 256 && strchr( invalid_chars, (char)*ext )) ? '_' : toupperW(*ext);
|
||||
}
|
||||
if (!dir_format) *dst = '\0';
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_FindUnixName
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *long_buf,
|
||||
INT long_len, LPWSTR short_buf )
|
||||
{
|
||||
DOS_DIR *dir;
|
||||
LPCWSTR long_name, short_name;
|
||||
WCHAR dos_name[12], tmp_buf[13];
|
||||
BOOL ret;
|
||||
|
||||
LPCWSTR p = strchrW( name, '/' );
|
||||
int len = p ? (int)(p - name) : strlenW(name);
|
||||
if ((p = strchrW( name, '\\' ))) len = min( (int)(p - name), len );
|
||||
/* Ignore trailing dots and spaces */
|
||||
while (len > 1 && (name[len-1] == '.' || name[len-1] == ' ')) len--;
|
||||
if (long_len < len + 1) return FALSE;
|
||||
|
||||
TRACE("%s,%s\n", path->long_name, debugstr_w(name) );
|
||||
|
||||
if (!DOSFS_ToDosFCBFormat( name, dos_name )) dos_name[0] = '\0';
|
||||
|
||||
if (!(dir = DOSFS_OpenDir( path->long_name )))
|
||||
{
|
||||
WARN("(%s,%s): can't open dir: %s\n",
|
||||
path->long_name, debugstr_w(name), strerror(errno) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while ((ret = DOSFS_ReadDir( dir, &long_name, &short_name )))
|
||||
{
|
||||
/* Check against Unix name */
|
||||
if (len == strlenW(long_name))
|
||||
{
|
||||
if (is_case_sensitive)
|
||||
{
|
||||
if (!strncmpW( long_name, name, len )) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strncmpiW( long_name, name, len )) break;
|
||||
}
|
||||
}
|
||||
if (dos_name[0])
|
||||
{
|
||||
/* Check against hashed DOS name */
|
||||
if (!short_name)
|
||||
{
|
||||
DOSFS_Hash( long_name, tmp_buf, TRUE );
|
||||
short_name = tmp_buf;
|
||||
}
|
||||
if (!strcmpW( dos_name, short_name )) break;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
if (long_buf) WideCharToMultiByte(CP_UNIXCP, 0, long_name, -1, long_buf, long_len, NULL, NULL);
|
||||
if (short_buf)
|
||||
{
|
||||
if (short_name)
|
||||
DOSFS_ToDosDTAFormat( short_name, short_buf );
|
||||
else
|
||||
DOSFS_Hash( long_name, short_buf, FALSE );
|
||||
}
|
||||
TRACE("(%s,%s) -> %s (%s)\n", path->long_name, debugstr_w(name),
|
||||
debugstr_w(long_name), short_buf ? debugstr_w(short_buf) : "***");
|
||||
}
|
||||
else
|
||||
WARN("%s not found in '%s'\n", debugstr_w(name), path->long_name);
|
||||
DOSFS_CloseDir( dir );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_GetPathDrive
|
||||
*
|
||||
* Get the drive specified by a given path name (DOS or Unix format).
|
||||
*/
|
||||
static int DOSFS_GetPathDrive( LPCWSTR *name )
|
||||
{
|
||||
int drive;
|
||||
LPCWSTR p = *name;
|
||||
|
||||
if (*p && (p[1] == ':'))
|
||||
{
|
||||
drive = toupperW(*p) - 'A';
|
||||
*name += 2;
|
||||
}
|
||||
else if (*p == '/') /* Absolute Unix path? */
|
||||
{
|
||||
if ((drive = DRIVE_FindDriveRootW( name )) == -1)
|
||||
{
|
||||
MESSAGE("Warning: %s not accessible from a configured DOS drive\n", debugstr_w(*name) );
|
||||
/* Assume it really was a DOS name */
|
||||
drive = DRIVE_GetCurrentDrive();
|
||||
}
|
||||
}
|
||||
else drive = DRIVE_GetCurrentDrive();
|
||||
|
||||
if (!DRIVE_IsValid(drive))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_DRIVE );
|
||||
return -1;
|
||||
}
|
||||
return drive;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSFS_GetFullName
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last, DOS_FULL_NAME *full )
|
||||
{
|
||||
BOOL found;
|
||||
char *p_l, *root;
|
||||
LPWSTR p_s;
|
||||
static const WCHAR driveA_rootW[] = {'A',':','\\',0};
|
||||
static const WCHAR dos_rootW[] = {'\\',0};
|
||||
|
||||
TRACE("%s (last=%d)\n", debugstr_w(name), check_last );
|
||||
|
||||
if ((!*name) || (*name=='\n'))
|
||||
{ /* error code for Win98 */
|
||||
SetLastError(ERROR_BAD_PATHNAME);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((full->drive = DOSFS_GetPathDrive( &name )) == -1) return FALSE;
|
||||
|
||||
lstrcpynA( 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 */
|
||||
|
||||
strcpyW( full->short_name, driveA_rootW );
|
||||
full->short_name[0] += full->drive;
|
||||
|
||||
if ((*name == '\\') || (*name == '/')) /* Absolute path */
|
||||
{
|
||||
while ((*name == '\\') || (*name == '/')) name++;
|
||||
}
|
||||
else /* Relative path */
|
||||
{
|
||||
lstrcpynA( root + 1, DRIVE_GetUnixCwd( full->drive ),
|
||||
sizeof(full->long_name) - (root - full->long_name) - 1 );
|
||||
if (root[1]) *root = '/';
|
||||
lstrcpynW( full->short_name + 3, DRIVE_GetDosCwd( full->drive ),
|
||||
sizeof(full->short_name)/sizeof(full->short_name[0]) - 3 );
|
||||
}
|
||||
|
||||
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 + strlenW(full->short_name)
|
||||
: full->short_name + 2;
|
||||
found = TRUE;
|
||||
|
||||
while (*name && found)
|
||||
{
|
||||
/* Check for '.' and '..' */
|
||||
|
||||
if (*name == '.')
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure buffers are large enough */
|
||||
|
||||
if ((p_s >= full->short_name + sizeof(full->short_name)/sizeof(full->short_name[0]) - 14) ||
|
||||
(p_l >= full->long_name + sizeof(full->long_name) - 1))
|
||||
{
|
||||
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get the long and short name matching the file name */
|
||||
|
||||
if ((found = DOSFS_FindUnixName( full, name, p_l + 1,
|
||||
sizeof(full->long_name) - (p_l - full->long_name) - 1, p_s + 1 )))
|
||||
{
|
||||
*p_l++ = '/';
|
||||
p_l += strlen(p_l);
|
||||
*p_s++ = '\\';
|
||||
p_s += strlenW(p_s);
|
||||
while (!is_end_of_name(*name)) name++;
|
||||
}
|
||||
else if (!check_last)
|
||||
{
|
||||
*p_l++ = '/';
|
||||
*p_s++ = '\\';
|
||||
while (!is_end_of_name(*name) &&
|
||||
(p_s < full->short_name + sizeof(full->short_name)/sizeof(full->short_name[0]) - 1) &&
|
||||
(p_l < full->long_name + sizeof(full->long_name) - 1))
|
||||
{
|
||||
WCHAR wch;
|
||||
*p_s++ = tolowerW(*name);
|
||||
/* If the drive is case-sensitive we want to create new */
|
||||
/* files in lower-case otherwise we can't reopen them */
|
||||
/* under the same short name. */
|
||||
if (is_case_sensitive) wch = tolowerW(*name);
|
||||
else wch = *name;
|
||||
p_l += WideCharToMultiByte(CP_UNIXCP, 0, &wch, 1, p_l, 2, NULL, NULL);
|
||||
name++;
|
||||
}
|
||||
/* Ignore trailing dots and spaces */
|
||||
while(p_l[-1] == '.' || p_l[-1] == ' ') {
|
||||
--p_l;
|
||||
--p_s;
|
||||
}
|
||||
*p_l = '\0';
|
||||
*p_s = '\0';
|
||||
}
|
||||
while ((*name == '\\') || (*name == '/')) name++;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (check_last)
|
||||
{
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return FALSE;
|
||||
}
|
||||
if (*name) /* Not last */
|
||||
{
|
||||
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (!full->long_name[0]) strcpy( full->long_name, "/" );
|
||||
if (!full->short_name[2]) strcpyW( full->short_name + 2, dos_rootW );
|
||||
TRACE("returning %s = %s\n", full->long_name, debugstr_w(full->short_name) );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MulDiv (KERNEL32.@)
|
||||
* RETURNS
|
||||
* Result of multiplication and division
|
||||
* -1: Overflow occurred or Divisor was 0
|
||||
*/
|
||||
INT WINAPI MulDiv(
|
||||
INT nMultiplicand,
|
||||
INT nMultiplier,
|
||||
INT nDivisor)
|
||||
{
|
||||
LONGLONG ret;
|
||||
|
||||
if (!nDivisor) return -1;
|
||||
|
||||
/* We want to deal with a positive divisor to simplify the logic. */
|
||||
if (nDivisor < 0)
|
||||
{
|
||||
nMultiplicand = - nMultiplicand;
|
||||
nDivisor = -nDivisor;
|
||||
}
|
||||
|
||||
/* If the result is positive, we "add" to round. else, we subtract to round. */
|
||||
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
|
||||
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
|
||||
ret = (((LONGLONG)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
|
||||
else
|
||||
ret = (((LONGLONG)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
|
||||
|
||||
if ((ret > 2147483647) || (ret < -2147483647)) return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DosDateTimeToFileTime (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI DosDateTimeToFileTime( WORD fatdate, WORD fattime, LPFILETIME ft)
|
||||
{
|
||||
struct tm newtm;
|
||||
#ifndef HAVE_TIMEGM
|
||||
struct tm *gtm;
|
||||
time_t time1, time2;
|
||||
#endif
|
||||
|
||||
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;
|
||||
#ifdef HAVE_TIMEGM
|
||||
RtlSecondsSince1970ToTime( timegm(&newtm), (LARGE_INTEGER *)ft );
|
||||
#else
|
||||
time1 = mktime(&newtm);
|
||||
gtm = gmtime(&time1);
|
||||
time2 = mktime(gtm);
|
||||
RtlSecondsSince1970ToTime( 2*time1-time2, (LARGE_INTEGER *)ft );
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FileTimeToDosDateTime (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
|
||||
LPWORD fattime )
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
ULONG t;
|
||||
time_t unixtime;
|
||||
struct tm* tm;
|
||||
|
||||
li.u.LowPart = ft->dwLowDateTime;
|
||||
li.u.HighPart = ft->dwHighDateTime;
|
||||
RtlTimeToSecondsSince1970( &li, &t );
|
||||
unixtime = t;
|
||||
tm = gmtime( &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;
|
||||
}
|
157
files/drive.c
157
files/drive.c
@ -64,8 +64,6 @@ WINE_DECLARE_DEBUG_CHANNEL(file);
|
||||
typedef struct
|
||||
{
|
||||
char *root; /* root dir in Unix format without trailing / */
|
||||
LPWSTR dos_cwd; /* cwd in DOS format without leading or trailing \ */
|
||||
char *unix_cwd; /* cwd in Unix format without leading or trailing / */
|
||||
char *device; /* raw device path */
|
||||
dev_t dev; /* unix device number */
|
||||
ino_t ino; /* unix inode number */
|
||||
@ -75,9 +73,6 @@ typedef struct
|
||||
#define MAX_DOS_DRIVES 26
|
||||
|
||||
static DOSDRIVE DOSDrives[MAX_DOS_DRIVES];
|
||||
static int DRIVE_CurDrive = -1;
|
||||
|
||||
static HTASK16 DRIVE_LastTask = 0;
|
||||
|
||||
/* strdup on the process heap */
|
||||
inline static char *heap_strdup( const char *str )
|
||||
@ -97,7 +92,6 @@ int DRIVE_Init(void)
|
||||
WCHAR driveW[] = {'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e','\\',
|
||||
'W','i','n','e','\\','W','i','n','e','\\',
|
||||
'C','o','n','f','i','g','\\','D','r','i','v','e',' ','A',0};
|
||||
WCHAR drive_env[] = {'=','A',':',0};
|
||||
WCHAR path[MAX_PATHNAME_LEN];
|
||||
char tmp[MAX_PATHNAME_LEN*sizeof(WCHAR) + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
|
||||
struct stat drive_stat_buffer;
|
||||
@ -145,8 +139,6 @@ int DRIVE_Init(void)
|
||||
continue;
|
||||
}
|
||||
drive->root = root;
|
||||
drive->dos_cwd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(drive->dos_cwd[0]));
|
||||
drive->unix_cwd = heap_strdup( "" );
|
||||
drive->device = NULL;
|
||||
drive->dev = drive_stat_buffer.st_dev;
|
||||
drive->ino = drive_stat_buffer.st_ino;
|
||||
@ -210,8 +202,6 @@ int DRIVE_Init(void)
|
||||
goto next;
|
||||
}
|
||||
|
||||
drive->dos_cwd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(drive->dos_cwd[0]));
|
||||
drive->unix_cwd = heap_strdup( "" );
|
||||
drive->device = NULL;
|
||||
drive->dev = drive_stat_buffer.st_dev;
|
||||
drive->ino = drive_stat_buffer.st_ino;
|
||||
@ -238,39 +228,6 @@ int DRIVE_Init(void)
|
||||
next:
|
||||
NtClose( hkey );
|
||||
}
|
||||
|
||||
if (!count && !symlink_count)
|
||||
{
|
||||
MESSAGE("Warning: no valid DOS drive found, check your configuration file.\n" );
|
||||
/* Create a C drive pointing to Unix root dir */
|
||||
DOSDrives[2].root = heap_strdup( "/" );
|
||||
DOSDrives[2].dos_cwd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSDrives[2].dos_cwd[0]));
|
||||
DOSDrives[2].unix_cwd = heap_strdup( "" );
|
||||
DOSDrives[2].device = NULL;
|
||||
DRIVE_CurDrive = 2;
|
||||
}
|
||||
|
||||
/* Make sure the current drive is valid */
|
||||
if (DRIVE_CurDrive == -1)
|
||||
{
|
||||
for (i = 2, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++)
|
||||
{
|
||||
if (drive->root)
|
||||
{
|
||||
DRIVE_CurDrive = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get current working directory info for all drives */
|
||||
for (i = 0; i < MAX_DOS_DRIVES; i++, drive_env[1]++)
|
||||
{
|
||||
if (!GetEnvironmentVariableW(drive_env, path, MAX_PATHNAME_LEN)) continue;
|
||||
/* sanity check */
|
||||
if (toupperW(path[0]) != drive_env[1] || path[1] != ':') continue;
|
||||
DRIVE_Chdir( i, path + 2 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -285,17 +242,6 @@ int DRIVE_IsValid( int drive )
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DRIVE_GetCurrentDrive
|
||||
*/
|
||||
int DRIVE_GetCurrentDrive(void)
|
||||
{
|
||||
TDB *pTask = GlobalLock16(GetCurrentTask());
|
||||
if (pTask && (pTask->curdrive & 0x80)) return pTask->curdrive & ~0x80;
|
||||
return DRIVE_CurDrive;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DRIVE_FindDriveRoot
|
||||
*
|
||||
@ -442,54 +388,6 @@ const char * DRIVE_GetRoot( int drive )
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DRIVE_GetDosCwd
|
||||
*/
|
||||
LPCWSTR DRIVE_GetDosCwd( int drive )
|
||||
{
|
||||
TDB *pTask = GlobalLock16(GetCurrentTask());
|
||||
if (!DRIVE_IsValid( drive )) return NULL;
|
||||
|
||||
/* Check if we need to change the directory to the new task. */
|
||||
if (pTask && (pTask->curdrive & 0x80) && /* The task drive is valid */
|
||||
((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */
|
||||
(DRIVE_LastTask != GetCurrentTask())) /* and the task changed */
|
||||
{
|
||||
static const WCHAR rootW[] = {'\\',0};
|
||||
WCHAR curdirW[MAX_PATH];
|
||||
MultiByteToWideChar(CP_ACP, 0, pTask->curdir, -1, curdirW, MAX_PATH);
|
||||
/* Perform the task-switch */
|
||||
if (!DRIVE_Chdir( drive, curdirW )) DRIVE_Chdir( drive, rootW );
|
||||
DRIVE_LastTask = GetCurrentTask();
|
||||
}
|
||||
return DOSDrives[drive].dos_cwd;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DRIVE_GetUnixCwd
|
||||
*/
|
||||
const char * DRIVE_GetUnixCwd( int drive )
|
||||
{
|
||||
TDB *pTask = GlobalLock16(GetCurrentTask());
|
||||
if (!DRIVE_IsValid( drive )) return NULL;
|
||||
|
||||
/* Check if we need to change the directory to the new task. */
|
||||
if (pTask && (pTask->curdrive & 0x80) && /* The task drive is valid */
|
||||
((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */
|
||||
(DRIVE_LastTask != GetCurrentTask())) /* and the task changed */
|
||||
{
|
||||
static const WCHAR rootW[] = {'\\',0};
|
||||
WCHAR curdirW[MAX_PATH];
|
||||
MultiByteToWideChar(CP_ACP, 0, pTask->curdir, -1, curdirW, MAX_PATH);
|
||||
/* Perform the task-switch */
|
||||
if (!DRIVE_Chdir( drive, curdirW )) DRIVE_Chdir( drive, rootW );
|
||||
DRIVE_LastTask = GetCurrentTask();
|
||||
}
|
||||
return DOSDrives[drive].unix_cwd;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DRIVE_GetDevice
|
||||
*/
|
||||
@ -497,58 +395,3 @@ const char * DRIVE_GetDevice( int drive )
|
||||
{
|
||||
return (DRIVE_IsValid( drive )) ? DOSDrives[drive].device : NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DRIVE_Chdir
|
||||
*/
|
||||
int DRIVE_Chdir( int drive, LPCWSTR path )
|
||||
{
|
||||
DOS_FULL_NAME full_name;
|
||||
WCHAR buffer[MAX_PATHNAME_LEN];
|
||||
LPSTR unix_cwd;
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
TDB *pTask = GlobalLock16(GetCurrentTask());
|
||||
|
||||
buffer[0] = 'A' + drive;
|
||||
buffer[1] = ':';
|
||||
buffer[2] = 0;
|
||||
TRACE("(%s,%s)\n", debugstr_w(buffer), debugstr_w(path) );
|
||||
strncpyW( buffer + 2, path, MAX_PATHNAME_LEN - 2 );
|
||||
buffer[MAX_PATHNAME_LEN - 1] = 0; /* ensure 0 termination */
|
||||
|
||||
if (!DOSFS_GetFullName( buffer, TRUE, &full_name )) return 0;
|
||||
if (!FILE_Stat( full_name.long_name, &info, NULL )) return 0;
|
||||
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return 0;
|
||||
}
|
||||
unix_cwd = full_name.long_name + strlen( DOSDrives[drive].root );
|
||||
while (*unix_cwd == '/') unix_cwd++;
|
||||
|
||||
TRACE("(%c:): unix_cwd=%s dos_cwd=%s\n",
|
||||
'A' + drive, unix_cwd, debugstr_w(full_name.short_name + 3) );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, DOSDrives[drive].dos_cwd );
|
||||
HeapFree( GetProcessHeap(), 0, DOSDrives[drive].unix_cwd );
|
||||
DOSDrives[drive].dos_cwd = HeapAlloc(GetProcessHeap(), 0, (strlenW(full_name.short_name) - 2) * sizeof(WCHAR));
|
||||
strcpyW(DOSDrives[drive].dos_cwd, full_name.short_name + 3);
|
||||
DOSDrives[drive].unix_cwd = heap_strdup( unix_cwd );
|
||||
|
||||
if (drive == DRIVE_CurDrive)
|
||||
{
|
||||
UNICODE_STRING dirW;
|
||||
|
||||
RtlInitUnicodeString( &dirW, full_name.short_name );
|
||||
RtlSetCurrentDirectory_U( &dirW );
|
||||
}
|
||||
|
||||
if (pTask && (pTask->curdrive & 0x80) &&
|
||||
((pTask->curdrive & ~0x80) == drive))
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, 0, full_name.short_name + 2, -1,
|
||||
pTask->curdir, sizeof(pTask->curdir), NULL, NULL);
|
||||
DRIVE_LastTask = GetCurrentTask();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
95
files/file.c
95
files/file.c
@ -80,14 +80,6 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||
|
||||
#if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
|
||||
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
|
||||
|
||||
#define SECSPERDAY 86400
|
||||
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_ConvertOFMode
|
||||
@ -551,93 +543,6 @@ static void FILE_FillInfo( struct stat *st, BY_HANDLE_FILE_INFORMATION *info )
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_show_dot_files_option
|
||||
*/
|
||||
static BOOL get_show_dot_files_option(void)
|
||||
{
|
||||
static const WCHAR WineW[] = {'M','a','c','h','i','n','e','\\',
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'W','i','n','e','\\','W','i','n','e','\\',
|
||||
'C','o','n','f','i','g','\\','W','i','n','e',0};
|
||||
static const WCHAR ShowDotFilesW[] = {'S','h','o','w','D','o','t','F','i','l','e','s',0};
|
||||
|
||||
char tmp[80];
|
||||
HKEY hkey;
|
||||
DWORD dummy;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING nameW;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &nameW;
|
||||
attr.Attributes = 0;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
RtlInitUnicodeString( &nameW, WineW );
|
||||
|
||||
if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ))
|
||||
{
|
||||
RtlInitUnicodeString( &nameW, ShowDotFilesW );
|
||||
if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
|
||||
{
|
||||
WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
|
||||
ret = IS_OPTION_TRUE( str[0] );
|
||||
}
|
||||
NtClose( hkey );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_Stat
|
||||
*
|
||||
* Stat a Unix path name. Return TRUE if OK.
|
||||
*/
|
||||
BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info, BOOL *is_symlink_ptr )
|
||||
{
|
||||
struct stat st;
|
||||
int is_symlink;
|
||||
LPCSTR p;
|
||||
|
||||
if (lstat( unixName, &st ) == -1)
|
||||
{
|
||||
FILE_SetDosError();
|
||||
return FALSE;
|
||||
}
|
||||
is_symlink = S_ISLNK(st.st_mode);
|
||||
if (is_symlink)
|
||||
{
|
||||
/* do a "real" stat to find out
|
||||
about the type of the symlink destination */
|
||||
if (stat( unixName, &st ) == -1)
|
||||
{
|
||||
FILE_SetDosError();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill in the information we gathered so far */
|
||||
FILE_FillInfo( &st, info );
|
||||
|
||||
/* and now see if this is a hidden file, based on the name */
|
||||
p = strrchr( unixName, '/');
|
||||
p = p ? p + 1 : unixName;
|
||||
if (*p == '.' && *(p+1) && (*(p+1) != '.' || *(p+2)))
|
||||
{
|
||||
static int show_dot_files = -1;
|
||||
if (show_dot_files == -1)
|
||||
show_dot_files = get_show_dot_files_option();
|
||||
if (!show_dot_files)
|
||||
info->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
if (is_symlink_ptr) *is_symlink_ptr = is_symlink;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetFileInformationByHandle (KERNEL32.@)
|
||||
*/
|
||||
|
@ -27,38 +27,18 @@
|
||||
|
||||
#define MAX_PATHNAME_LEN 1024
|
||||
|
||||
/* Definition of a full DOS file name */
|
||||
typedef struct
|
||||
{
|
||||
char long_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */
|
||||
WCHAR short_name[MAX_PATHNAME_LEN]; /* Short pathname in DOS 8.3 format */
|
||||
int drive;
|
||||
} DOS_FULL_NAME;
|
||||
|
||||
/* files/file.c */
|
||||
extern void FILE_SetDosError(void);
|
||||
extern BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info, BOOL *is_symlink );
|
||||
extern HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
|
||||
LPSECURITY_ATTRIBUTES sa, DWORD creation,
|
||||
DWORD attributes, HANDLE template );
|
||||
|
||||
/* files/directory.c */
|
||||
extern int DIR_Init(void);
|
||||
|
||||
/* files/dos_fs.c */
|
||||
extern BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last, DOS_FULL_NAME *full );
|
||||
|
||||
/* drive.c */
|
||||
extern int DRIVE_Init(void);
|
||||
extern int DRIVE_IsValid( int drive );
|
||||
extern int DRIVE_GetCurrentDrive(void);
|
||||
extern int DRIVE_FindDriveRoot( const char **path );
|
||||
extern int DRIVE_FindDriveRootW( LPCWSTR *path );
|
||||
extern const char * DRIVE_GetRoot( int drive );
|
||||
extern LPCWSTR DRIVE_GetDosCwd( int drive );
|
||||
extern const char * DRIVE_GetUnixCwd( int drive );
|
||||
extern const char * DRIVE_GetDevice( int drive );
|
||||
extern int DRIVE_Chdir( int drive, LPCWSTR path );
|
||||
|
||||
/* vxd.c */
|
||||
extern HANDLE VXD_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa );
|
||||
|
Loading…
Reference in New Issue
Block a user