[haiku-commits] r36178 - haiku/trunk/src/add-ons/kernel/file_systems/ntfs

  • From: revol@xxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 12 Apr 2010 02:07:52 +0200 (CEST)

Author: mmu_man
Date: 2010-04-12 02:07:52 +0200 (Mon, 12 Apr 2010)
New Revision: 36178
Changeset: http://dev.haiku-os.org/changeset/36178/haiku

Modified:
   haiku/trunk/src/add-ons/kernel/file_systems/ntfs/attributes.c
   haiku/trunk/src/add-ons/kernel/file_systems/ntfs/ntfs.h
Log:
First implementation of attribute support on NTFS. Currently lists and reads 
named streams as such, but the name mapping is not yet correct.


Modified: haiku/trunk/src/add-ons/kernel/file_systems/ntfs/attributes.c
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ntfs/attributes.c       
2010-04-12 00:05:40 UTC (rev 36177)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ntfs/attributes.c       
2010-04-12 00:07:52 UTC (rev 36178)
@@ -12,6 +12,7 @@
 
 #include <SupportDefs.h>
 #include <KernelExport.h>
+#include <TypeConstants.h>
 
 #include <dirent.h>
 #include <fs_attr.h>
@@ -22,6 +23,8 @@
 #include "attributes.h"
 #include "mime_table.h"
 
+//TODO: notify*()
+
 int32 kBeOSTypeCookie = 0x1234;
 
 status_t set_mime(vnode *node, const char *filename)
@@ -54,102 +57,108 @@
 }
 
 
-status_t 
+status_t
 fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
 {
-       nspace *ns = (nspace *)_vol->private_volume;
-               
-       int     result = B_NO_ERROR;
+       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;
 
-       ERRPRINT("fs_open_attrdir - ENTER\n");
+       status_t result = B_NO_ERROR;
 
+       ERRPRINT("%s - ENTER\n", __FUNCTION__);
+
        LOCK_VOL(ns);
 
-       if ((*_cookie = malloc(sizeof(uint32))) == NULL) {
+       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;
        
-       *(int32 *)(*_cookie) = 0;
-       
 exit:
 
-       ERRPRINT("fs_open_attrdir - EXIT, result is %s\n", strerror(result));
+       if (ctx)
+               ntfs_attr_put_search_ctx(ctx);
+       if (ni)
+               ntfs_inode_close(ni);
        
+       ERRPRINT("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
+       
        UNLOCK_VOL(ns);
        
        return result;
 }
 
-status_t 
+status_t
 fs_close_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
 {
-       nspace *ns = (nspace *)_vol->private_volume;
        
-       ERRPRINT("fs_close_attrdir - ENTER\n");
-
-       LOCK_VOL(ns);
-
-       *(int32 *)_cookie = 1;
        
-       ERRPRINT("fs_close_attrdir - EXIT\n");
-       
-       UNLOCK_VOL(ns);
-       
        return B_NO_ERROR;
 }
 
-status_t 
+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;
 
-       int     result = B_NO_ERROR;
-
        LOCK_VOL(ns);
-               
-       ERRPRINT("fs_free_attrib_dir_cookie - ENTER\n");
 
-       if (_cookie == NULL) {
-               ERRPRINT("fs_free_attrib_dir_cookie - error: called with null 
cookie\n");
-               result =  EINVAL;
-               goto    exit;
-       }
-       
-       *(int32 *)_cookie = 0x87654321;
-       free(_cookie);
+       if (cookie->ctx)
+               ntfs_attr_put_search_ctx(cookie->ctx);
+       if (cookie->inode)
+               ntfs_inode_close(cookie->inode);
 
-exit:
+       UNLOCK_VOL(ns);
 
-       ERRPRINT("fs_free_attrib_dir_cookie - EXIT, result is %s\n", 
strerror(result));
-
-       UNLOCK_VOL(ns);
-       
-       return result;
+       free(cookie);
+       return B_NO_ERROR;
 }
 
-status_t 
+status_t
 fs_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
 {
-       nspace *ns = (nspace *)_vol->private_volume;
+       nspace *ns = (nspace*)_vol->private_volume;
+       attrdircookie *cookie = (attrdircookie *)_cookie;
+       status_t result = B_NO_ERROR;
 
-       int     result = B_NO_ERROR;
+       ERRPRINT("%s - ENTER\n", __FUNCTION__);
 
        LOCK_VOL(ns);
-       
-       ERRPRINT("fs_rewind_attrcookie  - ENTER\n");
 
-       if (_cookie == NULL) {
-               ERRPRINT("fs_rewind_attrcookie - error: fs_rewind_attrcookie 
called with null cookie\n");
-               result =  EINVAL;
-               goto    exit;
+       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;
        }
-       
-       *(uint32 *)_cookie = 0;
 
-exit:
+//exit:
 
-       ERRPRINT("fs_rewind_attrcookie - EXIT, result is %s\n", 
strerror(result));
+       ERRPRINT("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
 
        UNLOCK_VOL(ns);
        
@@ -157,67 +166,146 @@
 }
 
 
-status_t 
+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;
+       attrdircookie *cookie = (attrdircookie *)_cookie;
+       uint32 numEntries = 0;
+       status_t result = B_NO_ERROR;
 
-       int32 *cookie = (int32 *)_cookie;
+       if (cookie->ctx == NULL)
+               panic("cookie->ctx == NULL");
 
        LOCK_VOL(ns);
 
-       ERRPRINT("fs_read_attrdir - ENTER\n");
+       ERRPRINT("%s - ENTER\n", __FUNCTION__);
 
-       *num = 0;
 
-       if ((*cookie == 0) && (node->mime)) {
-               *num = 1;
-               
-               entry->d_ino = node->vnid;
-               entry->d_dev = ns->id;
-               entry->d_reclen = 10;
-               strcpy(entry->d_name, "BEOS:TYPE");
+       while (!(result = ntfs_attrs_walk(cookie->ctx))) {
+               ATTR_RECORD *attr = cookie->ctx->attr;
+               if (attr->type == AT_DATA) {
+                       // it's the actual file body
+                       if (attr->name_length == 0)
+                               continue;
+                       
+                       char *name = ntfs_attr_name_get((const ntfschar 
*)(((char *)attr)
+                               + attr->name_offset), attr->name_length);
+                       dprintf("found AT_DATA '%s'\n", name);
+                       bufsize = MIN(bufsize, sizeof(struct dirent) + 
strlen(name) + 1);
+                       entry->d_ino = node->vnid;
+                       entry->d_dev = ns->id;
+                       entry->d_reclen = sizeof(struct dirent) + strlen(name);
+                       //XXX size
+                       strcpy(entry->d_name, name);
+                       ntfs_attr_name_free(&name);
+                       numEntries++;
+                       if (numEntries >= *num)
+                               break;
+                       break;
+               }
        }
+       if (result && errno != ENOENT) {
+               result = errno;
+               goto exit;
+       } else {
+               result = B_OK;
+       }
 
-       *cookie = 1;
 
-       ERRPRINT("fs_read_attrdir - EXIT\n");
+exit:
 
+       ERRPRINT("%s - EXIT, result is %s, *num %d\n", __FUNCTION__, 
strerror(result), *num);
+
        UNLOCK_VOL(ns);
        
-       return B_NO_ERROR;
+       if (result)
+               *num = 0;
+       else
+               *num = numEntries;
+
+       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;     
-       int     result = B_NO_ERROR;
+       nspace *ns = (nspace*)_vol->private_volume;
+       vnode *node = (vnode*)_node->private_node;
+       attrcookie *cookie = NULL;
+       ntfschar *unicode = NULL;
+       int ulen;
+       ntfs_inode *ni = NULL;
+       ntfs_attr *na = NULL;
+       status_t result = B_NO_ERROR;
 
+       ERRPRINT("%s - ENTER\n", __FUNCTION__);
+
        LOCK_VOL(ns);
-       
-       ERRPRINT("fs_open_attrib - ENTER\n");
 
-       if (strcmp(name, "BEOS:TYPE")) {
-               result = ENOENT;
-               goto    exit;
+       if (node == NULL) {
+               result = EINVAL;
+               goto exit;
        }
-       
-       if (node->mime == NULL) {
-               result = ENOENT;
-               goto    exit;
+
+       ni = ntfs_inode_open(ns->ntvol, node->vnid);
+       if (ni == NULL) {
+               result = errno;
+               goto exit;
        }
 
-       *_cookie = &kBeOSTypeCookie;
-       
+       // UXA demangling TODO
+
+       // check for EA first... TODO: WRITEME
+
+
+       // check for a named stream
+       if (true) {
+               unicode = ntfs_calloc(MAX_PATH);
+               ulen = ntfs_mbstoucs(name, &unicode);
+               if (ulen < 0) {
+                       result = EILSEQ;
+                       goto exit;
+               }
+
+               na = ntfs_attr_open(ni, AT_DATA, unicode, ulen);
+               if (na) {
+                       if (openMode & O_TRUNC) {
+                               if (ntfs_attr_truncate(na, 0))
+                                       result = errno;
+                       }
+               }
+       }
+
+
+       cookie = (attrcookie*)ntfs_calloc(sizeof(attrcookie));
+
+       if (cookie != NULL) {
+               cookie->omode = openMode;
+               *_cookie = (void*)cookie;
+               cookie->inode = ni;
+               cookie->stream = na;
+               ni = NULL;
+               na = NULL;
+       } else
+               result = ENOMEM;
+
 exit:
+       if (unicode)
+               free(unicode);
 
-       ERRPRINT("fs_open_attrib - EXIT, result is %s\n", strerror(result));
+       if (na)
+               ntfs_attr_close(na);
 
+       if (ni)
+               ntfs_inode_close(ni);
+
+       ERRPRINT("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
+
        UNLOCK_VOL(ns);
-               
+
        return result;
 }
 
@@ -230,8 +318,21 @@
 
 
 status_t
-fs_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node, void *cookie)
+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->stream)
+               ntfs_attr_close(cookie->stream);
+       if (cookie->inode)
+               ntfs_inode_close(cookie->inode);
+
+       UNLOCK_VOL(ns);
+
+       free(cookie);
        return B_NO_ERROR;
 }
 
@@ -240,30 +341,22 @@
 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;
-       int     result = B_NO_ERROR;
+       //vnode *node = (vnode *)_node->private_node;
+       attrcookie *cookie = (attrcookie *)_cookie;
+       //ntfs_inode *ni = cookie->inode;
+       ntfs_attr *na = cookie->stream;
 
+       //status_t result = B_NO_ERROR;
+
        LOCK_VOL(ns);
 
-       ERRPRINT("fs_read_attr_stat - ENTER\n");
+       //ERRPRINT("%s - ENTER\n", __FUNCTION__);
 
-       if (_cookie != &kBeOSTypeCookie) {
-               result = ENOENT;
-               goto    exit;
-       }
+       stat->st_type = B_RAW_TYPE;
+       stat->st_size = na ? na->data_size : 0;
 
-       if (node->mime == NULL) {
-               result = ENOENT;
-               goto    exit;
-       }
-       
-       stat->st_type = MIME_STRING_TYPE;
-       stat->st_size = strlen(node->mime) + 1;
+//exit:
 
-exit:
-
-       ERRPRINT("fs_read_attrib_stat - EXIT, result is %s\n", 
strerror(result));
-
        UNLOCK_VOL(ns);
        
        return B_NO_ERROR;
@@ -271,39 +364,59 @@
 
 
 status_t 
-fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,void 
*buffer, size_t *_length)
+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;
+       //vnode *node = (vnode *)_node->private_node;
+       attrcookie *cookie = (attrcookie *)_cookie;
+       ntfs_inode *ni = cookie->inode;
+       ntfs_attr *na = cookie->stream;
+       size_t  size = *len;
+       int total = 0;
+       status_t result = B_NO_ERROR;
 
-       int     result = B_NO_ERROR;
+       if (pos < 0) {
+               *len = 0;
+               return EINVAL;
+       }
 
+
        LOCK_VOL(ns);
 
-       ERRPRINT("fs_read_attr - ENTER\n");
+       ERRPRINT("%s - ENTER\n", __FUNCTION__);
 
-       if (_cookie != &kBeOSTypeCookie) {
-               result = ENOENT;
-               goto    exit;
+       // it is a named stream
+       if (na) {
+               if (pos + size > na->data_size)
+                       size = na->data_size - pos;
+
+               while (size) {
+                       off_t bytesRead = ntfs_attr_pread(na, pos, size, 
buffer);
+                       if (bytesRead < (s64)size) {
+                               ntfs_log_error("ntfs_attr_pread returned less 
bytes than "
+                                       "requested.\n");
+                       }
+                       if (bytesRead <= 0) {
+                               *len = 0;
+                               result = EINVAL;
+                               goto exit;
+                       }
+                       size -= bytesRead;
+                       pos += bytesRead;
+                       total += bytesRead;
+               }
+
+               *len = total;
+       } else {
+               *len = 0;
+               result = ENOENT; // TODO
        }
-                       
-       if (node->mime == NULL) {
-               result = ENOENT;
-               goto    exit;
-       }
-       
-       if ((pos < 0) || (pos > strlen(node->mime))) {
-               result = EINVAL;
-               goto    exit;
-       }
 
-       strncpy(buffer, node->mime + pos, *_length - 1);
-       ((char *)buffer)[*_length - 1] = 0;
-       *_length = strlen(buffer) + 1;
-       
+       fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME); // XXX needed ?
+
 exit:
        
-       ERRPRINT("fs_read_attr - EXIT, result is %s\n", strerror(result));
+       ERRPRINT("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
 
        UNLOCK_VOL(ns);
        
@@ -315,22 +428,74 @@
 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 = cookie->inode;
+       ntfs_attr *na = cookie->stream;
+       size_t  size = *_length;
+       int total = 0;
+       status_t result = B_NO_ERROR;
 
-       int     result = B_NO_ERROR;
-       
+       ERRPRINT("%s - ENTER!!\n", __FUNCTION__);
+       if (ns->flags & B_FS_IS_READONLY) {
+               ERRPRINT("ntfs is read-only\n");
+               return EROFS;
+       }
+
+       if (pos < 0) {
+               *_length = 0;
+               return EINVAL;
+       }
+
+
        LOCK_VOL(ns);
-       
-       ERRPRINT("fs_write_attr - ENTER\n");
 
-       *_length = 0;
+       ERRPRINT("%s - ENTER\n", __FUNCTION__);
 
-       if (_cookie != &kBeOSTypeCookie) {
-               result = ENOSYS;
+       // it is a named stream
+       if (na) {
+               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, MREF(ni->mft_no), 
B_STAT_SIZE);
+               }
+
+               while (size) {
+                       off_t bytesWritten = ntfs_attr_pwrite(na, pos, size, 
buffer);
+                       if (bytesWritten < (s64)size)
+                               ERRPRINT("%s - ntfs_attr_pwrite returned less 
bytes than requested.\n",
+                                       __FUNCTION__);
+                       if (bytesWritten <= 0) {
+                               ERRPRINT(("%s - ntfs_attr_pwrite()<=0\n", 
__FUNCTION__));
+                               *_length = 0;
+                               result = EINVAL;
+                               goto exit;
+                       }
+                       size -= bytesWritten;
+                       pos += bytesWritten;
+                       total += bytesWritten;
+               }
+
+               *_length = total;
+       } else {
+               *_length = 0;
+               return EINVAL;
        }
+
        
-       ERRPRINT("fs_write_attrib - EXIT, result is %s\n", strerror(result));
+       if (total > 0)
+               fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME); // XXX 
needed ?
 
+exit:
+       
+       ERRPRINT("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
+
        UNLOCK_VOL(ns);
-               
+       
        return result;
 }

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ntfs/ntfs.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ntfs/ntfs.h     2010-04-12 
00:05:40 UTC (rev 36177)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ntfs/ntfs.h     2010-04-12 
00:07:52 UTC (rev 36178)
@@ -91,6 +91,20 @@
        off_t   last_size;
 } filecookie;
 
+typedef struct attrcookie
+{
+       int     omode;
+       ntfs_inode *inode;
+       ntfs_attr *stream;
+       // MFT ref for EA ?
+} attrcookie;
+
+typedef struct attrdircookie
+{
+       ntfs_inode *inode;
+       ntfs_attr_search_ctx *ctx;
+} attrdircookie;
+
 #define ntfs_mark_free_space_outdated(ns) (ns->state |= 
(NF_FreeClustersOutdate | NF_FreeMFTOutdate));
 
 


Other related posts:

  • » [haiku-commits] r36178 - haiku/trunk/src/add-ons/kernel/file_systems/ntfs - revol