diff --git a/src/add-ons/kernel/file_systems/ntfs/attributes.c b/src/add-ons/kernel/file_systems/ntfs/attributes.c index 98759a7b17..adc1fd8a6c 100644 --- a/src/add-ons/kernel/file_systems/ntfs/attributes.c +++ b/src/add-ons/kernel/file_systems/ntfs/attributes.c @@ -1,769 +1,770 @@ -/* - 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 -#include -#include -#include - -#include -#include -#include - -#include - -#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 sizeToRead = size; - if (tempBuffer != NULL && size > TEMP_BUFFER_SIZE) - sizeToRead = TEMP_BUFFER_SIZE; - s64 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 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; - } - } - s64 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; -} +/* + 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 +#include +#include +#include + +#include +#include +#include + +#include + +#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 sizeToRead = size; + if (tempBuffer != NULL && size > TEMP_BUFFER_SIZE) + sizeToRead = TEMP_BUFFER_SIZE; + s64 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 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; + } + } + s64 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; +} + diff --git a/src/add-ons/kernel/file_systems/ntfs/attributes.h b/src/add-ons/kernel/file_systems/ntfs/attributes.h index 4e29b4d574..c618ffacd0 100644 --- a/src/add-ons/kernel/file_systems/ntfs/attributes.h +++ b/src/add-ons/kernel/file_systems/ntfs/attributes.h @@ -1,39 +1,39 @@ -/* - Copyright 1999-2001, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ -/* attributes.h - * handles mime type information for ntfs - * gets/sets mime information in vnode - */ -#ifndef NTFS_ATTRIBUTES_H -#define NTFS_ATTRIBUTES_H - - -#include - -#include "ntfs.h" - -status_t fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name, - uint32 type, int openMode, void** _cookie); -status_t fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie); -status_t fs_close_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie); -status_t fs_free_attrib_dir_cookie(fs_volume *_vol, fs_vnode *_node, - void *_cookie); -status_t fs_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie); -status_t fs_read_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie, - struct dirent *buf, size_t bufsize, uint32 *num); -status_t fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name, - int openMode, void **_cookie); -status_t fs_close_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie); -status_t fs_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node, void *cookie); -status_t fs_read_attrib_stat(fs_volume *_vol, fs_vnode *_node, void *cookie, - struct stat *stat); -status_t fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie, - off_t pos, void *buffer, size_t *_length); -status_t fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie, - 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 - +/* + Copyright 1999-2001, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ +/* attributes.h + * handles mime type information for ntfs + * gets/sets mime information in vnode + */ +#ifndef NTFS_ATTRIBUTES_H +#define NTFS_ATTRIBUTES_H + + +#include + +#include "ntfs.h" + +status_t fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name, + uint32 type, int openMode, void** _cookie); +status_t fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie); +status_t fs_close_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie); +status_t fs_free_attrib_dir_cookie(fs_volume *_vol, fs_vnode *_node, + void *_cookie); +status_t fs_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie); +status_t fs_read_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie, + struct dirent *buf, size_t bufsize, uint32 *num); +status_t fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name, + int openMode, void **_cookie); +status_t fs_close_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie); +status_t fs_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node, void *cookie); +status_t fs_read_attrib_stat(fs_volume *_vol, fs_vnode *_node, void *cookie, + struct stat *stat); +status_t fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie, + off_t pos, void *buffer, size_t *_length); +status_t fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie, + 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 +