Example #1
0
/**
 * main - Begin here
 *
 * Start from here.
 *
 * Return:  0  Success, the program worked
 *	    1  Error, something went wrong
 */
int main(int argc, char **argv)
{
	unsigned long mnt_flags = 0;
	int result = 0;
	ntfs_volume *vol;

	ntfs_log_set_handler(ntfs_log_handler_outerr);

	if (!parse_options(argc, argv))
		return 1;

	utils_set_locale();

	if (!opts.label)
		opts.noaction++;

	vol = utils_mount_volume(opts.device,
			(opts.noaction ? MS_RDONLY : 0) |
			(opts.force ? MS_RECOVER : 0));
	if (!vol)
		return 1;

	if (opts.label)
		result = change_label(vol, mnt_flags, opts.label, opts.force);
	else
		result = print_label(vol, mnt_flags);

	ntfs_umount(vol, FALSE);
	return result;
}
Example #2
0
static void dir_partition_ntfs_close(dir_data_t *dir_data)
{
  struct ntfs_dir_struct *ls=(struct ntfs_dir_struct*)dir_data->private_dir_data;
  /* ntfs_umount() will invoke ntfs_device_free() for us. */
  ntfs_umount(ls->vol, FALSE);
  free(ls->my_data);
#ifdef HAVE_ICONV
  if (ls->cd != (iconv_t)(-1))
    iconv_close(ls->cd);
#endif
  free(ls);
}
Example #3
0
/**
 * main - Begin here
 *
 * Start from here.
 *
 * Return:  0  Success, the program worked
 *	    1  Error, something went wrong
 */
int main(int argc, char **argv)
{
	unsigned long mnt_flags = 0;
	int result = 0;
	ntfs_volume *vol;

	ntfs_log_set_handler(ntfs_log_handler_outerr);

	result = parse_options(argc, argv);
	if (result >= 0)
		return (result);

	result = 0;
	utils_set_locale();

	if ((opts.label || opts.new_serial)
	    && !opts.noaction
	    && !opts.force
	    && !ntfs_check_if_mounted(opts.device, &mnt_flags)
	    && (mnt_flags & NTFS_MF_MOUNTED)) {
		ntfs_log_error("Cannot make changes to a mounted device\n");
		result = 1;
		goto abort;
	}

	if (!opts.label && !opts.new_serial)
		opts.noaction++;

	vol = utils_mount_volume(opts.device,
			(opts.noaction ? NTFS_MNT_RDONLY : 0) |
			(opts.force ? NTFS_MNT_RECOVER : 0));
	if (!vol)
		return 1;

	if (opts.new_serial) {
		result = set_new_serial(vol);
		if (result)
			goto unmount;
	} else {
		if (opts.verbose)
			result = print_serial(vol);
	}
	if (opts.label)
		result = change_label(vol, opts.label);
	else
		result = print_label(vol, mnt_flags);

unmount :
	ntfs_umount(vol, FALSE);
abort :
		/* "result" may be a negative reply of a library function */
	return (result ? 1 : 0);
}
Example #4
0
static void err_exit(ntfs_volume *vol, const char *fmt, ...)
{
	va_list ap;

	fprintf(stderr, "ERROR: ");
	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
	fprintf(stderr, "Aborting...\n");
	if (vol && ntfs_umount(vol, 0))
		fprintf(stderr, "Warning: Could not umount %s\n", dev_name);
	exit(1);
}
Example #5
0
float
fs_identify_partition(int fd, partition_data *partition, void **_cookie)
{
	NTFS_BOOT_SECTOR boot;
	identify_cookie *cookie;
	ntfs_volume *ntVolume;
	uint8 *buf = (uint8*)&boot;
	char devpath[256];

	// read in the boot sector
	ERRPRINT("fs_identify_partition: read in the boot sector\n");
	if (read_pos(fd, 0, (void*)&boot, 512) != 512) {
		return -1;
	}

	// check boot signature
	if ((buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) && buf[0x15] == 0xf8)
		return -1;

	// check boot signature NTFS
	if (memcmp(buf + 3, "NTFS    ", 8) != 0)
		return -1;

	// get path for device
	if (!ioctl(fd, B_GET_PATH_FOR_DEVICE, devpath))
		return -1;

	// try mount
	ntVolume = utils_mount_volume(devpath, MS_RDONLY, true);
	if (!ntVolume)
		return -1;

	// allocate identify_cookie
	cookie = (identify_cookie *)malloc(sizeof(identify_cookie));
	if (!cookie)
		return -1;

	memcpy(&cookie->boot, &boot, 512);

	strcpy(cookie->label, "NTFS Volume");

	if (ntVolume->vol_name && ntVolume->vol_name[0] != '\0')
		strcpy(cookie->label, ntVolume->vol_name);

	ntfs_umount(ntVolume, true);

	*_cookie = cookie;

	return 0.8f;
}
Example #6
0
static int ntfs_open(const char *device)
{
	ntfs_volume *vol;
	unsigned long flags = 0;
	int ret = NTFS_VOLUME_OK;
	
	if (opts.probetype == PROBE_READONLY)
		flags |= MS_RDONLY;

	vol = ntfs_mount(device, flags);
	if (!vol)
		ret = ntfs_volume_error(errno);

	ntfs_umount(vol, FALSE);

	return ret;
}
Example #7
0
void
fstyp_mod_fini(fstyp_mod_handle_t handle)
{
    fstyp_ntfs_t *h = (fstyp_ntfs_t *)handle;
    
    free(h->dev->d_private);
    
    if(h->vol != NULL) {
        ntfs_umount(h->vol, 0);
    }
        
    if (h->attr != NULL) {
        nvlist_free(h->attr);
        h->attr = NULL;
    }
    
    free(h);
}
Example #8
0
/**
 * main - Begin here
 *
 * Start from here.
 *
 * Return:  0  Success, the program worked
 *	    1  Error, something went wrong
 */
int main(int argc, char *argv[])
{
	ntfs_volume *vol;
	ntfs_inode *inode;
	ATTR_TYPES attr;
	int result = 1;

	ntfs_log_set_handler(ntfs_log_handler_stderr);

	if (!parse_options(argc, argv))
		return 1;

	utils_set_locale();

	vol = utils_mount_volume(opts.device, MS_RDONLY |
			(opts.force ? MS_RECOVER : 0));
	if (!vol) {
		ntfs_log_perror("ERROR: couldn't mount volume");
		return 1;
	}

	if (opts.inode != -1)
		inode = ntfs_inode_open(vol, opts.inode);
	else
		inode = ntfs_pathname_to_inode(vol, NULL, opts.file);

	if (!inode) {
		ntfs_log_perror("ERROR: Couldn't open inode");
		return 1;
	}

	attr = AT_DATA;
	if (opts.attr != cpu_to_le32(-1))
		attr = opts.attr;

	result = cat(vol, inode, attr, opts.attr_name, opts.attr_name_len);

	ntfs_inode_close(inode);
	ntfs_umount(vol, FALSE);

	return result;
}
Example #9
0
void ntfsUnmount (const char *name, bool force)
{
    ntfs_vd *vd = NULL;

    // Get the devices volume descriptor
    vd = ntfsGetVolume(name);
    if (!vd)
        return;

    // Remove the device from the devoptab table
    ntfsRemoveDevice(name);

    // Deinitialise the volume descriptor
    ntfsDeinitVolume(vd);

    // Unmount the volume
    ntfs_umount(vd->vol, force);

    // Free the volume descriptor
    ntfs_free(vd);

    return;
}
Example #10
0
bool ntfsMount (const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags)
{
    ntfs_vd *vd = NULL;
    gekko_fd *fd = NULL;

    // Sanity check
    if (!name || !interface) {
        errno = EINVAL;
        return -1;
    }

    // Initialise ntfs-3g
    ntfsInit();

    // Check that the requested mount name is free
    if (ntfsGetDevice(name, false)) {
        errno = EADDRINUSE;
        return false;
    }

    // Check that we can at least read from this device
    if (!(interface->features & FEATURE_MEDIUM_CANREAD)) {
        errno = EPERM;
        return false;
    }

    // Allocate the volume descriptor
    vd = (ntfs_vd*)ntfs_alloc(sizeof(ntfs_vd));
    if (!vd) {
        errno = ENOMEM;
        return false;
    }

    // Setup the volume descriptor
    vd->id = interface->ioType;
    vd->flags = 0;
    vd->uid = 0;
    vd->gid = 0;
    vd->fmask = 0;
    vd->dmask = 0;
    vd->atime = ((flags & NTFS_UPDATE_ACCESS_TIMES) ? ATIME_ENABLED : ATIME_DISABLED);
    vd->showHiddenFiles = (flags & NTFS_SHOW_HIDDEN_FILES);
    vd->showSystemFiles = (flags & NTFS_SHOW_SYSTEM_FILES);

    // Allocate the device driver descriptor
    fd = (gekko_fd*)ntfs_alloc(sizeof(gekko_fd));
    if (!fd) {
        ntfs_free(vd);
        errno = ENOMEM;
        return false;
    }

    // Setup the device driver descriptor
    fd->interface = interface;
    fd->startSector = startSector;
    fd->sectorSize = 0;
    fd->sectorCount = 0;
    fd->cachePageCount = cachePageCount;
    fd->cachePageSize = cachePageSize;

    // Allocate the device driver
    vd->dev = ntfs_device_alloc(name, 0, &ntfs_device_gekko_io_ops, fd);
    if (!vd->dev) {
        ntfs_free(fd);
        ntfs_free(vd);
        return false;
    }

    // Build the mount flags
    if (flags & NTFS_READ_ONLY)
        vd->flags |= MS_RDONLY;
    else
    {
        if (!(interface->features & FEATURE_MEDIUM_CANWRITE))
            vd->flags |= MS_RDONLY;
        if ((interface->features & FEATURE_MEDIUM_CANREAD) && (interface->features & FEATURE_MEDIUM_CANWRITE))
            vd->flags |= MS_EXCLUSIVE;
    }
    if (flags & NTFS_RECOVER)
        vd->flags |= MS_RECOVER;
    if (flags & NTFS_IGNORE_HIBERFILE)
        vd->flags |= MS_IGNORE_HIBERFILE;

    if (vd->flags & MS_RDONLY)
        ntfs_log_debug("Mounting \"%s\" as read-only\n", name);

    // Mount the device
    vd->vol = ntfs_device_mount(vd->dev, vd->flags);
    if (!vd->vol) {
        switch(ntfs_volume_error(errno)) {
        case NTFS_VOLUME_NOT_NTFS:
            errno = EINVALPART;
            break;
        case NTFS_VOLUME_CORRUPT:
            errno = EINVALPART;
            break;
        case NTFS_VOLUME_HIBERNATED:
            errno = EHIBERNATED;
            break;
        case NTFS_VOLUME_UNCLEAN_UNMOUNT:
            errno = EDIRTY;
            break;
        default:
            errno = EINVAL;
            break;
        }
        ntfs_device_free(vd->dev);
        ntfs_free(vd);
        return false;
    }

    // Initialise the volume descriptor
    if (ntfsInitVolume(vd)) {
        ntfs_umount(vd->vol, true);
        ntfs_free(vd);
        return false;
    }

    // Add the device to the devoptab table
    if (ntfsAddDevice(name, vd)) {
        ntfsDeinitVolume(vd);
        ntfs_umount(vd->vol, true);
        ntfs_free(vd);
        return false;
    }

    return true;
}
Example #11
0
/**
 * main - Begin here
 *
 * Start from here.
 *
 * Return:  0  Success, the program worked
 *	    1  Error, something went wrong
 */
int main(int argc, char *argv[])
{
    u8 *pfx_buf;
    char *password;
    ntfs_rsa_private_key rsa_key;
    ntfs_volume *vol;
    ntfs_inode *inode;
    ntfs_fek *fek;
    unsigned pfx_size;
    int res;
    NTFS_DF_TYPES df_type;
    char thumbprint[NTFS_SHA1_THUMBPRINT_SIZE];

#ifdef DEBUG
    ntfs_log_set_handler(ntfs_log_handler_stderr);
#endif

    if (!parse_options(argc, argv))
        return 1;
    utils_set_locale();

    /* Initialize crypto in ntfs. */
    if (ntfs_crypto_init()) {
        ntfs_log_error("Failed to initialize crypto.  Aborting.\n");
        return 1;
    }
    /* Load the PKCS#12 (.pfx) file containing the user's private key. */
    if (ntfs_pkcs12_load_pfxfile(opts.keyfile, &pfx_buf, &pfx_size)) {
        ntfs_log_error("Failed to load key file.  Aborting.\n");
        ntfs_crypto_deinit();
        return 1;
    }
    /* Ask the user for their password. */
    password = getpass("Enter the password with which the private key was "
                       "encrypted: ");
    if (!password) {
        ntfs_log_perror("Failed to obtain user password");
        free(pfx_buf);
        ntfs_crypto_deinit();
        return 1;
    }
    /* Obtain the user's private RSA key from the key file. */
    rsa_key = ntfs_pkcs12_extract_rsa_key(pfx_buf, pfx_size, password,
                                          thumbprint, sizeof(thumbprint), &df_type);
    /* Destroy the password. */
    memset(password, 0, strlen(password));
    /* No longer need the pfx file contents. */
    free(pfx_buf);
    if (!rsa_key) {
        ntfs_log_error("Failed to extract the private RSA key.\n");
        ntfs_crypto_deinit();
        return 1;
    }
    /* Mount the ntfs volume. */
    vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
                             (opts.force ? NTFS_MNT_RECOVER : 0));
    if (!vol) {
        ntfs_log_error("Failed to mount ntfs volume.  Aborting.\n");
        ntfs_rsa_private_key_release(rsa_key);
        ntfs_crypto_deinit();
        return 1;
    }
    /* Open the encrypted ntfs file. */
    if (opts.inode != -1)
        inode = ntfs_inode_open(vol, opts.inode);
    else
        inode = ntfs_pathname_to_inode(vol, NULL, opts.file);
    if (!inode) {
        ntfs_log_error("Failed to open encrypted file.  Aborting.\n");
        ntfs_umount(vol, FALSE);
        ntfs_rsa_private_key_release(rsa_key);
        ntfs_crypto_deinit();
        return 1;
    }
    /* Obtain the file encryption key of the encrypted file. */
    fek = ntfs_inode_fek_get(inode, rsa_key, thumbprint,
                             sizeof(thumbprint), df_type);
    ntfs_rsa_private_key_release(rsa_key);
    if (fek) {
        res = ntfs_cat_decrypt(inode, fek);
        ntfs_fek_release(fek);
    } else {
        ntfs_log_error("Failed to obtain file encryption key.  "
                       "Aborting.\n");
        res = 1;
    }
    ntfs_inode_close(inode);
    ntfs_umount(vol, FALSE);
    ntfs_crypto_deinit();
    return res;
}
Example #12
0
status_t
fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args,
	ino_t *_rootID)
{
	nspace *ns;
	vnode *newNode = NULL;
	char lockname[32];
	void *handle;
	unsigned long mountFlags = 0;
	status_t result = B_NO_ERROR;

	ERRPRINT("fs_mount - ENTER\n");

	ns = ntfs_malloc(sizeof(nspace));
	if (!ns) {
		result = ENOMEM;
		goto exit;
	}

	*ns = (nspace) {
		.state = NF_FreeClustersOutdate | NF_FreeMFTOutdate,
		.show_sys_files = false,
		.ro = false,
		.flags = 0
	};

	strcpy(ns->devicePath,device);

	sprintf(lockname, "ntfs_lock %lx", ns->id);
	recursive_lock_init_etc(&(ns->vlock), lockname, MUTEX_FLAG_CLONE_NAME);

	handle = load_driver_settings("ntfs");
	ns->show_sys_files = ! (strcasecmp(get_driver_parameter(handle,
		"hide_sys_files", "true", "true"), "true") == 0);
	ns->ro = strcasecmp(get_driver_parameter(handle, "read_only", "false",
		"false"), "false") != 0;
	ns->noatime = strcasecmp(get_driver_parameter(handle, "no_atime", "true",
		"true"), "true") == 0;
	unload_driver_settings(handle);

	if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0) {
		mountFlags |= MS_RDONLY;
		ns->flags |= B_FS_IS_READONLY;
	}

	// TODO: this does not take read-only volumes into account!
	ns->ntvol = utils_mount_volume(device, mountFlags, true);
	if (ns->ntvol != NULL)
		result = B_NO_ERROR;
	else
		result = errno;

	if (result == B_NO_ERROR) {
		*_rootID = FILE_root;
		ns->id = _vol->id;
		_vol->private_volume = (void *)ns;
		_vol->ops = &gNTFSVolumeOps;

		newNode = (vnode*)ntfs_calloc(sizeof(vnode));
		if (newNode == NULL)
			result = ENOMEM;
		else {
			newNode->vnid = *_rootID;
			newNode->parent_vnid = -1;

			result = publish_vnode(_vol, *_rootID, (void*)newNode,
				&gNTFSVnodeOps, S_IFDIR, 0);
			if (result != B_NO_ERROR) {
				free(ns);
				result = EINVAL;
				goto exit;
			} else {
				result = B_NO_ERROR;
				ntfs_mark_free_space_outdated(ns);
				ntfs_calc_free_space(ns);
			}
		}
	}

exit:
	ERRPRINT("fs_mount - EXIT, result code is %s\n", strerror(result));

	return result;
}


status_t
fs_unmount(fs_volume *_vol)
{
	nspace *ns = (nspace*)_vol->private_volume;
	status_t result = B_NO_ERROR;

	ERRPRINT("fs_unmount - ENTER\n");

	ntfs_umount(ns->ntvol, true);

	recursive_lock_destroy(&(ns->vlock));

	free(ns);

	ERRPRINT("fs_unmount - EXIT, result is %s\n", strerror(result));

	return result;
}
Example #13
0
/**
 * main
 */
int main(int argc, char **argv)
{
	unsigned long mnt_flags, ul;
	int err;
	ntfs_inode *ni;
	ntfs_volume *vol;
#ifdef HAVE_WINDOWS_H
	char *unix_name;
#endif

	vol = (ntfs_volume*)NULL;
	ntfs_log_set_handler(ntfs_log_handler_outerr);

	/* Initialize opts to zero / required values. */
	memset(&opts, 0, sizeof(opts));

	/* Parse command line options. */
	parse_options(argc, argv);

	utils_set_locale();

	/* Make sure the file system is not mounted. */
	if (ntfs_check_if_mounted(dev_name, &mnt_flags))
		ntfs_log_perror("Failed to determine whether %s is mounted",
				dev_name);
	else if (mnt_flags & NTFS_MF_MOUNTED) {
		ntfs_log_error("%s is mounted.\n", dev_name);
		if (!opts.force)
			err_exit((ntfs_volume*)NULL, "Refusing to run!\n");
		fprintf(stderr, "ntfsfallocate forced anyway. Hope /etc/mtab "
				"is incorrect.\n");
	}

	/* Mount the device. */
	if (opts.no_action) {
		ntfs_log_quiet("Running in READ-ONLY mode!\n");
		ul = NTFS_MNT_RDONLY;
	} else
		if (opts.force)
			ul = NTFS_MNT_RECOVER;
		else
			ul = 0;
	vol = ntfs_mount(dev_name, ul);
	if (!vol)
		err_exit(vol, "Failed to mount %s: %s\n", dev_name,
			strerror(errno));

	if ((vol->flags & VOLUME_IS_DIRTY) && !opts.force)
		err_exit(vol, "Volume is dirty, please run chkdsk.\n");

	if (ntfs_volume_get_free_space(vol))
		err_exit(vol, "Failed to get free clusters %s: %s\n",
					dev_name, strerror(errno));

	/* Open the specified inode. */
#ifdef HAVE_WINDOWS_H
	unix_name = (char*)malloc(strlen(file_name) + 1);
	if (unix_name) {
		int i;
		for (i=0; file_name[i]; i++)
			if (file_name[i] == '\\')
				unix_name[i] = '/';
			else
				unix_name[i] = file_name[i];
		unix_name[i] = 0;
		ni = ntfs_pathname_to_inode(vol, NULL, unix_name);
		free(unix_name);
	} else
		ni = (ntfs_inode*)NULL;
#else
	ni = ntfs_pathname_to_inode(vol, NULL, file_name);
#endif
	if (!ni)
		err_exit(vol, "Failed to open file \"%s\": %s\n", file_name,
				strerror(errno));
	if (!opts.no_action)
		err = ntfs_fallocate(ni, opt_alloc_offs, opt_alloc_len);

	/* Close the inode. */
	if (ntfs_inode_close(ni)) {
		err = -1;
		err_exit(vol, "Failed to close inode \"%s\" : %s\n", file_name,
				strerror(errno));
	}

	/* Unmount the volume. */
	err = ntfs_umount(vol, 0);
	vol = (ntfs_volume*)NULL;
	if (err)
		ntfs_log_perror("Warning: Failed to umount %s", dev_name);

	/* Free the attribute name if it exists. */
	if (attr_name_len)
		ntfs_ucsfree(attr_name);

	ntfs_log_quiet("ntfsfallocate completed successfully. Have a nice day.\n");
	return 0;
}
Example #14
0
ntfs_vd *ntfsMount (const char *name, struct _NTFS_VOLUME *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags)
{
    ntfs_vd *vd = NULL;
    struct _uefi_fd *fd = NULL;
	const devoptab_t *mnt;

	//Print(L"ntfsMount %a\n", name);

	//CpuBreakpoint();

	// Sanity check
    if (!name || !interface) {
		//Print(L"ntfsMount EINVAL\n");
        errno = EINVAL;
        return false;
    }

    // Initialise ntfs-3g
	ntfsInit();

	mnt = ntfsGetDevice(name, false);

    // Check that the requested mount name is free
    if (mnt) {
		//Print(L"ntfsMount EADDRINUSE\n");
        errno = 99; //EADDRINUSE;
	
		return (ntfs_vd*) mnt->deviceData;	// previous mnt data!
    }


    // Allocate the volume descriptor
    vd = (ntfs_vd*)ntfs_alloc(sizeof(ntfs_vd));
    if (!vd) {
		//Print(L"ntfsMount ENOMEM\n");
        errno = ENOMEM;
        return false;
    }
	else {
		//Print(L"ntfsMount ntfs_vd!\n");
	}

    // Setup the volume descriptor
	//Print(L"vd.id! [%x]\n", vd);
    vd->id = 0;//interface->ioType;
    //Print(L"vd.flags!\n");
	vd->flags = 0;
    vd->uid = 0;
    vd->gid = 0;
    vd->fmask = 0;
    vd->dmask = 0;
    vd->atime = ((flags & NTFS_UPDATE_ACCESS_TIMES) ? ATIME_ENABLED : ATIME_DISABLED);
    vd->showHiddenFiles = (flags & NTFS_SHOW_HIDDEN_FILES);
    vd->showSystemFiles = (flags & NTFS_SHOW_SYSTEM_FILES);

	//Print(L"invoking ntfs_alloc!\n");
    // Allocate the device driver descriptor
    fd = (struct _uefi_fd *)ntfs_alloc(sizeof(struct _uefi_fd));
    if (!fd) {
		//Print(L"ntfsMount ENOMEM(2)\n");
		ntfs_free(vd);
        errno = ENOMEM;
        return false;
    }
	else
	{
		//Print(L"ntfs_alloc uefi_fd\n");
	}

    // Setup the device driver descriptor
    fd->interface = interface;
    fd->startSector = startSector;
    fd->sectorSize = 0x200;
	fd->sectorCount = 0x200;
    fd->cachePageCount = cachePageCount;
    fd->cachePageSize = cachePageSize;

    // Allocate the device driver
    vd->dev = ntfs_device_alloc(name, 0, &ntfs_device_uefi_io_ops, fd);
    if (!vd->dev) {
		//Print(L"ntfsMount ntfs_device_alloc failed\n");
        ntfs_free(fd);
        ntfs_free(vd);
        return false;
    }
	//Print(L"ntfs_device_alloc success\n");

    // Build the mount flags
    if (flags & NTFS_READ_ONLY)
    	vd->flags |= NTFS_MNT_RDONLY;
    
    if (flags & NTFS_RECOVER)
        vd->flags |= NTFS_MNT_RECOVER;
    if (flags & NTFS_IGNORE_HIBERFILE)
        vd->flags |= NTFS_MNT_IGNORE_HIBERFILE;

    if (vd->flags & NTFS_MNT_RDONLY)
        ntfs_log_debug("Mounting \"%s\" as read-only\n", name);

    // Mount the device
	//Print(L"Invoking ntfs_device_mount\n");
    vd->vol = ntfs_device_mount(vd->dev, vd->flags);
    if (!vd->vol) {
        switch(ntfs_volume_error(errno)) {
            case NTFS_VOLUME_NOT_NTFS: errno = EINVALPART; break;
            case NTFS_VOLUME_CORRUPT: errno = EINVALPART; break;
            case NTFS_VOLUME_HIBERNATED: errno = EHIBERNATED; break;
            case NTFS_VOLUME_UNCLEAN_UNMOUNT: errno = EDIRTY; break;
            default: errno = EINVAL; break;
        }
        ntfs_device_free(vd->dev);
        ntfs_free(vd);
		//Print(L"ntfsMount ntfs_device_mount FAILED (%x)\n", errno);
        return NULL;
    }

	if (flags & NTFS_IGNORE_CASE)
		ntfs_set_ignore_case(vd->vol);

    // Initialise the volume descriptor
    if (ntfsInitVolume(vd)) {
        ntfs_umount(vd->vol, true);
        ntfs_free(vd);
		//Print(L"ntfsMount ntfsInitVolume failed\n");
        return NULL;
    }

    // Add the device to the devoptab table
    if (ntfsAddDevice(name, vd)) {
		//Print(L"ntfsMount ntfsAddDevice failed\n");
        ntfsDeinitVolume(vd);
        ntfs_umount(vd->vol, true);
        ntfs_free(vd);
        return NULL;
    }

	//Print(L"ntfsMount done.\n");
    return vd;
}