NTFS: Deep code refactoring and lot of fixes
* Fix: the size of dirent struct in the fake attributes was counted incorrectly * Directory reading code was re-written from scratch. That fixes hopefully #7573, #4974, #4877, #9082 * Create, rename, unlink routines were completely reimplemented * Added fully functional support of extended attributes. This fixes #6509
This commit is contained in:
@@ -8,8 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define MIME_STRING_TYPE 'MIMS'
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
@@ -23,7 +21,9 @@
|
|||||||
#include "mime_table.h"
|
#include "mime_table.h"
|
||||||
#include "ntfs.h"
|
#include "ntfs.h"
|
||||||
|
|
||||||
//TODO: notify*()
|
|
||||||
|
const char* kHaikuAttrPrefix={"HAIKU-XATTR:"};
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
||||||
@@ -66,9 +66,9 @@ fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
if (ctx)
|
if (ctx != NULL)
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
||||||
@@ -153,23 +153,31 @@ fs_read_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
|||||||
|
|
||||||
TRACE("%s - ENTER\n", __FUNCTION__);
|
TRACE("%s - ENTER\n", __FUNCTION__);
|
||||||
|
|
||||||
|
|
||||||
while (!(result = ntfs_attrs_walk(cookie->ctx))) {
|
while (!(result = ntfs_attrs_walk(cookie->ctx))) {
|
||||||
ATTR_RECORD *attr = cookie->ctx->attr;
|
ATTR_RECORD *attr = cookie->ctx->attr;
|
||||||
if (attr->type == AT_DATA) {
|
if (attr->type == AT_DATA) {
|
||||||
|
const char *real_name;
|
||||||
// it's the actual file body
|
// it's the actual file body
|
||||||
if (attr->name_length == 0)
|
if (attr->name_length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
name = ntfs_attr_name_get((const ntfschar *)(((char *)attr)
|
name = ntfs_attr_name_get((const ntfschar *)(((char *)attr)
|
||||||
+ attr->name_offset), attr->name_length);
|
+ attr->name_offset), attr->name_length);
|
||||||
dprintf("found AT_DATA '%s'\n", name);
|
|
||||||
bufsize = MIN(bufsize, sizeof(struct dirent) + strlen(name) + 1);
|
if(strncmp(name, kHaikuAttrPrefix, strlen(kHaikuAttrPrefix)) !=0 ) {
|
||||||
|
TRACE("found AT_DATA '%s' - Skip\n", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TRACE("found AT_DATA '%s' - Found\n", name);
|
||||||
|
|
||||||
|
real_name = name + strlen(kHaikuAttrPrefix);
|
||||||
|
|
||||||
|
bufsize = MIN(bufsize, sizeof(struct dirent) + strlen(real_name) + 1);
|
||||||
entry->d_ino = node->vnid;
|
entry->d_ino = node->vnid;
|
||||||
entry->d_dev = ns->id;
|
entry->d_dev = ns->id;
|
||||||
entry->d_reclen = sizeof(struct dirent) + strlen(name);
|
entry->d_reclen = sizeof(struct dirent) + strlen(real_name);
|
||||||
//XXX size
|
//XXX size
|
||||||
strcpy(entry->d_name, name);
|
strcpy(entry->d_name, real_name);
|
||||||
ntfs_attr_name_free(&name);
|
ntfs_attr_name_free(&name);
|
||||||
numEntries++;
|
numEntries++;
|
||||||
if (numEntries >= *num)
|
if (numEntries >= *num)
|
||||||
@@ -210,9 +218,13 @@ fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name,
|
|||||||
int ulen;
|
int ulen;
|
||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_attr *na = NULL;
|
ntfs_attr *na = NULL;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
TRACE("%s - ENTER\n", __FUNCTION__);
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
|
return B_READ_ONLY_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%s - ENTER - name: [%s] vnid: %d\n", __FUNCTION__, name, node->vnid);
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -224,7 +236,7 @@ fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name,
|
|||||||
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
if (ni == NULL) {
|
if (ni == NULL) {
|
||||||
result = errno;
|
result = errno;
|
||||||
ERROR("%s - inode_open: %s\n", __FUNCTION__, strerror(result));
|
TRACE("%s - inode_open: %s\n", __FUNCTION__, strerror(result));
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,59 +247,66 @@ fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name,
|
|||||||
|
|
||||||
// check for a named stream
|
// check for a named stream
|
||||||
if (true) {
|
if (true) {
|
||||||
|
char ntfs_attr_name[MAX_PATH] = {0};
|
||||||
|
strcat(ntfs_attr_name, kHaikuAttrPrefix);
|
||||||
|
strcat(ntfs_attr_name,name);
|
||||||
|
|
||||||
uname = ntfs_calloc(MAX_PATH);
|
uname = ntfs_calloc(MAX_PATH);
|
||||||
ulen = ntfs_mbstoucs(name, &uname);
|
ulen = ntfs_mbstoucs(ntfs_attr_name, &uname);
|
||||||
if (ulen < 0) {
|
if (ulen < 0) {
|
||||||
result = EILSEQ;
|
result = EILSEQ;
|
||||||
ERROR("%s - mb alloc: %s\n", __FUNCTION__, strerror(result));
|
TRACE("%s - mb alloc: %s\n", __FUNCTION__, strerror(result));
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
||||||
if (na) {
|
if (na != NULL) {
|
||||||
result = EEXIST;
|
if (ntfs_attr_truncate(na, 0)) {
|
||||||
ERROR("%s - ntfs_attr_open: %s\n", __FUNCTION__,
|
result = errno;
|
||||||
strerror(result));
|
goto exit;
|
||||||
goto exit;
|
}
|
||||||
|
} else {
|
||||||
|
if (ntfs_attr_add(ni, AT_DATA, uname, ulen, NULL, 0) < 0) {
|
||||||
|
result = errno;
|
||||||
|
TRACE("%s - ntfs_attr_add: %s\n", __FUNCTION__,
|
||||||
|
strerror(result));
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
||||||
|
if (na == NULL) {
|
||||||
|
result = errno;
|
||||||
|
TRACE("%s - ntfs_attr_open: %s\n", __FUNCTION__,
|
||||||
|
strerror(result));
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//if (ntfs_non_resident_attr_record_add(ni, AT_DATA, uname, ulen, 0, 32,
|
if(ntfs_attr_pwrite(na, 0, sizeof(uint32), &type) < 0 ) {
|
||||||
// 0) < 0) {
|
|
||||||
if (ntfs_attr_add(ni, AT_DATA, uname, ulen, NULL, 0) < 0) {
|
|
||||||
result = errno;
|
result = errno;
|
||||||
//ERROR("%s - ntfs_non_resident_attr_record_add: %s\n",
|
|
||||||
ERROR("%s - ntfs_attr_add: %s\n", __FUNCTION__, strerror(result));
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
|
||||||
if (!na) {
|
|
||||||
result = errno;
|
|
||||||
ERROR("%s - ntfs_attr_open: %s\n", __FUNCTION__,
|
|
||||||
strerror(result));
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cookie = (attrcookie*)ntfs_calloc(sizeof(attrcookie));
|
cookie = (attrcookie*)ntfs_calloc(sizeof(attrcookie));
|
||||||
|
|
||||||
if (cookie != NULL) {
|
if (cookie != NULL) {
|
||||||
cookie->omode = openMode;
|
cookie->omode = openMode;
|
||||||
*_cookie = (void*)cookie;
|
*_cookie = (void*)cookie;
|
||||||
cookie->inode = ni;
|
cookie->vnid = node->vnid;
|
||||||
cookie->stream = na;
|
cookie->uname = uname;
|
||||||
ni = NULL;
|
cookie->uname_len = ulen;
|
||||||
na = NULL;
|
cookie->type = type;
|
||||||
|
uname = NULL;
|
||||||
} else
|
} else
|
||||||
result = ENOMEM;
|
result = ENOMEM;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (uname)
|
if (uname != NULL)
|
||||||
free(uname);
|
free(uname);
|
||||||
|
|
||||||
if (na)
|
if (na != NULL)
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
|
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
||||||
@@ -310,8 +329,9 @@ fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
|
|||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_attr *na = NULL;
|
ntfs_attr *na = NULL;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
uint32 type = B_XATTR_TYPE;
|
||||||
|
|
||||||
TRACE("%s - ENTER\n", __FUNCTION__);
|
TRACE("%s - ENTER - name: [%s] vnid: %d\n", __FUNCTION__, name, node->vnid);
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -333,18 +353,33 @@ fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
|
|||||||
|
|
||||||
// check for a named stream
|
// check for a named stream
|
||||||
if (true) {
|
if (true) {
|
||||||
|
char ntfs_attr_name[MAX_PATH] = {0};
|
||||||
|
strcat(ntfs_attr_name, kHaikuAttrPrefix);
|
||||||
|
strcat(ntfs_attr_name, name);
|
||||||
|
|
||||||
uname = ntfs_calloc(MAX_PATH);
|
uname = ntfs_calloc(MAX_PATH);
|
||||||
ulen = ntfs_mbstoucs(name, &uname);
|
ulen = ntfs_mbstoucs(ntfs_attr_name, &uname);
|
||||||
if (ulen < 0) {
|
if (ulen < 0) {
|
||||||
result = EILSEQ;
|
result = EILSEQ;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
||||||
if (na) {
|
if (na != NULL) {
|
||||||
if (openMode & O_TRUNC) {
|
if (openMode & O_TRUNC) {
|
||||||
if (ntfs_attr_truncate(na, 0))
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
result = errno;
|
result = B_READ_ONLY_DEVICE;
|
||||||
|
goto exit;
|
||||||
|
} else {
|
||||||
|
if (ntfs_attr_truncate(na, sizeof(uint32))) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ntfs_attr_pread(na, 0, sizeof(uint32), &type) != sizeof(uint32)) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
@@ -357,22 +392,23 @@ fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
|
|||||||
|
|
||||||
if (cookie != NULL) {
|
if (cookie != NULL) {
|
||||||
cookie->omode = openMode;
|
cookie->omode = openMode;
|
||||||
|
cookie->vnid = node->vnid;
|
||||||
|
cookie->uname = uname;
|
||||||
|
cookie->uname_len = ulen;
|
||||||
|
cookie->type = type;
|
||||||
*_cookie = (void*)cookie;
|
*_cookie = (void*)cookie;
|
||||||
cookie->inode = ni;
|
uname = NULL;
|
||||||
cookie->stream = na;
|
|
||||||
ni = NULL;
|
|
||||||
na = NULL;
|
|
||||||
} else
|
} else
|
||||||
result = ENOMEM;
|
result = ENOMEM;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (uname)
|
if (uname != NULL)
|
||||||
free(uname);
|
free(uname);
|
||||||
|
|
||||||
if (na)
|
if (na != NULL)
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
|
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
||||||
@@ -386,6 +422,8 @@ exit:
|
|||||||
status_t
|
status_t
|
||||||
fs_close_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie)
|
fs_close_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie)
|
||||||
{
|
{
|
||||||
|
vnode *node = (vnode*)_node->private_node;
|
||||||
|
TRACE("%s vnid: %d\n", __FUNCTION__, node->vnid);
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,10 +436,8 @@ fs_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
|||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
if (cookie->stream)
|
if (cookie->uname != NULL)
|
||||||
ntfs_attr_close(cookie->stream);
|
free(cookie->uname);
|
||||||
if (cookie->inode)
|
|
||||||
ntfs_inode_close(cookie->inode);
|
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -415,21 +451,33 @@ fs_read_attrib_stat(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
|||||||
struct stat *stat)
|
struct stat *stat)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace *)_vol->private_volume;
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
//vnode *node = (vnode *)_node->private_node;
|
vnode *node = (vnode *)_node->private_node;
|
||||||
attrcookie *cookie = (attrcookie *)_cookie;
|
attrcookie *cookie = (attrcookie *)_cookie;
|
||||||
//ntfs_inode *ni = cookie->inode;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_attr *na = cookie->stream;
|
ntfs_attr *na = NULL;
|
||||||
|
status_t result = B_NO_ERROR;
|
||||||
//status_t result = B_NO_ERROR;
|
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
//ERRPRINT("%s - ENTER\n", __FUNCTION__);
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
|
if (ni == NULL) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
na = ntfs_attr_open(ni, AT_DATA, cookie->uname, cookie->uname_len);
|
||||||
|
if (na == NULL) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
stat->st_type = B_XATTR_TYPE;
|
stat->st_type = cookie->type;
|
||||||
stat->st_size = na ? na->data_size : 0;
|
stat->st_size = na ? na->data_size - sizeof(uint32) : 0;
|
||||||
|
|
||||||
//exit:
|
exit:
|
||||||
|
if (na != NULL)
|
||||||
|
ntfs_attr_close(na);
|
||||||
|
if (ni != NULL)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -442,10 +490,10 @@ fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
|
|||||||
void *buffer, size_t *len)
|
void *buffer, size_t *len)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace *)_vol->private_volume;
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
//vnode *node = (vnode *)_node->private_node;
|
vnode *node = (vnode *)_node->private_node;
|
||||||
attrcookie *cookie = (attrcookie *)_cookie;
|
attrcookie *cookie = (attrcookie *)_cookie;
|
||||||
ntfs_inode *ni = cookie->inode;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_attr *na = cookie->stream;
|
ntfs_attr *na = NULL;
|
||||||
size_t size = *len;
|
size_t size = *len;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
@@ -455,20 +503,32 @@ fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("%s - ENTER\n", __FUNCTION__);
|
TRACE("%s - ENTER vnid: %d\n", __FUNCTION__, node->vnid);
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
|
if (ni == NULL) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
na = ntfs_attr_open(ni, AT_DATA, cookie->uname, cookie->uname_len);
|
||||||
|
if (na == NULL) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += sizeof(uint32);
|
||||||
|
|
||||||
// it is a named stream
|
// it is a named stream
|
||||||
if (na) {
|
if (na != NULL) {
|
||||||
if (pos + size > na->data_size)
|
if (pos + size > na->data_size)
|
||||||
size = na->data_size - pos;
|
size = na->data_size - pos;
|
||||||
|
|
||||||
while (size) {
|
while (size) {
|
||||||
off_t bytesRead = ntfs_attr_pread(na, pos, size, buffer);
|
off_t bytesRead = ntfs_attr_pread(na, pos, size, buffer);
|
||||||
if (bytesRead < (s64)size) {
|
if (bytesRead < (s64)size) {
|
||||||
ntfs_log_error("ntfs_attr_pread returned less bytes than "
|
ERROR("ntfs_attr_pread returned less bytes than "
|
||||||
"requested.\n");
|
"requested.\n");
|
||||||
}
|
}
|
||||||
if (bytesRead <= 0) {
|
if (bytesRead <= 0) {
|
||||||
@@ -487,10 +547,12 @@ fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
|
|||||||
result = ENOENT; // TODO
|
result = ENOENT; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME); // XXX needed ?
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
if (na != NULL)
|
||||||
|
ntfs_attr_close(na);
|
||||||
|
if (ni != NULL)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
@@ -500,22 +562,24 @@ exit:
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie,off_t pos,
|
fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
|
||||||
const void *buffer, size_t *_length)
|
const void *buffer, size_t *_length)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace *)_vol->private_volume;
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
//vnode *node = (vnode *)_node->private_node;
|
vnode *node = (vnode *)_node->private_node;
|
||||||
attrcookie *cookie = (attrcookie *)_cookie;
|
attrcookie *cookie = (attrcookie *)_cookie;
|
||||||
ntfs_inode *ni = cookie->inode;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_attr *na = cookie->stream;
|
ntfs_attr *na = NULL;
|
||||||
size_t size = *_length;
|
size_t size = *_length;
|
||||||
|
char *attr_name = NULL;
|
||||||
|
char *real_name = NULL;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
TRACE("%s - ENTER!!\n", __FUNCTION__);
|
TRACE("%s - ENTER vnode: %d\n", __FUNCTION__, node->vnid);
|
||||||
if (ns->flags & B_FS_IS_READONLY) {
|
|
||||||
ERROR("ntfs is read-only\n");
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
return EROFS;
|
return B_READ_ONLY_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos < 0) {
|
if (pos < 0) {
|
||||||
@@ -523,13 +587,23 @@ fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie,off_t pos,
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("%s - ENTER\n", __FUNCTION__);
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
|
if (ni == NULL) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
na = ntfs_attr_open(ni, AT_DATA, cookie->uname, cookie->uname_len);
|
||||||
|
if (na == NULL) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += sizeof(uint32);
|
||||||
|
|
||||||
// it is a named stream
|
// it is a named stream
|
||||||
if (na) {
|
if (na != NULL) {
|
||||||
if (cookie->omode & O_APPEND)
|
if (cookie->omode & O_APPEND)
|
||||||
pos = na->data_size;
|
pos = na->data_size;
|
||||||
|
|
||||||
@@ -560,15 +634,27 @@ fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie,off_t pos,
|
|||||||
*_length = total;
|
*_length = total;
|
||||||
} else {
|
} else {
|
||||||
*_length = 0;
|
*_length = 0;
|
||||||
return EINVAL;
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (total > 0)
|
|
||||||
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME); // XXX needed ?
|
|
||||||
|
|
||||||
exit:
|
|
||||||
|
|
||||||
|
if (ntfs_ucstombs(na->name, na->name_len, &attr_name, 0) >= 0) {
|
||||||
|
if (attr_name != NULL) {
|
||||||
|
if(strncmp(attr_name, kHaikuAttrPrefix, strlen(kHaikuAttrPrefix)) !=0 )
|
||||||
|
goto exit;
|
||||||
|
real_name = attr_name + strlen(kHaikuAttrPrefix);
|
||||||
|
notify_attribute_changed(ns->id, MREF(ni->mft_no),
|
||||||
|
real_name, B_ATTR_CHANGED);
|
||||||
|
free(attr_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (na != NULL)
|
||||||
|
ntfs_attr_close(na);
|
||||||
|
if (ni != NULL)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
@@ -576,3 +662,68 @@ exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fs_remove_attrib(fs_volume *_vol, fs_vnode *_node, const char* name)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
vnode *node = (vnode *)_node->private_node;
|
||||||
|
char ntfs_attr_name[MAX_PATH]={0};
|
||||||
|
ntfschar *uname = NULL;
|
||||||
|
int ulen;
|
||||||
|
ntfs_inode *ni = NULL;
|
||||||
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
|
TRACE("%s - ENTER - name: [%s]\n", __FUNCTION__, name);
|
||||||
|
|
||||||
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
|
ERROR("ntfs is read-only\n");
|
||||||
|
return B_READ_ONLY_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
|
if (ni == NULL) {
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(ntfs_attr_name, kHaikuAttrPrefix);
|
||||||
|
strcat(ntfs_attr_name, name);
|
||||||
|
|
||||||
|
uname = ntfs_calloc(MAX_PATH);
|
||||||
|
ulen = ntfs_mbstoucs(ntfs_attr_name, &uname);
|
||||||
|
if (ulen < 0) {
|
||||||
|
result = EILSEQ;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntfs_attr_remove(ni, AT_DATA, uname, ulen)) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
|
||||||
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
|
NInoFileNameSetDirty(ni);
|
||||||
|
}
|
||||||
|
notify_attribute_changed(ns->id, MREF(ni->mft_no), name, B_ATTR_REMOVED);
|
||||||
|
exit:
|
||||||
|
if (uname != NULL)
|
||||||
|
free(uname);
|
||||||
|
|
||||||
|
if (ni != NULL)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ status_t fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie,
|
|||||||
off_t pos, void *buffer, size_t *_length);
|
off_t pos, void *buffer, size_t *_length);
|
||||||
status_t fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie,
|
status_t fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie,
|
||||||
off_t pos, const void *buffer, size_t *_length);
|
off_t pos, const void *buffer, size_t *_length);
|
||||||
|
status_t fs_remove_attrib(fs_volume *_vol, fs_vnode *_node, const char* name);
|
||||||
|
|
||||||
#endif // NTFS_ATTRIBUTES_H
|
#endif // NTFS_ATTRIBUTES_H
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,13 @@
|
|||||||
#include "mime_table.h"
|
#include "mime_table.h"
|
||||||
|
|
||||||
int32 kBeOSTypeCookie = 0x1234;
|
int32 kBeOSTypeCookie = 0x1234;
|
||||||
|
char *kFailBackMime = {"application/octet-stream"};
|
||||||
|
|
||||||
status_t set_mime(vnode *node, const char *filename)
|
status_t set_mime(vnode *node, const char *filename)
|
||||||
{
|
{
|
||||||
struct ext_mime *p;
|
struct ext_mime *p;
|
||||||
int32 namelen, ext_len;
|
int32 namelen, ext_len;
|
||||||
node->mime = NULL;
|
node->mime = kFailBackMime;
|
||||||
namelen = strlen(filename);
|
namelen = strlen(filename);
|
||||||
|
|
||||||
for (p=mimes; p->extension; p++) {
|
for (p=mimes; p->extension; p++) {
|
||||||
@@ -67,7 +68,7 @@ fake_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
TRACE("fs_open_attrdir - EXIT, result is %s\n", strerror(result));
|
TRACE("fake_open_attrdir - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -134,7 +135,7 @@ fake_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
|||||||
TRACE("fake_rewind_attrcookie - ENTER\n");
|
TRACE("fake_rewind_attrcookie - ENTER\n");
|
||||||
|
|
||||||
if (_cookie == NULL) {
|
if (_cookie == NULL) {
|
||||||
TRACE("fake_rewind_attrcookie - error: fs_rewind_attrcookie"
|
TRACE("fake_rewind_attrcookie - error: fake_rewind_attrcookie"
|
||||||
"called with null cookie\n");
|
"called with null cookie\n");
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -172,7 +173,7 @@ fake_read_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
|||||||
|
|
||||||
entry->d_ino = node->vnid;
|
entry->d_ino = node->vnid;
|
||||||
entry->d_dev = ns->id;
|
entry->d_dev = ns->id;
|
||||||
entry->d_reclen = 10;
|
entry->d_reclen = sizeof(struct dirent)+10;
|
||||||
strcpy(entry->d_name, "BEOS:TYPE");
|
strcpy(entry->d_name, "BEOS:TYPE");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,14 +196,15 @@ fake_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
|
|||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("fake_open_attrib - ENTER\n");
|
TRACE("fake_open_attrib - ENTER (name = [%s])\n",name);
|
||||||
|
|
||||||
if (strcmp(name, "BEOS:TYPE")) {
|
if (strcmp(name, "BEOS:TYPE") != 0) {
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->mime == NULL) {
|
if (node->mime == NULL) {
|
||||||
|
TRACE("fake_open_attrib - MIME = NULL\n");
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,16 +118,22 @@ static u64
|
|||||||
ntfs_inode_lookup(fs_volume *_vol, ino_t parent, const char *name)
|
ntfs_inode_lookup(fs_volume *_vol, ino_t parent, const char *name)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
ntfschar *uname = NULL;
|
||||||
|
int uname_len;
|
||||||
u64 ino = (u64)-1;
|
u64 ino = (u64)-1;
|
||||||
u64 inum;
|
u64 inum;
|
||||||
ntfs_inode *dir_ni;
|
ntfs_inode *dir_ni;
|
||||||
|
|
||||||
/* Open target directory. */
|
/* Open target directory. */
|
||||||
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
||||||
if (dir_ni) {
|
if (dir_ni) {
|
||||||
|
uname_len = ntfs_mbstoucs(name, &uname);
|
||||||
|
if (uname_len < 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (ino);
|
||||||
|
}
|
||||||
/* Lookup file */
|
/* Lookup file */
|
||||||
inum = ntfs_inode_lookup_by_mbsname(dir_ni, name);
|
inum = ntfs_inode_lookup_by_name(dir_ni, uname, uname_len);
|
||||||
/* never return inodes 0 and 1 */
|
/* never return inodes 0 and 1 */
|
||||||
if (MREF(inum) <= 1) {
|
if (MREF(inum) <= 1) {
|
||||||
inum = (u64)-1;
|
inum = (u64)-1;
|
||||||
@@ -139,6 +145,8 @@ ntfs_inode_lookup(fs_volume *_vol, ino_t parent, const char *name)
|
|||||||
else
|
else
|
||||||
ino = MREF(inum);
|
ino = MREF(inum);
|
||||||
}
|
}
|
||||||
|
if (uname != NULL)
|
||||||
|
free(uname);
|
||||||
return (ino);
|
return (ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,137 +157,53 @@ ntfs_remove(fs_volume *_vol, ino_t parent, const char *name)
|
|||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
|
||||||
ntfschar *uname = NULL;
|
ntfschar *uname = NULL;
|
||||||
ntfs_inode *dir_ni = NULL, *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
int res = B_OK, uname_len;
|
ntfs_inode *dir_ni = NULL;
|
||||||
|
int result = B_OK;
|
||||||
|
int uname_len;
|
||||||
u64 iref;
|
u64 iref;
|
||||||
|
|
||||||
/* Open parent directory. */
|
/* Open parent directory. */
|
||||||
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
||||||
if (!dir_ni) {
|
if (!dir_ni) {
|
||||||
res = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
/* Generate unicode filename. */
|
/* Generate unicode filename. */
|
||||||
uname_len = ntfs_mbstoucs(name, &uname);
|
uname_len = ntfs_mbstoucs(name, &uname);
|
||||||
if (uname_len < 0) {
|
if (uname_len < 0) {
|
||||||
res = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
/* Open object for delete. */
|
/* Open object for delete. */
|
||||||
iref = ntfs_inode_lookup_by_mbsname(dir_ni, name);
|
iref = ntfs_inode_lookup_by_name(dir_ni, uname, uname_len);
|
||||||
if (iref == (u64)-1) {
|
if (iref == (u64)-1) {
|
||||||
res = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
/* deny unlinking metadata files */
|
/* deny unlinking metadata files */
|
||||||
if (MREF(iref) < FILE_first_user) {
|
if (MREF(iref) < FILE_first_user) {
|
||||||
res = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ni = ntfs_inode_open(ns->ntvol, MREF(iref));
|
ni = ntfs_inode_open(ns->ntvol, MREF(iref));
|
||||||
if (!ni) {
|
if (!ni) {
|
||||||
res = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_delete(ns->ntvol, (char*)NULL, ni, dir_ni, uname, uname_len))
|
if (ntfs_delete(ns->ntvol, (char*)NULL, ni, dir_ni, uname, uname_len))
|
||||||
res = EINVAL;
|
result = EINVAL;
|
||||||
/* ntfs_delete() always closes ni and dir_ni */
|
/* ntfs_delete() always closes ni and dir_ni */
|
||||||
ni = dir_ni = NULL;
|
ni = dir_ni = NULL;
|
||||||
exit:
|
exit:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
if (dir_ni)
|
if (dir_ni != NULL)
|
||||||
ntfs_inode_close(dir_ni);
|
ntfs_inode_close(dir_ni);
|
||||||
|
|
||||||
free(uname);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,6 +368,7 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args,
|
|||||||
gNTFSVnodeOps.read_attr = fake_read_attrib;
|
gNTFSVnodeOps.read_attr = fake_read_attrib;
|
||||||
gNTFSVnodeOps.read_attr_stat = fake_read_attrib_stat;
|
gNTFSVnodeOps.read_attr_stat = fake_read_attrib_stat;
|
||||||
gNTFSVnodeOps.write_attr = fake_write_attrib;
|
gNTFSVnodeOps.write_attr = fake_write_attrib;
|
||||||
|
gNTFSVnodeOps.remove_attr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ns->ntvol = utils_mount_volume(device, mountFlags | MS_RECOVER);
|
ns->ntvol = utils_mount_volume(device, mountFlags | MS_RECOVER);
|
||||||
@@ -557,7 +482,7 @@ fs_wfsstat(fs_volume *_vol, const struct fs_info *fss, uint32 mask)
|
|||||||
|
|
||||||
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");
|
||||||
return EROFS;
|
return B_READ_ONLY_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
@@ -580,10 +505,10 @@ fs_walk(fs_volume *_vol, fs_vnode *_dir, const char *file, ino_t *vnid)
|
|||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *baseNode = (vnode*)_dir->private_node;
|
vnode *baseNode = (vnode*)_dir->private_node;
|
||||||
vnode *newNode = NULL;
|
vnode *newNode = NULL;
|
||||||
ntfschar *unicode = NULL;
|
ntfschar *uname = NULL;
|
||||||
ntfs_inode *bi = NULL;
|
ntfs_inode *dir_ni = NULL;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
int len;
|
int uname_len;
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -603,23 +528,23 @@ fs_walk(fs_volume *_vol, fs_vnode *_dir, const char *file, ino_t *vnid)
|
|||||||
if (get_vnode(_vol, *vnid, (void**)&newNode) != 0)
|
if (get_vnode(_vol, *vnid, (void**)&newNode) != 0)
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
} else {
|
} else {
|
||||||
unicode = ntfs_calloc(MAX_PATH);
|
uname = ntfs_calloc(MAX_PATH);
|
||||||
len = ntfs_mbstoucs(file, &unicode);
|
uname_len = ntfs_mbstoucs(file, &uname);
|
||||||
if (len < 0) {
|
if (uname_len < 0) {
|
||||||
result = EILSEQ;
|
result = EILSEQ;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bi = ntfs_inode_open(ns->ntvol, baseNode->vnid);
|
dir_ni = ntfs_inode_open(ns->ntvol, baseNode->vnid);
|
||||||
if (!bi) {
|
if (dir_ni == NULL) {
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
*vnid = MREF(ntfs_inode_lookup_by_name(bi, unicode, len));
|
*vnid = MREF(ntfs_inode_lookup_by_name(dir_ni, uname, uname_len));
|
||||||
TRACE("fs_walk - VNID = %d\n",*vnid);
|
TRACE("fs_walk - VNID = %d\n",*vnid);
|
||||||
|
|
||||||
ntfs_inode_close(bi);
|
ntfs_inode_close(dir_ni);
|
||||||
|
|
||||||
if (*vnid == (u64)-1) {
|
if (*vnid == (u64)-1) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
@@ -636,8 +561,8 @@ fs_walk(fs_volume *_vol, fs_vnode *_dir, const char *file, ino_t *vnid)
|
|||||||
exit:
|
exit:
|
||||||
TRACE("fs_walk - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_walk - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
if (unicode)
|
if (uname)
|
||||||
free(unicode);
|
free(uname);
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -676,7 +601,7 @@ fs_get_vnode_name(fs_volume *_vol, fs_vnode *_vnode, char *buffer,
|
|||||||
strlcpy(buffer, name, bufferSize);
|
strlcpy(buffer, name, bufferSize);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
@@ -893,7 +818,7 @@ fs_rstat(fs_volume *_vol, fs_vnode *_node, struct stat *stbuf)
|
|||||||
stbuf->st_mtim = ntfs2timespec(ni->last_data_change_time);
|
stbuf->st_mtim = ntfs2timespec(ni->last_data_change_time);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_rstat - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_rstat - EXIT, result is %s\n", strerror(result));
|
||||||
@@ -954,7 +879,7 @@ fs_wstat(fs_volume *_vol, fs_vnode *_node, const struct stat *st, uint32 mask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_wstat: EXIT with (%s)\n", strerror(result));
|
TRACE("fs_wstat: EXIT with (%s)\n", strerror(result));
|
||||||
@@ -1008,7 +933,7 @@ fs_fsync(fs_volume *_vol, fs_vnode *_node)
|
|||||||
ntfs_inode_sync(ni);
|
ntfs_inode_sync(ni);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_fsync: EXIT\n");
|
TRACE("fs_fsync: EXIT\n");
|
||||||
@@ -1062,10 +987,10 @@ fs_open(fs_volume *_vol, fs_vnode *_node, int omode, void **_cookie)
|
|||||||
result = ENOMEM;
|
result = ENOMEM;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (na)
|
if (na != NULL)
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
|
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_open - EXIT\n");
|
TRACE("fs_open - EXIT\n");
|
||||||
@@ -1086,15 +1011,14 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
|
|||||||
vnode *newNode = NULL;
|
vnode *newNode = NULL;
|
||||||
ntfs_attr *na = NULL;
|
ntfs_attr *na = NULL;
|
||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_inode *bi = NULL;
|
ntfs_inode *dir_ni = NULL;
|
||||||
ntfschar *uname = NULL;
|
ntfschar *uname = NULL;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
int unameLength;
|
int unameLength;
|
||||||
|
|
||||||
if (ns->flags & B_FS_IS_READONLY) {
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
ERROR("ntfs is read-only\n");
|
return B_READ_ONLY_DEVICE;
|
||||||
return EROFS;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -1111,13 +1035,13 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bi = ntfs_inode_open(ns->ntvol, dir->vnid);
|
dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid);
|
||||||
if (bi == NULL) {
|
if (dir_ni == NULL) {
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(bi->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -1137,53 +1061,51 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ni = ntfs_pathname_to_inode(ns->ntvol, bi, name);
|
ni = ntfs_pathname_to_inode(ns->ntvol, dir_ni, name);
|
||||||
if (ni) {
|
if (ni != NULL) {
|
||||||
// file exists
|
// file exists
|
||||||
*_vnid = MREF(ni->mft_no);
|
*_vnid = MREF(ni->mft_no);
|
||||||
if (omode & O_TRUNC) {
|
if (omode & O_TRUNC) {
|
||||||
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
||||||
if (na) {
|
if (na != NULL) {
|
||||||
if (ntfs_attr_truncate(na, 0))
|
if (ntfs_attr_truncate(na, 0))
|
||||||
result = errno;
|
result = errno;
|
||||||
|
ntfs_attr_close(na);
|
||||||
} else
|
} else
|
||||||
result = errno;
|
result = errno;
|
||||||
}
|
}
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
} else {
|
} else {
|
||||||
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(dir_ni, securid, uname, unameLength, S_IFREG);
|
||||||
if (ni) {
|
if (ni != NULL) {
|
||||||
*_vnid = MREF(ni->mft_no);
|
ino_t vnid = MREF(ni->mft_no);
|
||||||
|
|
||||||
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
||||||
if (newNode == NULL) {
|
if (newNode == NULL) {
|
||||||
result = ENOMEM;
|
result = ENOMEM;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_inode_close_in_dir(ni, bi)) {
|
newNode->vnid = vnid;
|
||||||
result = EINVAL;
|
newNode->parent_vnid = MREF(dir_ni->mft_no);
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
newNode->vnid = *_vnid;
|
|
||||||
newNode->parent_vnid = MREF(bi->mft_no);
|
|
||||||
|
|
||||||
if (ns->fake_attrib)
|
|
||||||
set_mime(newNode, name);
|
|
||||||
|
|
||||||
ni->flags |= FILE_ATTR_ARCHIVE;
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
ntfs_inode_update_mbsname(bi, name, ni->mft_no);
|
|
||||||
NInoSetDirty(ni);
|
NInoSetDirty(ni);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
if (ntfs_inode_close_in_dir(ni, dir_ni)) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_vnid = vnid;
|
||||||
|
|
||||||
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, dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
notify_entry_created(ns->id, MREF(bi->mft_no), name, *_vnid);
|
notify_entry_created(ns->id, MREF(dir_ni->mft_no), name, *_vnid);
|
||||||
} else
|
} else
|
||||||
result = errno;
|
result = errno;
|
||||||
}
|
}
|
||||||
@@ -1193,12 +1115,12 @@ exit:
|
|||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
else
|
else
|
||||||
free(cookie);
|
free(cookie);
|
||||||
|
|
||||||
if (na)
|
if (dir_ni != NULL)
|
||||||
ntfs_attr_close(na);
|
ntfs_inode_close(dir_ni);
|
||||||
if (bi)
|
|
||||||
ntfs_inode_close(bi);
|
if (uname != NULL)
|
||||||
free(uname);
|
free(uname);
|
||||||
|
|
||||||
TRACE("fs_create - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_create - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
@@ -1245,7 +1167,7 @@ fs_read(fs_volume *_vol, fs_vnode *_dir, void *_cookie, off_t offset, void *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
||||||
if (!na) {
|
if (na == NULL) {
|
||||||
*len = 0;
|
*len = 0;
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit2;
|
goto exit2;
|
||||||
@@ -1273,11 +1195,11 @@ fs_read(fs_volume *_vol, fs_vnode *_dir, void *_cookie, off_t offset, void *buf,
|
|||||||
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME);
|
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (na)
|
if (na != NULL)
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
|
|
||||||
exit2:
|
exit2:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
@@ -1303,7 +1225,7 @@ fs_write(fs_volume *_vol, fs_vnode *_dir, void *_cookie, off_t offset,
|
|||||||
|
|
||||||
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");
|
||||||
return EROFS;
|
return B_READ_ONLY_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
@@ -1332,7 +1254,7 @@ fs_write(fs_volume *_vol, fs_vnode *_dir, void *_cookie, off_t offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
||||||
if (!na) {
|
if (na == NULL) {
|
||||||
ERROR("fs_write - ntfs_attr_open()==NULL\n");
|
ERROR("fs_write - ntfs_attr_open()==NULL\n");
|
||||||
*len = 0;
|
*len = 0;
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
@@ -1374,10 +1296,10 @@ fs_write(fs_volume *_vol, fs_vnode *_dir, void *_cookie, off_t offset,
|
|||||||
TRACE("fs_write - OK\n");
|
TRACE("fs_write - OK\n");
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (na)
|
if (na != NULL)
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
exit2:
|
exit2:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_write - EXIT, result is %s, writed %d bytes\n",
|
TRACE("fs_write - EXIT, result is %s, writed %d bytes\n",
|
||||||
@@ -1506,9 +1428,9 @@ fs_readlink(fs_volume *_vol, fs_vnode *_node, char *buffer, size_t *bufferSize)
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
free(intxFile);
|
free(intxFile);
|
||||||
if (na)
|
if (na != NULL)
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_readlink - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_readlink - EXIT, result is %s\n", strerror(result));
|
||||||
@@ -1525,16 +1447,19 @@ fs_create_symlink(fs_volume *_vol, fs_vnode *_dir, const char *name,
|
|||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *dir = (vnode*)_dir->private_node;
|
vnode *dir = (vnode*)_dir->private_node;
|
||||||
ntfs_inode *sym = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_inode *bi = NULL;
|
ntfs_inode *dir_ni = NULL;
|
||||||
vnode *symnode = NULL;
|
vnode *newNode = NULL;
|
||||||
ntfschar *uname = NULL;
|
ntfschar *uname = NULL;
|
||||||
ntfschar *utarget = NULL;
|
ntfschar *utarget = NULL;
|
||||||
int unameLength;
|
int unameLength;
|
||||||
int utargetLength;
|
int utargetLength;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
int fmode = FS_FILE_MODE;
|
le32 securid = const_cpu_to_le32(0);
|
||||||
le32 securid = 0;
|
|
||||||
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
|
return B_READ_ONLY_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
@@ -1544,10 +1469,10 @@ fs_create_symlink(fs_volume *_vol, fs_vnode *_dir, const char *name,
|
|||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bi = ntfs_inode_open(ns->ntvol, dir->vnid);
|
dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid);
|
||||||
if (bi == NULL) {
|
if (dir_ni == NULL) {
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1563,51 +1488,45 @@ fs_create_symlink(fs_volume *_vol, fs_vnode *_dir, const char *name,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
sym = ntfs_create_symlink(bi, securid, uname, unameLength, utarget,
|
ni = ntfs_create_symlink(dir_ni, securid, uname, unameLength, utarget,
|
||||||
utargetLength);
|
utargetLength);
|
||||||
if (sym == NULL) {
|
if (ni) {
|
||||||
result = EINVAL;
|
ino_t vnid = MREF(ni->mft_no);
|
||||||
goto exit;
|
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
||||||
}
|
if (newNode == NULL) {
|
||||||
|
result = ENOMEM;
|
||||||
symnode = (vnode*)ntfs_calloc(sizeof(vnode));
|
goto exit;
|
||||||
if (symnode == NULL) {
|
|
||||||
result = ENOMEM;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
symnode->vnid = MREF(sym->mft_no);
|
|
||||||
symnode->parent_vnid = MREF(bi->mft_no);
|
|
||||||
|
|
||||||
if (ns->fake_attrib) {
|
|
||||||
if (sym->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
|
|
||||||
set_mime(symnode, ".***");
|
|
||||||
fmode = FS_DIR_MODE;
|
|
||||||
} else {
|
|
||||||
set_mime(symnode, name);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
result = publish_vnode(_vol, MREF(sym->mft_no), symnode, &gNTFSVnodeOps,
|
newNode->vnid = vnid;
|
||||||
S_IFLNK | fmode, 0);
|
newNode->parent_vnid = MREF(dir_ni->mft_no);
|
||||||
if (result != 0) {
|
|
||||||
ERROR("fs_symlink - new_vnode failed for vnid %Ld: %s\n",
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
MREF(sym->mft_no), strerror(result));
|
NInoSetDirty(ni);
|
||||||
}
|
|
||||||
|
|
||||||
put_vnode(_vol, MREF(sym->mft_no));
|
result = B_NO_ERROR;
|
||||||
fs_ntfs_update_times(_vol, sym, NTFS_UPDATE_CTIME);
|
result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps,
|
||||||
fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME);
|
S_IFREG, 0);
|
||||||
|
put_vnode(_vol, vnid);
|
||||||
|
|
||||||
|
if (ntfs_inode_close_in_dir(ni, dir_ni)) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
notify_entry_created(ns->id, MREF( bi->mft_no ), name, MREF(sym->mft_no));
|
ntfs_mark_free_space_outdated(ns);
|
||||||
|
fs_ntfs_update_times(_vol, dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
|
notify_entry_created(ns->id, MREF(dir_ni->mft_no), name, vnid);
|
||||||
|
} else
|
||||||
|
result = errno;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (sym)
|
if (dir_ni != NULL)
|
||||||
ntfs_inode_close(sym);
|
ntfs_inode_close(dir_ni);
|
||||||
if (bi)
|
if (utarget != NULL)
|
||||||
ntfs_inode_close(bi);
|
free(utarget);
|
||||||
free(utarget);
|
if (uname != NULL)
|
||||||
free(uname);
|
free(uname);
|
||||||
|
|
||||||
TRACE("fs_symlink - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_symlink - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
@@ -1626,13 +1545,13 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
ntfschar *uname = NULL;
|
ntfschar *uname = NULL;
|
||||||
int unameLength;
|
int unameLength;
|
||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_inode *bi = NULL;
|
ntfs_inode *dir_ni = NULL;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
le32 securid = const_cpu_to_le32(0);
|
le32 securid = const_cpu_to_le32(0);
|
||||||
|
|
||||||
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");
|
||||||
return EROFS;
|
return B_READ_ONLY_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
@@ -1644,13 +1563,13 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bi = ntfs_inode_open(ns->ntvol, dir->vnid);
|
dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid);
|
||||||
if (bi == NULL) {
|
if (dir_ni == NULL) {
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(bi->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -1661,8 +1580,8 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ni = ntfs_create(bi, securid, uname, unameLength, S_IFDIR);
|
ni = ntfs_create(dir_ni, securid, uname, unameLength, S_IFDIR);
|
||||||
if (ni) {
|
if (ni != NULL) {
|
||||||
ino_t vnid = MREF(ni->mft_no);
|
ino_t vnid = MREF(ni->mft_no);
|
||||||
|
|
||||||
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
||||||
@@ -1671,19 +1590,10 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_inode_close_in_dir(ni, bi)) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
newNode->vnid = vnid;
|
newNode->vnid = vnid;
|
||||||
newNode->parent_vnid = MREF(bi->mft_no);
|
newNode->parent_vnid = MREF(dir_ni->mft_no);
|
||||||
|
|
||||||
if (ns->fake_attrib)
|
|
||||||
set_mime(newNode, ".***");
|
|
||||||
|
|
||||||
ni->flags |= FILE_ATTR_ARCHIVE;
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
ntfs_inode_update_mbsname(bi, name, ni->mft_no);
|
|
||||||
NInoSetDirty(ni);
|
NInoSetDirty(ni);
|
||||||
|
|
||||||
result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps,
|
result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps,
|
||||||
@@ -1691,16 +1601,22 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
|
|
||||||
put_vnode(_vol, vnid);
|
put_vnode(_vol, vnid);
|
||||||
|
|
||||||
|
if (ntfs_inode_close_in_dir(ni, dir_ni)) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
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, dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
notify_entry_created(ns->id, MREF(bi->mft_no), name, vnid);
|
notify_entry_created(ns->id, MREF(dir_ni->mft_no), name, vnid);
|
||||||
} else
|
} else
|
||||||
result = errno;
|
result = errno;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (bi)
|
if (dir_ni != NULL)
|
||||||
ntfs_inode_close(bi);
|
ntfs_inode_close(dir_ni);
|
||||||
free(uname);
|
if (uname != NULL)
|
||||||
|
free(uname);
|
||||||
|
|
||||||
TRACE("fs_mkdir - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_mkdir - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
@@ -1715,49 +1631,49 @@ 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 *parent_vnode = (vnode*)_odir->private_node;
|
||||||
vnode *ndir = (vnode*)_ndir->private_node;
|
vnode *newparent_vnode = (vnode*)_ndir->private_node;
|
||||||
vnode *file = NULL;
|
vnode *file = NULL;
|
||||||
|
|
||||||
ino_t parent = odir->vnid;
|
|
||||||
ino_t newparent = ndir->vnid;
|
|
||||||
|
|
||||||
ino_t ino, xino;
|
ino_t parent_vnid = parent_vnode->vnid;
|
||||||
|
ino_t newparent_vnid = newparent_vnode->vnid;
|
||||||
|
|
||||||
|
ino_t inode;
|
||||||
|
ino_t target_inode;
|
||||||
|
|
||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_inode *dir_ni = NULL;
|
ntfs_inode *dir_ni = NULL;
|
||||||
|
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
|
|
||||||
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");
|
||||||
return EROFS;
|
return B_READ_ONLY_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("NTFS:fs_rename - oldname:%s newname:%s\n", name, newname);
|
TRACE("NTFS:fs_rename - oldname:%s newname:%s\n", name, newname);
|
||||||
|
|
||||||
ino = ntfs_inode_lookup(_vol, parent, name);
|
inode = ntfs_inode_lookup(_vol, parent_vnid, name);
|
||||||
if (ino == (u64)-1) {
|
if (inode == (u64)-1) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether target is present */
|
/* Check whether target is present */
|
||||||
xino = ntfs_inode_lookup(_vol, newparent, newname);
|
target_inode = ntfs_inode_lookup(_vol, newparent_vnid, newname);
|
||||||
|
|
||||||
if (xino == (u64)-1) {
|
if (target_inode == (u64)-1) {
|
||||||
ntfschar *uname = NULL;
|
ntfschar *uname = NULL;
|
||||||
int uname_len;
|
int uname_len;
|
||||||
|
|
||||||
result = get_vnode(_vol, ino, (void**)&file);
|
result = get_vnode(_vol, inode, (void**)&file);
|
||||||
if (result != B_NO_ERROR)
|
if (result != B_NO_ERROR)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
|
||||||
ni = ntfs_inode_open(ns->ntvol, ino);
|
ni = ntfs_inode_open(ns->ntvol, inode);
|
||||||
if (!ni) {
|
if (!ni) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -1769,7 +1685,7 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_ni = ntfs_inode_open(ns->ntvol, newparent);
|
dir_ni = ntfs_inode_open(ns->ntvol, newparent_vnid);
|
||||||
if (!dir_ni) {
|
if (!dir_ni) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -1780,8 +1696,6 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no);
|
|
||||||
|
|
||||||
ni->flags |= FILE_ATTR_ARCHIVE;
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
|
|
||||||
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_CTIME);
|
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_CTIME);
|
||||||
@@ -1792,6 +1706,8 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name,
|
|||||||
set_mime(file, ".***");
|
set_mime(file, ".***");
|
||||||
else
|
else
|
||||||
set_mime(file, newname);
|
set_mime(file, newname);
|
||||||
|
notify_attribute_changed(ns->id, file->vnid, "BEOS:TYPE",
|
||||||
|
B_ATTR_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_inode_close(dir_ni);
|
ntfs_inode_close(dir_ni);
|
||||||
@@ -1799,13 +1715,14 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name,
|
|||||||
|
|
||||||
free(uname);
|
free(uname);
|
||||||
|
|
||||||
ntfs_remove(_vol, parent, name);
|
ntfs_remove(_vol, parent_vnid, name);
|
||||||
|
|
||||||
|
file->parent_vnid = newparent_vnid;
|
||||||
|
|
||||||
file->parent_vnid = newparent;
|
|
||||||
|
|
||||||
put_vnode(_vol, file->vnid);
|
put_vnode(_vol, file->vnid);
|
||||||
|
|
||||||
notify_entry_moved(ns->id, parent, name, newparent, newname, ino);
|
notify_entry_moved(ns->id, parent_vnid, name, newparent_vnid,
|
||||||
|
newname, inode);
|
||||||
} else
|
} else
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
exit:
|
exit:
|
||||||
@@ -1822,11 +1739,15 @@ fs_rmdir(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
|||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *dir = (vnode*)_dir->private_node;
|
vnode *dir = (vnode*)_dir->private_node;
|
||||||
|
vnode *file = NULL;
|
||||||
|
ntfs_inode *ni = NULL;
|
||||||
|
ntfs_inode *dir_ni = NULL;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
ino_t ino;
|
||||||
|
|
||||||
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");
|
||||||
return EROFS;
|
return B_READ_ONLY_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
@@ -1835,20 +1756,64 @@ fs_rmdir(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
|||||||
|
|
||||||
if (ns == NULL || dir == NULL || name == NULL) {
|
if (ns == NULL || dir == NULL || name == NULL) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit1;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
||||||
result = EPERM;
|
result = EPERM;
|
||||||
goto exit1;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = do_unlink(_vol, dir, name, true);
|
ino = ntfs_inode_lookup(_vol, dir->vnid, name);
|
||||||
|
if (ino == (u64)-1) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: space must not be freed here, but in fs_remove_vnode()!!!
|
result = get_vnode(_vol, ino, (void**)&file);
|
||||||
|
if (result != B_NO_ERROR)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, file->vnid);
|
||||||
|
if (ni != NULL) {
|
||||||
|
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
||||||
|
result = ENOTDIR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (ntfs_check_empty_dir(ni)<0) {
|
||||||
|
result = ENOTEMPTY;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
} else {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
result = ntfs_remove(_vol, dir->vnid, name);
|
||||||
|
if(result != B_NO_ERROR) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_entry_removed(ns->id, dir->vnid, name, file->vnid);
|
||||||
|
|
||||||
|
remove_vnode(_vol, file->vnid);
|
||||||
|
|
||||||
|
put_vnode(_vol, ino);
|
||||||
|
|
||||||
|
dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid);
|
||||||
|
if (dir_ni != NULL) {
|
||||||
|
fs_ntfs_update_times(_vol, dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
|
ntfs_inode_close(dir_ni);
|
||||||
|
}
|
||||||
|
|
||||||
ntfs_mark_free_space_outdated(ns);
|
ntfs_mark_free_space_outdated(ns);
|
||||||
|
|
||||||
exit1:
|
exit:
|
||||||
|
if (ni != NULL)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_rmdir - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_rmdir - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
@@ -1862,11 +1827,14 @@ fs_unlink(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
|||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *dir = (vnode*)_dir->private_node;
|
vnode *dir = (vnode*)_dir->private_node;
|
||||||
|
vnode *file = NULL;
|
||||||
|
ntfs_inode *dir_ni = NULL;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
ino_t inode;
|
||||||
|
|
||||||
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");
|
||||||
return EROFS;
|
return B_READ_ONLY_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
@@ -1883,11 +1851,35 @@ fs_unlink(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = do_unlink(_vol, dir, name, false);
|
inode = ntfs_inode_lookup(_vol, dir->vnid, name);
|
||||||
|
if (inode == (u64)-1) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = get_vnode(_vol, inode, (void**)&file);
|
||||||
|
if (result != B_NO_ERROR)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
result = ntfs_remove(_vol, dir->vnid, name);
|
||||||
|
if(result != B_NO_ERROR) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_entry_removed(ns->id, dir->vnid, name, file->vnid);
|
||||||
|
|
||||||
|
remove_vnode(_vol, file->vnid);
|
||||||
|
|
||||||
|
put_vnode(_vol, inode);
|
||||||
|
|
||||||
|
dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid);
|
||||||
|
if (dir_ni != NULL) {
|
||||||
|
fs_ntfs_update_times(_vol, dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
|
ntfs_inode_close(dir_ni);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: space must not be freed here, but in fs_remove_vnode()!!!
|
|
||||||
ntfs_mark_free_space_outdated(ns);
|
ntfs_mark_free_space_outdated(ns);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
TRACE("fs_unlink - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_unlink - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ fs_vnode_ops gNTFSVnodeOps = {
|
|||||||
&fs_read_attrib_stat,
|
&fs_read_attrib_stat,
|
||||||
NULL, //&fs_write_attr_stat,
|
NULL, //&fs_write_attr_stat,
|
||||||
NULL, //&fs_rename_attr,
|
NULL, //&fs_rename_attr,
|
||||||
NULL, //&fs_remove_attr,
|
&fs_remove_attrib,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -87,19 +87,20 @@ typedef struct vnode {
|
|||||||
} vnode;
|
} vnode;
|
||||||
|
|
||||||
typedef struct filecookie {
|
typedef struct filecookie {
|
||||||
int omode;
|
int omode;
|
||||||
off_t last_size;
|
off_t last_size;
|
||||||
} filecookie;
|
} filecookie;
|
||||||
|
|
||||||
typedef struct attrcookie {
|
typedef struct attrcookie {
|
||||||
int omode;
|
int omode;
|
||||||
ntfs_inode *inode;
|
ino_t vnid;
|
||||||
ntfs_attr *stream;
|
ntfschar* uname;
|
||||||
// MFT ref for EA ?
|
int uname_len;
|
||||||
|
uint32 type;
|
||||||
} attrcookie;
|
} attrcookie;
|
||||||
|
|
||||||
typedef struct attrdircookie {
|
typedef struct attrdircookie {
|
||||||
ntfs_inode *inode;
|
ntfs_inode* inode;
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
} attrdircookie;
|
} attrdircookie;
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
||||||
//callback function for readdir()
|
static int
|
||||||
static int _ntfs_dirent_filler(void *_dirent, const ntfschar *name,
|
_ntfs_dirent_filler(void *_dirent, const ntfschar *name,
|
||||||
const int name_len, const int name_type, const s64 pos, const MFT_REF mref,
|
const int name_len, const int name_type, const s64 pos, const MFT_REF mref,
|
||||||
const unsigned dt_type)
|
const unsigned dt_type)
|
||||||
{
|
{
|
||||||
@@ -45,42 +45,64 @@ static int _ntfs_dirent_filler(void *_dirent, const ntfschar *name,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user
|
if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user
|
||||||
|| cookie->show_sys_files) {
|
|| cookie->show_sys_files) {
|
||||||
if (cookie->readed == 1) {
|
int len = ntfs_ucstombs(name, name_len, &filename, 0);
|
||||||
cookie->pos=pos;
|
if (len >= 0 && filename != NULL) {
|
||||||
cookie->readed = 0;
|
cache_entry* new_entry =
|
||||||
return -1;
|
(cache_entry*)ntfs_calloc(sizeof(cache_entry));
|
||||||
} else {
|
if (new_entry == NULL) {
|
||||||
if (ntfs_ucstombs(name, name_len, &filename, 0) >= 0) {
|
free(filename);
|
||||||
if (filename) {
|
return -1;
|
||||||
strcpy(cookie->name,filename);
|
}
|
||||||
cookie->ino=MREF(mref);
|
|
||||||
cookie->readed = 1;
|
new_entry->ent =
|
||||||
free(filename);
|
(struct dirent*)ntfs_calloc(sizeof(struct dirent) + len);
|
||||||
return 0;
|
new_entry->ent->d_dev = cookie->dev_id;
|
||||||
}
|
new_entry->ent->d_ino = MREF(mref);
|
||||||
|
memcpy(new_entry->ent->d_name,filename, len + 1);
|
||||||
|
new_entry->ent->d_reclen = sizeof(struct dirent) + len;
|
||||||
|
|
||||||
|
if(cookie->cache_root == NULL || cookie->entry == NULL) {
|
||||||
|
cookie->cache_root = new_entry;
|
||||||
|
cookie->entry = cookie->cache_root;
|
||||||
|
cookie->entry->next = NULL;
|
||||||
|
} else {
|
||||||
|
cookie->entry->next = (void*)new_entry;
|
||||||
|
cookie->entry = cookie->entry->next;
|
||||||
|
cookie->entry->next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
free(filename);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_free_dircookie(fs_volume *_vol, fs_vnode *vnode, void *cookie)
|
fs_free_dircookie(fs_volume *_vol, fs_vnode *vnode, void *_cookie)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
dircookie *cookie = (dircookie*)_cookie;
|
||||||
LOCK_VOL(ns);
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
TRACE("fs_free_dircookie - ENTER\n");
|
TRACE("fs_free_dircookie - ENTER\n");
|
||||||
if (cookie != NULL)
|
|
||||||
|
if (cookie != NULL) {
|
||||||
|
cache_entry *entry = cookie->cache_root;
|
||||||
|
for(;entry!=NULL;) {
|
||||||
|
cache_entry *next = entry->next;
|
||||||
|
if(entry->ent != NULL)
|
||||||
|
free(entry->ent);
|
||||||
|
free(entry);
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
free(cookie);
|
free(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("fs_free_dircookie - EXIT\n");
|
TRACE("fs_free_dircookie - EXIT\n");
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
@@ -93,11 +115,10 @@ fs_opendir(fs_volume *_vol, fs_vnode *_node, void** _cookie)
|
|||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *node = (vnode*)_node->private_node;
|
vnode *node = (vnode*)_node->private_node;
|
||||||
dircookie *cookie = NULL;
|
dircookie *cookie = NULL;
|
||||||
int result = B_NO_ERROR;
|
|
||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("fs_opendir - ENTER\n");
|
TRACE("fs_opendir - ENTER\n");
|
||||||
|
|
||||||
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
@@ -114,21 +135,19 @@ fs_opendir(fs_volume *_vol, fs_vnode *_node, void** _cookie)
|
|||||||
cookie = (dircookie*)ntfs_calloc(sizeof(dircookie));
|
cookie = (dircookie*)ntfs_calloc(sizeof(dircookie));
|
||||||
if (cookie != NULL) {
|
if (cookie != NULL) {
|
||||||
cookie->pos = 0;
|
cookie->pos = 0;
|
||||||
cookie->ino = 0;
|
cookie->dev_id = ns->id;
|
||||||
cookie->readed = 0;
|
|
||||||
cookie->last = 0;
|
|
||||||
cookie->name[0] = 0;
|
|
||||||
cookie->show_sys_files = ns->show_sys_files;
|
cookie->show_sys_files = ns->show_sys_files;
|
||||||
|
cookie->cache_root = NULL;
|
||||||
|
cookie->entry = cookie->cache_root;
|
||||||
*_cookie = (void*)cookie;
|
*_cookie = (void*)cookie;
|
||||||
} else
|
} else
|
||||||
result = ENOMEM;
|
result = ENOMEM;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
TRACE("fs_opendir - EXIT\n");
|
TRACE("fs_opendir - EXIT\n");
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -138,32 +157,7 @@ exit:
|
|||||||
status_t
|
status_t
|
||||||
fs_closedir(fs_volume *_vol, fs_vnode *_node, void *cookie)
|
fs_closedir(fs_volume *_vol, fs_vnode *_node, void *cookie)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
return B_NO_ERROR;
|
||||||
vnode *node = (vnode*)_node->private_node;
|
|
||||||
int result = B_NO_ERROR;
|
|
||||||
ntfs_inode *ni = NULL;
|
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
|
||||||
|
|
||||||
TRACE("fs_closedir - ENTER\n");
|
|
||||||
|
|
||||||
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
|
||||||
if (ni == NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
if (ni)
|
|
||||||
ntfs_inode_close(ni);
|
|
||||||
|
|
||||||
TRACE("fs_closedir - EXIT\n");
|
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -174,12 +168,12 @@ fs_readdir(fs_volume *_vol, fs_vnode *_node, void *_cookie, struct dirent *buf,
|
|||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *node = (vnode*)_node->private_node;
|
vnode *node = (vnode*)_node->private_node;
|
||||||
dircookie *cookie = (dircookie*)_cookie;
|
dircookie *cookie = (dircookie*)_cookie;
|
||||||
uint32 nameLength = bufsize - sizeof(struct dirent), realLen;
|
|
||||||
int result = B_NO_ERROR;
|
|
||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
uint32 nameLength = bufsize - sizeof(struct dirent), realLen;
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
TRACE("fs_readdir - ENTER (sizeof(buf)=%d, bufsize=%d, num=%d\n",
|
TRACE("fs_readdir - ENTER (sizeof(buf)=%d, bufsize=%d, num=%d\n",
|
||||||
sizeof(buf), bufsize, *num);
|
sizeof(buf), bufsize, *num);
|
||||||
|
|
||||||
@@ -188,36 +182,47 @@ fs_readdir(fs_volume *_vol, fs_vnode *_node, void *_cookie, struct dirent *buf,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cookie->readed == 1 || cookie->last == 1) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
if (ni == NULL) {
|
if (ni == NULL) {
|
||||||
ERROR("fs_readdir - dir not opened\n");
|
TRACE("fs_readdir - dir not opened\n");
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ntfs_readdir(ni, &cookie->pos, cookie,
|
if(cookie->cache_root == NULL) {
|
||||||
(ntfs_filldir_t)_ntfs_dirent_filler);
|
cookie->entry = NULL;
|
||||||
|
result = ntfs_readdir(ni, &cookie->pos, cookie,
|
||||||
|
(ntfs_filldir_t)_ntfs_dirent_filler);
|
||||||
|
cookie->entry = cookie->cache_root;
|
||||||
|
if(result) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cookie->entry == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cookie->entry->ent == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
realLen = nameLength > 255 ? 255 : nameLength;
|
realLen = nameLength > 255 ? 255 : nameLength;
|
||||||
|
|
||||||
buf->d_dev = ns->id;
|
buf->d_dev = ns->id;
|
||||||
buf->d_ino = cookie->ino;
|
buf->d_ino = cookie->entry->ent->d_ino;
|
||||||
strlcpy(buf->d_name, cookie->name, realLen + 1);
|
strlcpy(buf->d_name, cookie->entry->ent->d_name, realLen + 1);
|
||||||
buf->d_reclen = sizeof(struct dirent) + realLen;
|
buf->d_reclen = sizeof(struct dirent) + realLen;
|
||||||
|
|
||||||
if (result == 0)
|
cookie->entry = (cache_entry*)cookie->entry->next;
|
||||||
cookie->last = 1;
|
|
||||||
|
|
||||||
result = B_NO_ERROR;
|
|
||||||
|
|
||||||
TRACE("fs_readdir - FILE: [%s]\n",buf->d_name);
|
TRACE("fs_readdir - FILE: [%s]\n",buf->d_name);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (ni)
|
if (ni != NULL)
|
||||||
ntfs_inode_close(ni);
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
if (result == B_NO_ERROR)
|
if (result == B_NO_ERROR)
|
||||||
@@ -228,8 +233,7 @@ exit:
|
|||||||
if (result == ENOENT)
|
if (result == ENOENT)
|
||||||
result = B_NO_ERROR;
|
result = B_NO_ERROR;
|
||||||
|
|
||||||
TRACE("fs_readdir - EXIT result (%s)\n", strerror(result));
|
TRACE("fs_readdir - EXIT num=%d result (%s)\n",*num, strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -244,19 +248,26 @@ fs_rewinddir(fs_volume *_vol, fs_vnode *vnode, void *_cookie)
|
|||||||
int result = EINVAL;
|
int result = EINVAL;
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("fs_rewinddir - ENTER\n");
|
TRACE("fs_rewinddir - ENTER\n");
|
||||||
|
|
||||||
if (cookie != NULL) {
|
if (cookie != NULL) {
|
||||||
|
cache_entry *entry = cookie->cache_root;
|
||||||
|
for(;entry!=NULL;) {
|
||||||
|
cache_entry *next = entry->next;
|
||||||
|
if(entry->ent != NULL)
|
||||||
|
free(entry->ent);
|
||||||
|
free(entry);
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
cookie->pos = 0;
|
cookie->pos = 0;
|
||||||
cookie->ino = 0;
|
cookie->dev_id = ns->id;
|
||||||
cookie->readed = 0;
|
cookie->show_sys_files = ns->show_sys_files;
|
||||||
cookie->last = 0;
|
cookie->cache_root = NULL;
|
||||||
cookie->name[0] = 0;
|
cookie->entry = cookie->cache_root;
|
||||||
result = B_NO_ERROR;
|
result = B_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("fs_rewinddir - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_rewinddir - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -24,15 +24,21 @@
|
|||||||
#include "ntfs.h"
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct cache_entry {
|
||||||
|
struct dirent *ent;
|
||||||
|
struct cache_entry *next;
|
||||||
|
} cache_entry;
|
||||||
|
|
||||||
|
|
||||||
typedef struct dircookie {
|
typedef struct dircookie {
|
||||||
u64 pos;
|
u64 pos;
|
||||||
int readed;
|
dev_t dev_id;
|
||||||
int last;
|
BOOL show_sys_files;
|
||||||
ino_t ino;
|
cache_entry *cache_root;
|
||||||
BOOL show_sys_files;
|
cache_entry *entry;
|
||||||
char name[MAX_PATH];
|
|
||||||
} dircookie;
|
} dircookie;
|
||||||
|
|
||||||
|
|
||||||
status_t fs_closedir(fs_volume *volume, fs_vnode *vnode, void *cookie);
|
status_t fs_closedir(fs_volume *volume, fs_vnode *vnode, void *cookie);
|
||||||
status_t fs_free_dircookie(fs_volume *volume, fs_vnode *vnode, void *cookie);
|
status_t fs_free_dircookie(fs_volume *volume, fs_vnode *vnode, void *cookie);
|
||||||
status_t fs_opendir(fs_volume *volume, fs_vnode *vnode, void** cookie);
|
status_t fs_opendir(fs_volume *volume, fs_vnode *vnode, void** cookie);
|
||||||
|
|||||||
Reference in New Issue
Block a user