Exemplo n.º 1
0
/* Convert an utf-8 file name to NT file name, return converted name length in bytes, no NULL terminator is appended */
static int filename_to_nt_pathname(const char *filename, WCHAR *buf, int buf_size)
{
    if (buf_size < 4)
        return 0;
    buf[0] = L'\\';
    buf[1] = L'?';
    buf[2] = L'?';
    buf[3] = L'\\';
    buf += 4;
    buf_size -= 4;
    int out_size = 4;
    int len = (DWORD)GetCurrentDirectoryW(buf_size, buf);
    buf += len;
    out_size += len;
    buf_size -= len;
    if (filename[0] == 0)
        return out_size;
    *buf++ = L'\\';
    out_size++;
    buf_size--;
    int fl = utf8_to_utf16_filename(filename, strlen(filename), buf, buf_size);
    if (fl == 0)
        return 0;
    return out_size + fl;
}
Exemplo n.º 2
0
Arquivo: winfs.c Projeto: xwlan/flinux
/* Convert an utf-8 file name to NT file name, return converted name length in characters, no NULL terminator is appended */
static int filename_to_nt_pathname(const char *filename, WCHAR *buf, int buf_size)
{
	HANDLE basedir_handle = CreateFileW(L".", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
		OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
	if (basedir_handle == INVALID_HANDLE_VALUE)
		return 0;
	WCHAR basedir[PATH_MAX];
	DWORD basedir_len = GetFinalPathNameByHandleW(basedir_handle, basedir, PATH_MAX, FILE_NAME_NORMALIZED);
	CloseHandle(basedir_handle);
	if (basedir_len > PATH_MAX)
		return 0;
	basedir[1] = L'?';

	if (buf_size < basedir_len)
		return 0;
	memcpy(buf, basedir, basedir_len * sizeof(WCHAR));
	buf += basedir_len;
	int out_size = basedir_len;
	buf_size -= basedir_len;
	if (filename[0] == 0)
		return out_size;
	if (buf_size < 1)
		return 0;
	*buf++ = L'\\';
	out_size++;
	buf_size--;
	int fl = utf8_to_utf16_filename(filename, strlen(filename), buf, buf_size);
	if (fl == 0)
		return 0;
	return out_size + fl;
}
Exemplo n.º 3
0
static int winfs_rmdir(struct mount_point *mp, const char *pathname)
{
	WCHAR wpathname[PATH_MAX];
	if (utf8_to_utf16_filename(pathname, strlen(pathname) + 1, wpathname, PATH_MAX) <= 0)
		return -L_ENOENT;
	if (!RemoveDirectoryW(wpathname))
	{
		log_warning("RemoveDirectoryW() failed, error code: %d", GetLastError());
		return -L_ENOENT;
	}
	return 0;
}
Exemplo n.º 4
0
static int winfs_mkdir(struct mount_point *mp, const char *pathname, int mode)
{
	WCHAR wpathname[PATH_MAX];

	if (utf8_to_utf16_filename(pathname, strlen(pathname) + 1, wpathname, PATH_MAX) <= 0)
		return -L_ENOENT;
	if (!CreateDirectoryW(wpathname, NULL))
	{
		DWORD err = GetLastError();
		if (err == ERROR_FILE_EXISTS || err == ERROR_ALREADY_EXISTS)
		{
			log_warning("File already exists.");
			return -L_EEXIST;
		}
		log_warning("CreateDirectoryW() failed, error code: %d", GetLastError());
		return -L_ENOENT;
	}
	return 0;
}
Exemplo n.º 5
0
/* Convert an utf-8 file name to NT file name, return converted name length in characters, no NULL terminator is appended */
static int filename_to_nt_pathname(struct mount_point *mp, const char *filename, WCHAR *buf, int buf_size)
{
	if (buf_size < mp->win_path_len)
		return 0;
	memcpy(buf, mp->win_path, mp->win_path_len * sizeof(WCHAR));
	buf += mp->win_path_len;
	int out_size = mp->win_path_len;
	buf_size -= mp->win_path_len;
	if (filename[0] == 0)
		return out_size;
	if (buf_size < 1)
		return 0;
	*buf++ = L'\\';
	out_size++;
	buf_size--;
	int fl = utf8_to_utf16_filename(filename, strlen(filename), buf, buf_size);
	if (fl < 0)
		return 0;
	return out_size + fl;
}
Exemplo n.º 6
0
static int winfs_symlink(const char *target, const char *linkpath)
{
    HANDLE handle;
    WCHAR wlinkpath[PATH_MAX];

    if (utf8_to_utf16_filename(linkpath, strlen(linkpath) + 1, wlinkpath, PATH_MAX) <= 0)
        return -ENOENT;

    log_info("CreateFileW(): %s\n", linkpath);
    handle = CreateFileW(wlinkpath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_NEW, FILE_ATTRIBUTE_SYSTEM, NULL);
    if (handle == INVALID_HANDLE_VALUE)
    {
        DWORD err = GetLastError();
        if (err == ERROR_FILE_EXISTS || err == ERROR_ALREADY_EXISTS)
        {
            log_warning("File already exists.\n");
            return -EEXIST;
        }
        log_warning("CreateFileW() failed, error code: %d.\n", GetLastError());
        return -ENOENT;
    }
    DWORD num_written;
    if (!WriteFile(handle, WINFS_SYMLINK_HEADER, WINFS_SYMLINK_HEADER_LEN, &num_written, NULL) || num_written < WINFS_SYMLINK_HEADER_LEN)
    {
        log_warning("WriteFile() failed, error code: %d.\n", GetLastError());
        CloseHandle(handle);
        return -EIO;
    }
    DWORD targetlen = strlen(target);
    if (!WriteFile(handle, target, targetlen, &num_written, NULL) || num_written < targetlen)
    {
        log_warning("WriteFile() failed, error code: %d.\n", GetLastError());
        CloseHandle(handle);
        return -EIO;
    }
    CloseHandle(handle);
    return 0;
}
Exemplo n.º 7
0
static int winfs_open(const char *pathname, int flags, int mode, struct file **fp, char *target, int buflen)
{
    /* TODO: mode */
    DWORD desiredAccess, shareMode, creationDisposition;
    HANDLE handle;
    FILE_ATTRIBUTE_TAG_INFO attributeInfo;
    WCHAR wpathname[PATH_MAX];
    struct winfs_file *file;
    int pathlen = strlen(pathname);

    if (utf8_to_utf16_filename(pathname, pathlen + 1, wpathname, PATH_MAX) <= 0)
        return -ENOENT;
    if (wpathname[0] == 0)
    {
        /* CreateFile() does not accept empty filename. */
        wpathname[0] = '.';
        wpathname[1] = 0;
    }

    if (flags & O_PATH)
        desiredAccess = 0;
    else if (flags & O_RDWR)
        desiredAccess = GENERIC_READ | GENERIC_WRITE;
    else if (flags & O_WRONLY)
        desiredAccess = GENERIC_WRITE;
    else
        desiredAccess = GENERIC_READ;
    if (flags & __O_DELETE)
        desiredAccess |= DELETE;
    shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
    creationDisposition;
    if (flags & O_EXCL)
        creationDisposition = CREATE_NEW;
    else if (flags & O_CREAT)
        creationDisposition = OPEN_ALWAYS;
    else
        creationDisposition = OPEN_EXISTING;
    //log_debug("CreateFileW(): %s\n", pathname);
    SECURITY_ATTRIBUTES attr;
    attr.nLength = sizeof(SECURITY_ATTRIBUTES);
    attr.lpSecurityDescriptor = NULL;
    attr.bInheritHandle = (fp != NULL);
    handle = CreateFileW(wpathname, desiredAccess, shareMode, &attr, creationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (handle == INVALID_HANDLE_VALUE)
    {
        DWORD err = GetLastError();
        if (err == ERROR_FILE_EXISTS || err == ERROR_ALREADY_EXISTS)
        {
            log_warning("File already exists.\n");
            return -EEXIST;
        }
        else
        {
            log_warning("Unhandled CreateFileW() failure, error code: %d, returning ENOENT.\n", GetLastError());
            return -ENOENT;
        }
    }
    if (!GetFileInformationByHandleEx(handle, FileAttributeTagInfo, &attributeInfo, sizeof(attributeInfo)))
    {
        CloseHandle(handle);
        return -EIO;
    }
    /* Test if the file is a symlink */
    int is_symlink = 0;
    if (attributeInfo.FileAttributes != INVALID_FILE_ATTRIBUTES && (attributeInfo.FileAttributes & FILE_ATTRIBUTE_SYSTEM))
    {
        log_info("The file has system flag set.\n");
        if (!(desiredAccess & GENERIC_READ))
        {
            /* We need to get a readable handle */
            log_info("But the handle does not have READ access, try reopening file...\n");
            HANDLE read_handle = ReOpenFile(handle, desiredAccess | GENERIC_READ, shareMode, FILE_FLAG_BACKUP_SEMANTICS);
            if (read_handle == INVALID_HANDLE_VALUE)
            {
                log_warning("Reopen file failed, error code %d. Assume not symlink.\n", GetLastError());
                goto after_symlink_test;
            }
            CloseHandle(handle);
            log_info("Reopen succeeded.\n");
            handle = read_handle;
        }
        if (winfs_read_symlink(handle, target, buflen) > 0)
        {
            if (!(flags & O_NOFOLLOW))
            {
                CloseHandle(handle);
                return 1;
            }
            if (!(flags & O_PATH))
            {
                CloseHandle(handle);
                log_info("Specified O_NOFOLLOW but not O_PATH, returning ELOOP.\n");
                return -ELOOP;
            }
            is_symlink = 1;
        }
        log_info("Opening file directly.\n");
    }
    else if (attributeInfo.FileAttributes != INVALID_FILE_ATTRIBUTES && !(attributeInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (flags & O_DIRECTORY))
    {
        log_warning("Not a directory.\n");
        return -ENOTDIR;
    }

after_symlink_test:
    if (!is_symlink && (flags & O_TRUNC) && ((flags & O_WRONLY) || (flags & O_RDWR)))
    {
        /* Truncate the file */
        FILE_END_OF_FILE_INFORMATION info;
        info.EndOfFile.QuadPart = 0;
        IO_STATUS_BLOCK status_block;
        NTSTATUS status = NtSetInformationFile(handle, &status_block, &info, sizeof(info), FileEndOfFileInformation);
        if (!NT_SUCCESS(status))
            log_error("NtSetInformationFile() failed, status: %x\n", status);
    }

    if (fp)
    {
        file = (struct winfs_file *)kmalloc(sizeof(struct winfs_file) + pathlen);
        file->base_file.op_vtable = &winfs_ops;
        file->base_file.ref = 1;
        file->base_file.flags = flags;
        file->handle = handle;
        file->restart_scan = 1;
        file->pathlen = pathlen;
        memcpy(file->pathname, pathname, pathlen);
        *fp = (struct file *)file;
    }
    else
        CloseHandle(handle);
    return 0;
}