NTFS:Critical fixes for renaming and creating nodes. The adaptation of some functions to the new version of the libntfs3g.
This commit is contained in:
@@ -113,6 +113,176 @@ get_node_type(ntfs_inode* ni, int* _type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u64
|
||||||
|
ntfs_inode_lookup(fs_volume *_vol, ino_t parent, const char *name)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
|
||||||
|
u64 ino = (u64)-1;
|
||||||
|
u64 inum;
|
||||||
|
ntfs_inode *dir_ni;
|
||||||
|
|
||||||
|
/* Open target directory. */
|
||||||
|
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
||||||
|
if (dir_ni) {
|
||||||
|
/* Lookup file */
|
||||||
|
inum = ntfs_inode_lookup_by_mbsname(dir_ni, name);
|
||||||
|
/* never return inodes 0 and 1 */
|
||||||
|
if (MREF(inum) <= 1) {
|
||||||
|
inum = (u64)-1;
|
||||||
|
errno = ENOENT;
|
||||||
|
}
|
||||||
|
if (ntfs_inode_close(dir_ni)
|
||||||
|
|| (inum == (u64)-1))
|
||||||
|
ino = (u64)-1;
|
||||||
|
else
|
||||||
|
ino = MREF(inum);
|
||||||
|
}
|
||||||
|
return (ino);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
ntfs_remove(fs_volume *_vol, ino_t parent, const char *name)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
|
||||||
|
ntfschar *uname = NULL;
|
||||||
|
ntfs_inode *dir_ni = NULL, *ni = NULL;
|
||||||
|
int res = B_OK, uname_len;
|
||||||
|
u64 iref;
|
||||||
|
|
||||||
|
/* Open parent directory. */
|
||||||
|
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
||||||
|
if (!dir_ni) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
/* Generate unicode filename. */
|
||||||
|
uname_len = ntfs_mbstoucs(name, &uname);
|
||||||
|
if (uname_len < 0) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
/* Open object for delete. */
|
||||||
|
iref = ntfs_inode_lookup_by_mbsname(dir_ni, name);
|
||||||
|
if (iref == (u64)-1) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
/* deny unlinking metadata files */
|
||||||
|
if (MREF(iref) < FILE_first_user) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, MREF(iref));
|
||||||
|
if (!ni) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntfs_delete(ns->ntvol, (char*)NULL, ni, dir_ni, uname, uname_len))
|
||||||
|
res = EINVAL;
|
||||||
|
/* ntfs_delete() always closes ni and dir_ni */
|
||||||
|
ni = dir_ni = NULL;
|
||||||
|
exit:
|
||||||
|
if (ni)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
if (dir_ni)
|
||||||
|
ntfs_inode_close(dir_ni);
|
||||||
|
|
||||||
|
free(uname);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
do_unlink(fs_volume *_vol, vnode *dir, const char *name, bool isdir)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
ino_t vnid;
|
||||||
|
vnode *node = NULL;
|
||||||
|
ntfs_inode *ni = NULL;
|
||||||
|
ntfs_inode *bi = NULL;
|
||||||
|
ntfschar *uname = NULL;
|
||||||
|
int unameLength;
|
||||||
|
|
||||||
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
|
unameLength = ntfs_mbstoucs(name, &uname);
|
||||||
|
if (unameLength < 0) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bi = ntfs_inode_open(ns->ntvol, dir->vnid);
|
||||||
|
if (bi == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vnid = MREF(ntfs_inode_lookup_by_name(bi, uname, unameLength));
|
||||||
|
|
||||||
|
if ( vnid == (u64)-1 || vnid == FILE_root) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = get_vnode(_vol, vnid, (void**)&node);
|
||||||
|
|
||||||
|
if (result != B_NO_ERROR || node==NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
|
if (ni == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isdir) {
|
||||||
|
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
||||||
|
result = ENOTDIR;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
if (ntfs_check_empty_dir(ni)<0) {
|
||||||
|
result = ENOTEMPTY;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
} else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
|
||||||
|
result = EISDIR;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: the file must not be deleted here, only unlinked!
|
||||||
|
if (ntfs_delete(ns->ntvol, (char*)NULL, ni, bi, uname, unameLength))
|
||||||
|
result = errno;
|
||||||
|
|
||||||
|
ni = bi = NULL;
|
||||||
|
|
||||||
|
node->parent_vnid = dir->vnid;
|
||||||
|
|
||||||
|
notify_entry_removed(ns->id, dir->vnid, name, vnid);
|
||||||
|
|
||||||
|
remove_vnode(_vol, vnid);
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
exit2:
|
||||||
|
put_vnode(_vol, vnid);
|
||||||
|
exit1:
|
||||||
|
free(uname);
|
||||||
|
|
||||||
|
if (ni)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
if (bi)
|
||||||
|
ntfs_inode_close(bi);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
fs_ntfs_update_times(fs_volume *vol, ntfs_inode *ni,
|
fs_ntfs_update_times(fs_volume *vol, ntfs_inode *ni,
|
||||||
ntfs_time_update_flags mask)
|
ntfs_time_update_flags mask)
|
||||||
@@ -964,8 +1134,6 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
|
|||||||
le32 securid = const_cpu_to_le32(0);
|
le32 securid = const_cpu_to_le32(0);
|
||||||
ni = ntfs_create(bi, securid, uname, unameLength, S_IFREG);
|
ni = ntfs_create(bi, securid, uname, unameLength, S_IFREG);
|
||||||
if (ni) {
|
if (ni) {
|
||||||
NInoSetDirty(ni);
|
|
||||||
|
|
||||||
*_vnid = MREF(ni->mft_no);
|
*_vnid = MREF(ni->mft_no);
|
||||||
|
|
||||||
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
||||||
@@ -983,13 +1151,16 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
|
|||||||
newNode->parent_vnid = MREF(bi->mft_no);
|
newNode->parent_vnid = MREF(bi->mft_no);
|
||||||
set_mime(newNode, name);
|
set_mime(newNode, name);
|
||||||
|
|
||||||
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
|
ntfs_inode_update_mbsname(bi, name, ni->mft_no);
|
||||||
|
NInoSetDirty(ni);
|
||||||
|
|
||||||
result = B_NO_ERROR;
|
result = B_NO_ERROR;
|
||||||
result = publish_vnode(_vol, *_vnid, (void*)newNode, &gNTFSVnodeOps,
|
result = publish_vnode(_vol, *_vnid, (void*)newNode, &gNTFSVnodeOps,
|
||||||
S_IFREG, 0);
|
S_IFREG, 0);
|
||||||
|
|
||||||
ntfs_mark_free_space_outdated(ns);
|
ntfs_mark_free_space_outdated(ns);
|
||||||
fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME);
|
fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME);
|
||||||
|
|
||||||
notify_entry_created(ns->id, MREF(bi->mft_no), name, *_vnid);
|
notify_entry_created(ns->id, MREF(bi->mft_no), name, *_vnid);
|
||||||
} else
|
} else
|
||||||
result = errno;
|
result = errno;
|
||||||
@@ -1471,8 +1642,6 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
if (ni) {
|
if (ni) {
|
||||||
ino_t vnid = MREF(ni->mft_no);
|
ino_t vnid = MREF(ni->mft_no);
|
||||||
|
|
||||||
NInoSetDirty(ni);
|
|
||||||
|
|
||||||
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
||||||
if (newNode == NULL) {
|
if (newNode == NULL) {
|
||||||
result = ENOMEM;
|
result = ENOMEM;
|
||||||
@@ -1488,6 +1657,10 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
newNode->parent_vnid = MREF(bi->mft_no);
|
newNode->parent_vnid = MREF(bi->mft_no);
|
||||||
set_mime(newNode, ".***");
|
set_mime(newNode, ".***");
|
||||||
|
|
||||||
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
|
ntfs_inode_update_mbsname(bi, name, ni->mft_no);
|
||||||
|
NInoSetDirty(ni);
|
||||||
|
|
||||||
result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps,
|
result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps,
|
||||||
S_IFDIR, 0);
|
S_IFDIR, 0);
|
||||||
|
|
||||||
@@ -1513,30 +1686,24 @@ exit:
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *oldname,
|
fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name,
|
||||||
fs_vnode *_ndir, const char *newname)
|
fs_vnode *_ndir, const char *newname)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *odir = (vnode*)_odir->private_node;
|
vnode *odir = (vnode*)_odir->private_node;
|
||||||
vnode *ndir = (vnode*)_ndir->private_node;
|
vnode *ndir = (vnode*)_ndir->private_node;
|
||||||
|
vnode *file = NULL;
|
||||||
|
|
||||||
vnode *onode = NULL;
|
ino_t parent = odir->vnid;
|
||||||
vnode *nnode = NULL;
|
ino_t newparent = ndir->vnid;
|
||||||
|
|
||||||
ino_t ovnid, nvnid;
|
ino_t ino, xino;
|
||||||
|
|
||||||
ntfs_inode *oi = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_inode *ndi = NULL;
|
ntfs_inode *dir_ni = NULL;
|
||||||
ntfs_inode *odi = NULL;
|
|
||||||
|
|
||||||
ntfschar *unewname = NULL;
|
|
||||||
ntfschar *uoldname = NULL;
|
|
||||||
int unewnameLength;
|
|
||||||
int uoldnameLength;
|
|
||||||
|
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
char path[MAX_PATH];
|
|
||||||
|
|
||||||
if (ns->flags & B_FS_IS_READONLY) {
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
ERROR("ntfs is read-only\n");
|
ERROR("ntfs is read-only\n");
|
||||||
@@ -1545,156 +1712,70 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *oldname,
|
|||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("fs_rename - oldname:%s newname:%s\n", oldname, newname);
|
TRACE("NTFS:fs_rename - oldname:%s newname:%s\n", name, newname);
|
||||||
|
|
||||||
// convert names from utf8 to unicode string
|
ino = ntfs_inode_lookup(_vol, parent, name);
|
||||||
unewnameLength = ntfs_mbstoucs(newname, &unewname);
|
if (ino == (u64)-1) {
|
||||||
if (unewnameLength < 0) {
|
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
uoldnameLength = ntfs_mbstoucs(oldname, &uoldname);
|
/* Check whether target is present */
|
||||||
if (uoldnameLength < 0) {
|
xino = ntfs_inode_lookup(_vol, newparent, newname);
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// open source directory inode
|
if (xino == (u64)-1) {
|
||||||
odi = ntfs_inode_open(ns->ntvol, odir->vnid);
|
ntfschar *uname = NULL;
|
||||||
if (odi == NULL) {
|
int uname_len;
|
||||||
result = ENOENT;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ovnid = MREF(ntfs_inode_lookup_by_name(odi, uoldname, uoldnameLength));
|
result = get_vnode(_vol, ino, (void**)&file);
|
||||||
if (ovnid == (u64) -1) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = get_vnode(_vol, ovnid, (void**)&onode);
|
|
||||||
if (result != B_NO_ERROR)
|
if (result != B_NO_ERROR)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
|
||||||
if (odir != ndir) {
|
ni = ntfs_inode_open(ns->ntvol, ino);
|
||||||
// moving
|
if (!ni) {
|
||||||
ndi = ntfs_inode_open(ns->ntvol, ndir->vnid);
|
|
||||||
if (ndi != NULL) {
|
|
||||||
nvnid = MREF(ntfs_inode_lookup_by_name(ndi, unewname,
|
|
||||||
unewnameLength));
|
|
||||||
if (nvnid != (u64) -1)
|
|
||||||
get_vnode(_vol, nvnid, (void**)&nnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nnode != NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
put_vnode(_vol, nnode->vnid);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_link(oi, ndi, unewname, unewnameLength)) {
|
uname_len = ntfs_mbstoucs(newname, &uname);
|
||||||
ntfs_inode_close(oi);
|
if (uname_len < 0) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oi->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
dir_ni = ntfs_inode_open(ns->ntvol, newparent);
|
||||||
set_mime(onode, ".***");
|
if (!dir_ni) {
|
||||||
else
|
|
||||||
set_mime(onode, newname);
|
|
||||||
|
|
||||||
ntfs_inode_close(oi);
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
onode->parent_vnid = MREF(ndi->mft_no);
|
if (ntfs_link(ni, dir_ni, uname, uname_len)) {
|
||||||
|
|
||||||
notify_entry_moved(ns->id, MREF(odi->mft_no), oldname, MREF(ndi->mft_no),
|
|
||||||
newname, onode->vnid);
|
|
||||||
|
|
||||||
if (utils_inode_get_name(oi, path, MAX_PATH) == 0) {
|
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_delete(ns->ntvol, path, oi, odi, uoldname, uoldnameLength);
|
ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no);
|
||||||
oi = odi = NULL;
|
|
||||||
/* ntfs_delete() always closes ni and dir_ni */
|
|
||||||
|
|
||||||
put_vnode(_vol, onode->vnid);
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
} else {
|
|
||||||
// renaming
|
|
||||||
|
|
||||||
nvnid = MREF(ntfs_inode_lookup_by_name(odi, unewname, unewnameLength));
|
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_CTIME);
|
||||||
if (nvnid != (u64)-1)
|
fs_ntfs_update_times(_vol, dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
get_vnode(_vol, nvnid, (void**)&nnode);
|
|
||||||
|
|
||||||
if (nnode != NULL) {
|
ntfs_inode_close(dir_ni);
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
|
free(uname);
|
||||||
|
|
||||||
|
ntfs_remove(_vol, parent, name);
|
||||||
|
|
||||||
|
file->parent_vnid = newparent;
|
||||||
|
put_vnode(_vol, file->vnid);
|
||||||
|
|
||||||
|
notify_entry_moved(ns->id, parent, name, newparent, newname, ino);
|
||||||
|
} else
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
put_vnode(_vol, nnode->vnid);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntfs_link(oi, odi, unewname, unewnameLength)) {
|
|
||||||
ntfs_inode_close(oi);
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oi->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
|
||||||
set_mime(onode, ".***");
|
|
||||||
else
|
|
||||||
set_mime(onode, newname);
|
|
||||||
|
|
||||||
ntfs_inode_close(oi);
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
notify_entry_moved(ns->id, MREF(odi->mft_no), oldname,
|
|
||||||
MREF(odi->mft_no), newname, onode->vnid);
|
|
||||||
put_vnode(_vol, onode->vnid);
|
|
||||||
|
|
||||||
if (utils_inode_get_name(oi, path, MAX_PATH) == 0) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ntfs_delete(ns->ntvol, path, oi, odi, uoldname, uoldnameLength);
|
|
||||||
oi = odi = NULL;
|
|
||||||
/* ntfs_delete() always closes ni and dir_ni */
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
free(unewname);
|
|
||||||
free(uoldname);
|
|
||||||
|
|
||||||
if (odi)
|
|
||||||
ntfs_inode_close(odi);
|
|
||||||
if (ndi)
|
|
||||||
ntfs_inode_close(ndi);
|
|
||||||
|
|
||||||
TRACE("fs_rename - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_rename - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
@@ -1703,97 +1784,6 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
do_unlink(fs_volume *_vol, vnode *dir, const char *name, bool isdir)
|
|
||||||
{
|
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
|
||||||
ino_t vnid;
|
|
||||||
vnode *node = NULL;
|
|
||||||
ntfs_inode *ni = NULL;
|
|
||||||
ntfs_inode *bi = NULL;
|
|
||||||
ntfschar *uname = NULL;
|
|
||||||
int unameLength;
|
|
||||||
char path[MAX_PATH];
|
|
||||||
|
|
||||||
status_t result = B_NO_ERROR;
|
|
||||||
|
|
||||||
unameLength = ntfs_mbstoucs(name, &uname);
|
|
||||||
if (unameLength < 0) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bi = ntfs_inode_open(ns->ntvol, dir->vnid);
|
|
||||||
if (bi == NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnid = MREF(ntfs_inode_lookup_by_name(bi, uname, unameLength));
|
|
||||||
|
|
||||||
if ( vnid == (u64)-1 || vnid == FILE_root) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = get_vnode(_vol, vnid, (void**)&node);
|
|
||||||
|
|
||||||
if (result != B_NO_ERROR || node==NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
|
||||||
if (ni == NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdir) {
|
|
||||||
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
|
||||||
result = ENOTDIR;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
if (ntfs_check_empty_dir(ni)<0) {
|
|
||||||
result = ENOTEMPTY;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
} else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
|
|
||||||
result = EISDIR;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utils_inode_get_name(ni, path, MAX_PATH) == 0) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: the file must not be deleted here, only unlinked!
|
|
||||||
if (ntfs_delete(ns->ntvol, path, ni, bi, uname, unameLength))
|
|
||||||
result = errno;
|
|
||||||
|
|
||||||
ni = bi = NULL;
|
|
||||||
|
|
||||||
node->parent_vnid = dir->vnid;
|
|
||||||
|
|
||||||
notify_entry_removed(ns->id, dir->vnid, name, vnid);
|
|
||||||
|
|
||||||
result = remove_vnode(_vol, vnid);
|
|
||||||
|
|
||||||
exit2:
|
|
||||||
put_vnode(_vol, vnid);
|
|
||||||
exit1:
|
|
||||||
free(uname);
|
|
||||||
|
|
||||||
if (ni)
|
|
||||||
ntfs_inode_close(ni);
|
|
||||||
if (bi)
|
|
||||||
ntfs_inode_close(bi);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_rmdir(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
fs_rmdir(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
||||||
{
|
{
|
||||||
@@ -1872,4 +1862,3 @@ exit:
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user