Skip to content
Snippets Groups Projects
dos_fs.c 74.6 KiB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
/*
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
 */

Alexandre Julliard's avatar
Alexandre Julliard committed
#include "config.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <sys/types.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <ctype.h>
#include <dirent.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <errno.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <sys/errno.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <fcntl.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_IOCTL_H
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <sys/ioctl.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <time.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed

#define NONAMELESSUNION
#define NONAMELESSSTRUCT
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "winerror.h"
#include "wingdi.h"

#include "wine/unicode.h"
#include "wine/winbase16.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "drive.h"
#include "file.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "heap.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "msdos.h"
#include "wine/server.h"
Alexandre Julliard's avatar
Alexandre Julliard committed

WINE_DEFAULT_DEBUG_CHANNEL(dosfs);
WINE_DECLARE_DEBUG_CHANNEL(file);
Alexandre Julliard's avatar
Alexandre Julliard committed
/* Define the VFAT ioctl to get both short and long file names */
Alexandre Julliard's avatar
Alexandre Julliard committed
/* FIXME: is it possible to get this to work on other systems? */
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef linux
Alexandre Julliard's avatar
Alexandre Julliard committed
/* 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

Alexandre Julliard's avatar
Alexandre Julliard committed
#else   /* linux */
#undef VFAT_IOCTL_READDIR_BOTH  /* just in case... */
#endif  /* linux */
Alexandre Julliard's avatar
Alexandre Julliard committed

#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')

Alexandre Julliard's avatar
Alexandre Julliard committed
/* Chars we don't want to see in DOS file names */
Alexandre Julliard's avatar
Alexandre Julliard committed
#define INVALID_DOS_CHARS  "*?<>|\"+=,;[] \345"
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
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
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
typedef struct
{
    WCHAR names[1];
Alexandre Julliard's avatar
Alexandre Julliard committed
} DOS_DIR;

Alexandre Julliard's avatar
Alexandre Julliard committed
/* Info structure for FindFirstFile handle */
typedef struct
{
    char *path; /* unix path */
    LPWSTR long_mask;
    LPWSTR short_mask;
Alexandre Julliard's avatar
Alexandre Julliard committed
    BYTE  attr;
    int   drive;
    int   cur_pos;
    union
    {
        DOS_DIR *dos_dir;
        SMB_DIR *smb_dir;
    } u;
Alexandre Julliard's avatar
Alexandre Julliard committed
} FIND_FIRST_INFO;


static WINE_EXCEPTION_FILTER(page_fault)
{
    if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
        return EXCEPTION_EXECUTE_HANDLER;
    return EXCEPTION_CONTINUE_SEARCH;
}

Alexandre Julliard's avatar
Alexandre Julliard committed

/***********************************************************************
 *           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 )
Alexandre Julliard's avatar
Alexandre Julliard committed
{
Alexandre Julliard's avatar
Alexandre Julliard committed
    static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
    const WCHAR *p = name;
Alexandre Julliard's avatar
Alexandre Julliard committed
    const char *invalid = ignore_case ? (invalid_chars + 26) : invalid_chars;
Alexandre Julliard's avatar
Alexandre Julliard committed
    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 */
Alexandre Julliard's avatar
Alexandre Julliard committed
        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...