773 lines
16 KiB
C
773 lines
16 KiB
C
/*
|
|
Copyright 1999-2001, Be Incorporated. All Rights Reserved.
|
|
This file may be used under the terms of the Be Sample Code License.
|
|
*/
|
|
/* attributes.c
|
|
* handles mime type information for ntfs
|
|
* gets/sets mime information in vnode
|
|
*/
|
|
|
|
|
|
#include "attributes.h"
|
|
|
|
#include <dirent.h>
|
|
#include <fs_attr.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <KernelExport.h>
|
|
#include <SupportDefs.h>
|
|
#include <TypeConstants.h>
|
|
|
|
#include <kernel.h>
|
|
|
|
#include "mime_table.h"
|
|
#include "ntfs.h"
|
|
|
|
|
|
const char* kHaikuAttrPrefix = { "HAIKU-XATTR:" };
|
|
|
|
|
|
status_t
|
|
fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
|
{
|
|
nspace *ns = (nspace*)_vol->private_volume;
|
|
vnode *node = (vnode*)_node->private_node;
|
|
attrdircookie *cookie = NULL;
|
|
ntfs_inode *ni = NULL;
|
|
ntfs_attr_search_ctx *ctx = NULL;
|
|
|
|
status_t result = B_NO_ERROR;
|
|
|
|
TRACE("%s - ENTER\n", __FUNCTION__);
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
|
if (ni == NULL) {
|
|
result = errno;
|
|
goto exit;
|
|
}
|
|
|
|
ctx = ntfs_attr_get_search_ctx(ni, NULL);
|
|
if (ctx == NULL) {
|
|
result = errno;
|
|
goto exit;
|
|
}
|
|
|
|
cookie = (attrdircookie*)ntfs_calloc(sizeof(attrdircookie));
|
|
if (cookie == NULL) {
|
|
result = ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
cookie->inode = ni;
|
|
cookie->ctx = ctx;
|
|
ni = NULL;
|
|
ctx = NULL;
|
|
*_cookie = cookie;
|
|
|
|
exit:
|
|
|
|
if (ctx != NULL)
|
|
ntfs_attr_put_search_ctx(ctx);
|
|
if (ni != NULL)
|
|
ntfs_inode_close(ni);
|
|
|
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_close_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
|
{
|
|
return B_NO_ERROR;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_free_attrib_dir_cookie(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
|
{
|
|
nspace *ns = (nspace *)_vol->private_volume;
|
|
attrdircookie *cookie = (attrdircookie *)_cookie;
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
if (cookie->ctx)
|
|
ntfs_attr_put_search_ctx(cookie->ctx);
|
|
if (cookie->inode)
|
|
ntfs_inode_close(cookie->inode);
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
free(cookie);
|
|
return B_NO_ERROR;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
|
{
|
|
nspace *ns = (nspace*)_vol->private_volume;
|
|
attrdircookie *cookie = (attrdircookie *)_cookie;
|
|
status_t result = B_NO_ERROR;
|
|
|
|
TRACE("%s - ENTER\n", __FUNCTION__);
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
if (cookie->ctx)
|
|
ntfs_attr_put_search_ctx(cookie->ctx);
|
|
cookie->ctx = ntfs_attr_get_search_ctx(cookie->inode, NULL);
|
|
if (cookie->ctx == NULL) {
|
|
result = errno;
|
|
//goto exit;
|
|
}
|
|
|
|
//exit:
|
|
|
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_read_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
|
struct dirent *entry, size_t bufsize, uint32 *num)
|
|
{
|
|
nspace *ns = (nspace *)_vol->private_volume;
|
|
vnode *node = (vnode *)_node->private_node;
|
|
char *name = NULL;
|
|
attrdircookie *cookie = (attrdircookie *)_cookie;
|
|
uint32 numEntries = 0;
|
|
status_t result = B_NO_ERROR;
|
|
|
|
if (cookie->ctx == NULL)
|
|
panic("cookie->ctx == NULL");
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
TRACE("%s - ENTER\n", __FUNCTION__);
|
|
|
|
while (!(result = ntfs_attrs_walk(cookie->ctx))) {
|
|
ATTR_RECORD *attr = cookie->ctx->attr;
|
|
if (attr->type == AT_DATA) {
|
|
const char *real_name;
|
|
// it's the actual file body
|
|
if (attr->name_length == 0)
|
|
continue;
|
|
|
|
name = ntfs_attr_name_get((const ntfschar *)(((char *)attr)
|
|
+ attr->name_offset), attr->name_length);
|
|
|
|
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_dev = ns->id;
|
|
entry->d_reclen = sizeof(struct dirent) + strlen(real_name);
|
|
//XXX size
|
|
strcpy(entry->d_name, real_name);
|
|
ntfs_attr_name_free(&name);
|
|
numEntries++;
|
|
if (numEntries >= *num)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
if (result && errno != ENOENT) {
|
|
result = errno;
|
|
goto exit;
|
|
} else
|
|
result = B_OK;
|
|
|
|
exit:
|
|
|
|
TRACE("%s - EXIT, result is %s, *num %d\n", __FUNCTION__,
|
|
strerror(result), *num);
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
if (result)
|
|
*num = 0;
|
|
else
|
|
*num = numEntries;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name,
|
|
uint32 type, int openMode, void** _cookie)
|
|
{
|
|
nspace *ns = (nspace*)_vol->private_volume;
|
|
vnode *node = (vnode*)_node->private_node;
|
|
attrcookie *cookie = NULL;
|
|
ntfschar *uname = NULL;
|
|
int ulen;
|
|
ntfs_inode *ni = NULL;
|
|
ntfs_attr *na = NULL;
|
|
status_t result = B_NO_ERROR;
|
|
|
|
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);
|
|
|
|
if (node == NULL) {
|
|
result = EINVAL;
|
|
goto exit;
|
|
}
|
|
|
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
|
if (ni == NULL) {
|
|
result = errno;
|
|
TRACE("%s - inode_open: %s\n", __FUNCTION__, strerror(result));
|
|
goto exit;
|
|
}
|
|
|
|
// UXA demangling TODO
|
|
|
|
// check for EA first... TODO: WRITEME
|
|
|
|
// check for a named stream
|
|
if (true) {
|
|
char ntfs_attr_name[MAX_PATH] = {0};
|
|
strlcpy(ntfs_attr_name, kHaikuAttrPrefix, sizeof(ntfs_attr_name));
|
|
strlcat(ntfs_attr_name, name, sizeof(ntfs_attr_name));
|
|
|
|
uname = ntfs_calloc(MAX_PATH);
|
|
ulen = ntfs_mbstoucs(ntfs_attr_name, &uname);
|
|
if (ulen < 0) {
|
|
result = EILSEQ;
|
|
TRACE("%s - mb alloc: %s\n", __FUNCTION__, strerror(result));
|
|
goto exit;
|
|
}
|
|
|
|
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
|
if (na != NULL) {
|
|
if (ntfs_attr_truncate(na, 0)) {
|
|
result = errno;
|
|
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_attr_pwrite(na, 0, sizeof(uint32), &type) < 0 ) {
|
|
result = errno;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
cookie = (attrcookie*)ntfs_calloc(sizeof(attrcookie));
|
|
|
|
if (cookie != NULL) {
|
|
cookie->omode = openMode;
|
|
*_cookie = (void*)cookie;
|
|
cookie->vnid = node->vnid;
|
|
cookie->uname = uname;
|
|
cookie->uname_len = ulen;
|
|
cookie->type = type;
|
|
uname = NULL;
|
|
} else
|
|
result = ENOMEM;
|
|
|
|
exit:
|
|
if (uname != NULL)
|
|
free(uname);
|
|
|
|
if (na != NULL)
|
|
ntfs_attr_close(na);
|
|
|
|
if (ni != NULL)
|
|
ntfs_inode_close(ni);
|
|
|
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
|
|
int openMode, void **_cookie)
|
|
{
|
|
nspace *ns = (nspace*)_vol->private_volume;
|
|
vnode *node = (vnode*)_node->private_node;
|
|
attrcookie *cookie = NULL;
|
|
ntfschar *uname = NULL;
|
|
int ulen;
|
|
ntfs_inode *ni = NULL;
|
|
ntfs_attr *na = NULL;
|
|
status_t result = B_NO_ERROR;
|
|
uint32 type = B_XATTR_TYPE;
|
|
|
|
TRACE("%s - ENTER - name: [%s] vnid: %d\n", __FUNCTION__, name, node->vnid);
|
|
|
|
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;
|
|
}
|
|
|
|
// UXA demangling TODO
|
|
|
|
// check for EA first... TODO: WRITEME
|
|
|
|
// check for a named stream
|
|
if (true) {
|
|
char ntfs_attr_name[MAX_PATH] = {0};
|
|
strlcpy(ntfs_attr_name, kHaikuAttrPrefix, sizeof(ntfs_attr_name));
|
|
strlcat(ntfs_attr_name, name, sizeof(ntfs_attr_name));
|
|
|
|
uname = ntfs_calloc(MAX_PATH);
|
|
ulen = ntfs_mbstoucs(ntfs_attr_name, &uname);
|
|
if (ulen < 0) {
|
|
result = EILSEQ;
|
|
goto exit;
|
|
}
|
|
|
|
na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
|
|
if (na != NULL) {
|
|
if (openMode & O_TRUNC) {
|
|
if (ns->flags & B_FS_IS_READONLY) {
|
|
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 {
|
|
result = ENOENT;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
|
|
cookie = (attrcookie*)ntfs_calloc(sizeof(attrcookie));
|
|
|
|
if (cookie != NULL) {
|
|
cookie->omode = openMode;
|
|
cookie->vnid = node->vnid;
|
|
cookie->uname = uname;
|
|
cookie->uname_len = ulen;
|
|
cookie->type = type;
|
|
*_cookie = (void*)cookie;
|
|
uname = NULL;
|
|
} else
|
|
result = ENOMEM;
|
|
|
|
exit:
|
|
if (uname != NULL)
|
|
free(uname);
|
|
|
|
if (na != NULL)
|
|
ntfs_attr_close(na);
|
|
|
|
if (ni != NULL)
|
|
ntfs_inode_close(ni);
|
|
|
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_close_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie)
|
|
{
|
|
TRACE("%s vnid: %d\n", __FUNCTION__, ((vnode*)_node->private_node)->vnid);
|
|
return B_NO_ERROR;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
|
{
|
|
nspace *ns = (nspace*)_vol->private_volume;
|
|
attrcookie *cookie = (attrcookie *)_cookie;
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
if (cookie->uname != NULL)
|
|
free(cookie->uname);
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
free(cookie);
|
|
return B_NO_ERROR;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_read_attrib_stat(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
|
struct stat *stat)
|
|
{
|
|
nspace *ns = (nspace *)_vol->private_volume;
|
|
vnode *node = (vnode *)_node->private_node;
|
|
attrcookie *cookie = (attrcookie *)_cookie;
|
|
ntfs_inode *ni = NULL;
|
|
ntfs_attr *na = NULL;
|
|
status_t result = B_OK;
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
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 = cookie->type;
|
|
stat->st_size = na ? na->data_size - sizeof(uint32) : 0;
|
|
|
|
exit:
|
|
if (na != NULL)
|
|
ntfs_attr_close(na);
|
|
if (ni != NULL)
|
|
ntfs_inode_close(ni);
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
|
|
void *_buffer, size_t *len)
|
|
{
|
|
nspace *ns = (nspace *)_vol->private_volume;
|
|
vnode *node = (vnode *)_node->private_node;
|
|
attrcookie *cookie = (attrcookie *)_cookie;
|
|
ntfs_inode *ni = NULL;
|
|
ntfs_attr *na = NULL;
|
|
size_t size = *len;
|
|
int total = 0;
|
|
status_t result = B_OK;
|
|
void *tempBuffer = NULL;
|
|
addr_t buffer = (addr_t)_buffer;
|
|
|
|
if (pos < 0) {
|
|
*len = 0;
|
|
return EINVAL;
|
|
}
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
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
|
|
if (na == NULL) {
|
|
*len = 0;
|
|
result = ENOENT; // TODO
|
|
goto exit;
|
|
}
|
|
|
|
if (pos + size > na->data_size)
|
|
size = na->data_size - pos;
|
|
|
|
while (size > 0) {
|
|
s64 bytesRead;
|
|
s64 sizeToRead = size;
|
|
if (tempBuffer != NULL && size > TEMP_BUFFER_SIZE)
|
|
sizeToRead = TEMP_BUFFER_SIZE;
|
|
bytesRead = ntfs_attr_pread(na, pos, sizeToRead,
|
|
tempBuffer != NULL ? tempBuffer : (void*)buffer);
|
|
if (bytesRead <= 0) {
|
|
*len = 0;
|
|
result = errno;
|
|
goto exit;
|
|
}
|
|
if (tempBuffer != NULL
|
|
&& user_memcpy((void*)buffer, tempBuffer, bytesRead) < B_OK) {
|
|
result = B_BAD_ADDRESS;
|
|
goto exit;
|
|
}
|
|
buffer += bytesRead;
|
|
size -= bytesRead;
|
|
pos += bytesRead;
|
|
total += bytesRead;
|
|
if (bytesRead < sizeToRead) {
|
|
ntfs_log_error("ntfs_attr_pread returned less bytes than "
|
|
"requested.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
*len = total;
|
|
|
|
exit:
|
|
free(tempBuffer);
|
|
if (na != NULL)
|
|
ntfs_attr_close(na);
|
|
if (ni != NULL)
|
|
ntfs_inode_close(ni);
|
|
|
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
status_t
|
|
fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
|
|
const void *_buffer, size_t *_length)
|
|
{
|
|
nspace *ns = (nspace *)_vol->private_volume;
|
|
vnode *node = (vnode *)_node->private_node;
|
|
attrcookie *cookie = (attrcookie *)_cookie;
|
|
ntfs_inode *ni = NULL;
|
|
ntfs_attr *na = NULL;
|
|
size_t size = *_length;
|
|
char *attr_name = NULL;
|
|
char *real_name = NULL;
|
|
size_t total = 0;
|
|
status_t result = B_OK;
|
|
void *tempBuffer = NULL;
|
|
addr_t buffer = (addr_t)_buffer;
|
|
|
|
TRACE("%s - ENTER vnode: %d\n", __FUNCTION__, node->vnid);
|
|
|
|
if (ns->flags & B_FS_IS_READONLY) {
|
|
return B_READ_ONLY_DEVICE;
|
|
}
|
|
|
|
if (pos < 0) {
|
|
*_length = 0;
|
|
return EINVAL;
|
|
}
|
|
|
|
LOCK_VOL(ns);
|
|
|
|
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
|
|
if (na == NULL) {
|
|
*_length = 0;
|
|
result = EINVAL;
|
|
goto exit;
|
|
}
|
|
if (cookie->omode & O_APPEND)
|
|
pos = na->data_size;
|
|
|
|
if (pos + size > na->data_size) {
|
|
ntfs_mark_free_space_outdated(ns);
|
|
if (ntfs_attr_truncate(na, pos + size))
|
|
size = na->data_size - pos;
|
|
else
|
|
notify_stat_changed(ns->id, -1, MREF(ni->mft_no), B_STAT_SIZE);
|
|
}
|
|
|
|
if (IS_USER_ADDRESS(_buffer)) {
|
|
tempBuffer = malloc(TEMP_BUFFER_SIZE);
|
|
if (tempBuffer == NULL) {
|
|
*_length = 0;
|
|
result = B_NO_MEMORY;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
while (size > 0) {
|
|
s64 bytesWritten;
|
|
s64 sizeToWrite = size;
|
|
if (tempBuffer != NULL) {
|
|
if (size > TEMP_BUFFER_SIZE)
|
|
sizeToWrite = TEMP_BUFFER_SIZE;
|
|
if (user_memcpy(tempBuffer, (void*)buffer, sizeToWrite) < B_OK) {
|
|
result = B_BAD_ADDRESS;
|
|
goto exit;
|
|
}
|
|
}
|
|
bytesWritten = ntfs_attr_pwrite(na, pos, sizeToWrite,
|
|
tempBuffer != NULL ? tempBuffer : (void*)buffer);
|
|
if (bytesWritten <= 0) {
|
|
ERROR("%s - ntfs_attr_pwrite()<=0\n", __FUNCTION__);
|
|
*_length = 0;
|
|
result = EINVAL;
|
|
goto exit;
|
|
}
|
|
buffer += bytesWritten;
|
|
size -= bytesWritten;
|
|
pos += bytesWritten;
|
|
total += bytesWritten;
|
|
if (bytesWritten < sizeToWrite) {
|
|
ERROR("%s - ntfs_attr_pwrite returned less bytes than "
|
|
"requested.\n", __FUNCTION__);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*_length = total;
|
|
|
|
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, -1, MREF(ni->mft_no),
|
|
real_name, B_ATTR_CHANGED);
|
|
free(attr_name);
|
|
}
|
|
}
|
|
|
|
exit:
|
|
free(tempBuffer);
|
|
if (na != NULL)
|
|
ntfs_attr_close(na);
|
|
if (ni != NULL)
|
|
ntfs_inode_close(ni);
|
|
|
|
TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
|
|
|
|
UNLOCK_VOL(ns);
|
|
|
|
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;
|
|
}
|
|
|
|
strlcpy(ntfs_attr_name, kHaikuAttrPrefix, sizeof(ntfs_attr_name));
|
|
strlcat(ntfs_attr_name, name, sizeof(ntfs_attr_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, -1, 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;
|
|
}
|
|
|