Newer
Older
/*
* 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
#ifdef HAVE_SYS_ERRNO_H
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "ntstatus.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "wine/unicode.h"
#include "wine/winbase16.h"
#include "winternl.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? */
/* 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] )
Michal Janusz Miroslaw
committed
/* 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 */
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
static const DOS_DEVICE DOSFS_Devices[] =
/* name, device flags (see Int 21/AX=0x4400) */
{
{ {'C','O','N',0}, 0xc0d3 },
{ {'P','R','N',0}, 0xa0c0 },
{ {'N','U','L',0}, 0x80c4 },
{ {'A','U','X',0}, 0x80c0 },
{ {'L','P','T','1',0}, 0xa0c0 },
{ {'L','P','T','2',0}, 0xa0c0 },
{ {'L','P','T','3',0}, 0xa0c0 },
{ {'L','P','T','4',0}, 0xc0d3 },
{ {'C','O','M','1',0}, 0x80c0 },
{ {'C','O','M','2',0}, 0x80c0 },
{ {'C','O','M','3',0}, 0x80c0 },
{ {'C','O','M','4',0}, 0x80c0 },
{ {'S','C','S','I','M','G','R','$',0}, 0xc0c0 },
{ {'H','P','S','C','A','N',0}, 0xc0c0 },
{ {'E','M','M','X','X','X','X','0',0}, 0x0000 }
static const WCHAR devW[] = {'\\','D','e','v','i','c','e','\\',0};
static const WCHAR dosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
static const WCHAR auxW[] = {'A','U','X',0};
static const WCHAR comW[] = {'C','O','M',0};
static const WCHAR lptW[] = {'L','P','T',0};
static const WCHAR nulW[] = {'N','U','L',0};
static const WCHAR nullW[] = {'N','u','l','l',0};
static const WCHAR parW[] = {'P','a','r','a','l','l','e','l',0};
static const WCHAR serW[] = {'S','e','r','i','a','l',0};
static const WCHAR oneW[] = {'1',0};
/*
* Directory info for DOSFS_ReadDir
* contains the names of *all* the files in the directory
*/
/* Info structure for FindFirstFile handle */
typedef struct
{
char *path; /* unix path */
LPWSTR long_mask;
LPWSTR short_mask;
CRITICAL_SECTION cs;
union
{
DOS_DIR *dos_dir;
SMB_DIR *smb_dir;
} u;
static WINE_EXCEPTION_FILTER(page_fault)
{
if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
/***********************************************************************
* 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, int ignore_case )
static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
const char *invalid = ignore_case ? (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))
Loading
Loading full blame...