diff --git a/src/add-ons/kernel/file_systems/ntfs/attributes.c b/src/add-ons/kernel/file_systems/ntfs/attributes.c index bef6dcd11c..727b6d6960 100644 --- a/src/add-ons/kernel/file_systems/ntfs/attributes.c +++ b/src/add-ons/kernel/file_systems/ntfs/attributes.c @@ -8,8 +8,6 @@ */ -#define MIME_STRING_TYPE 'MIMS' - #include #include #include @@ -23,7 +21,9 @@ #include "mime_table.h" #include "ntfs.h" -//TODO: notify*() + +const char* kHaikuAttrPrefix={"HAIKU-XATTR:"}; + status_t 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: - if (ctx) + if (ctx != NULL) ntfs_attr_put_search_ctx(ctx); - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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__); - 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); - 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_dev = ns->id; - entry->d_reclen = sizeof(struct dirent) + strlen(name); + entry->d_reclen = sizeof(struct dirent) + strlen(real_name); //XXX size - strcpy(entry->d_name, name); + strcpy(entry->d_name, real_name); ntfs_attr_name_free(&name); numEntries++; if (numEntries >= *num) @@ -210,9 +218,13 @@ fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name, int ulen; ntfs_inode *ni = 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); @@ -224,7 +236,7 @@ fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name, ni = ntfs_inode_open(ns->ntvol, node->vnid); if (ni == NULL) { result = errno; - ERROR("%s - inode_open: %s\n", __FUNCTION__, strerror(result)); + TRACE("%s - inode_open: %s\n", __FUNCTION__, strerror(result)); goto exit; } @@ -235,59 +247,66 @@ fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name, // check for a named stream if (true) { + char ntfs_attr_name[MAX_PATH] = {0}; + strcat(ntfs_attr_name, kHaikuAttrPrefix); + strcat(ntfs_attr_name,name); + uname = ntfs_calloc(MAX_PATH); - ulen = ntfs_mbstoucs(name, &uname); + ulen = ntfs_mbstoucs(ntfs_attr_name, &uname); if (ulen < 0) { result = EILSEQ; - ERROR("%s - mb alloc: %s\n", __FUNCTION__, strerror(result)); + TRACE("%s - mb alloc: %s\n", __FUNCTION__, strerror(result)); goto exit; } na = ntfs_attr_open(ni, AT_DATA, uname, ulen); - if (na) { - result = EEXIST; - ERROR("%s - ntfs_attr_open: %s\n", __FUNCTION__, - strerror(result)); - goto exit; + 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_non_resident_attr_record_add(ni, AT_DATA, uname, ulen, 0, 32, - // 0) < 0) { - if (ntfs_attr_add(ni, AT_DATA, uname, ulen, NULL, 0) < 0) { + if(ntfs_attr_pwrite(na, 0, sizeof(uint32), &type) < 0 ) { 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; } } - 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; + cookie->vnid = node->vnid; + cookie->uname = uname; + cookie->uname_len = ulen; + cookie->type = type; + uname = NULL; } else result = ENOMEM; exit: - if (uname) + if (uname != NULL) free(uname); - if (na) + if (na != NULL) ntfs_attr_close(na); - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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_attr *na = NULL; 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); @@ -333,18 +353,33 @@ fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name, // check for a named stream if (true) { + char ntfs_attr_name[MAX_PATH] = {0}; + strcat(ntfs_attr_name, kHaikuAttrPrefix); + strcat(ntfs_attr_name, name); + uname = ntfs_calloc(MAX_PATH); - ulen = ntfs_mbstoucs(name, &uname); + 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) { + if (na != NULL) { if (openMode & O_TRUNC) { - if (ntfs_attr_truncate(na, 0)) - result = errno; + 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; @@ -357,22 +392,23 @@ fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name, if (cookie != NULL) { cookie->omode = openMode; + cookie->vnid = node->vnid; + cookie->uname = uname; + cookie->uname_len = ulen; + cookie->type = type; *_cookie = (void*)cookie; - cookie->inode = ni; - cookie->stream = na; - ni = NULL; - na = NULL; + uname = NULL; } else result = ENOMEM; exit: - if (uname) + if (uname != NULL) free(uname); - if (na) + if (na != NULL) ntfs_attr_close(na); - if (ni) + if (ni != NULL) ntfs_inode_close(ni); TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result)); @@ -386,6 +422,8 @@ exit: status_t 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; } @@ -398,10 +436,8 @@ fs_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node, void *_cookie) LOCK_VOL(ns); - if (cookie->stream) - ntfs_attr_close(cookie->stream); - if (cookie->inode) - ntfs_inode_close(cookie->inode); + if (cookie->uname != NULL) + free(cookie->uname); UNLOCK_VOL(ns); @@ -415,21 +451,33 @@ 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; + 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; + ntfs_inode *ni = NULL; + ntfs_attr *na = NULL; + status_t result = B_NO_ERROR; 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_size = na ? na->data_size : 0; + stat->st_type = cookie->type; + 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); @@ -442,10 +490,10 @@ 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; + ntfs_inode *ni = NULL; + ntfs_attr *na = NULL; size_t size = *len; int total = 0; 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; } - 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 - if (na) { + if (na != NULL) { 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 " + ERROR("ntfs_attr_pread returned less bytes than " "requested.\n"); } if (bytesRead <= 0) { @@ -487,10 +547,12 @@ fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos, result = ENOENT; // TODO } - fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME); // XXX needed ? - 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)); UNLOCK_VOL(ns); @@ -500,22 +562,24 @@ exit: 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) { 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; + ntfs_inode *ni = NULL; + ntfs_attr *na = NULL; size_t size = *_length; + char *attr_name = NULL; + char *real_name = NULL; int total = 0; status_t result = B_NO_ERROR; - TRACE("%s - ENTER!!\n", __FUNCTION__); - if (ns->flags & B_FS_IS_READONLY) { - ERROR("ntfs is read-only\n"); - return EROFS; + TRACE("%s - ENTER vnode: %d\n", __FUNCTION__, node->vnid); + + if (ns->flags & B_FS_IS_READONLY) { + return B_READ_ONLY_DEVICE; } if (pos < 0) { @@ -523,13 +587,23 @@ fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie,off_t pos, return EINVAL; } - 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 - if (na) { + if (na != NULL) { if (cookie->omode & O_APPEND) pos = na->data_size; @@ -560,15 +634,27 @@ fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie,off_t pos, *_length = total; } else { *_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)); UNLOCK_VOL(ns); @@ -576,3 +662,68 @@ exit: 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; +} diff --git a/src/add-ons/kernel/file_systems/ntfs/attributes.h b/src/add-ons/kernel/file_systems/ntfs/attributes.h index a7d924ef81..4e29b4d574 100644 --- a/src/add-ons/kernel/file_systems/ntfs/attributes.h +++ b/src/add-ons/kernel/file_systems/ntfs/attributes.h @@ -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); 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 diff --git a/src/add-ons/kernel/file_systems/ntfs/fake_attributes.c b/src/add-ons/kernel/file_systems/ntfs/fake_attributes.c index 517add5d57..a2fd0964ec 100644 --- a/src/add-ons/kernel/file_systems/ntfs/fake_attributes.c +++ b/src/add-ons/kernel/file_systems/ntfs/fake_attributes.c @@ -22,12 +22,13 @@ #include "mime_table.h" int32 kBeOSTypeCookie = 0x1234; +char *kFailBackMime = {"application/octet-stream"}; status_t set_mime(vnode *node, const char *filename) { struct ext_mime *p; int32 namelen, ext_len; - node->mime = NULL; + node->mime = kFailBackMime; namelen = strlen(filename); for (p=mimes; p->extension; p++) { @@ -67,7 +68,7 @@ fake_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie) 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); @@ -134,7 +135,7 @@ fake_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie) TRACE("fake_rewind_attrcookie - ENTER\n"); if (_cookie == NULL) { - TRACE("fake_rewind_attrcookie - error: fs_rewind_attrcookie" + TRACE("fake_rewind_attrcookie - error: fake_rewind_attrcookie" "called with null cookie\n"); result = EINVAL; 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_dev = ns->id; - entry->d_reclen = 10; + entry->d_reclen = sizeof(struct dirent)+10; 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); - 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; goto exit; } if (node->mime == NULL) { + TRACE("fake_open_attrib - MIME = NULL\n"); result = ENOENT; goto exit; } diff --git a/src/add-ons/kernel/file_systems/ntfs/fs_func.c b/src/add-ons/kernel/file_systems/ntfs/fs_func.c index 3427e4b314..a50c6f6b2a 100644 --- a/src/add-ons/kernel/file_systems/ntfs/fs_func.c +++ b/src/add-ons/kernel/file_systems/ntfs/fs_func.c @@ -118,16 +118,22 @@ static u64 ntfs_inode_lookup(fs_volume *_vol, ino_t parent, const char *name) { nspace *ns = (nspace*)_vol->private_volume; - + ntfschar *uname = NULL; + int uname_len; u64 ino = (u64)-1; u64 inum; - ntfs_inode *dir_ni; + ntfs_inode *dir_ni; /* Open target directory. */ dir_ni = ntfs_inode_open(ns->ntvol, parent); if (dir_ni) { + uname_len = ntfs_mbstoucs(name, &uname); + if (uname_len < 0) { + errno = EINVAL; + return (ino); + } /* 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 */ if (MREF(inum) <= 1) { inum = (u64)-1; @@ -139,6 +145,8 @@ ntfs_inode_lookup(fs_volume *_vol, ino_t parent, const char *name) else ino = MREF(inum); } + if (uname != NULL) + free(uname); return (ino); } @@ -149,137 +157,53 @@ ntfs_remove(fs_volume *_vol, ino_t parent, const char *name) nspace *ns = (nspace*)_vol->private_volume; ntfschar *uname = NULL; - ntfs_inode *dir_ni = NULL, *ni = NULL; - int res = B_OK, uname_len; + ntfs_inode *ni = NULL; + ntfs_inode *dir_ni = NULL; + int result = B_OK; + int uname_len; u64 iref; /* Open parent directory. */ dir_ni = ntfs_inode_open(ns->ntvol, parent); if (!dir_ni) { - res = EINVAL; + result = EINVAL; goto exit; } /* Generate unicode filename. */ uname_len = ntfs_mbstoucs(name, &uname); if (uname_len < 0) { - res = EINVAL; + result = EINVAL; goto exit; } /* 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) { - res = EINVAL; + result = EINVAL; goto exit; } /* deny unlinking metadata files */ if (MREF(iref) < FILE_first_user) { - res = EINVAL; + result = EINVAL; goto exit; } ni = ntfs_inode_open(ns->ntvol, MREF(iref)); if (!ni) { - res = EINVAL; + result = EINVAL; goto exit; } 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 */ ni = dir_ni = NULL; exit: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); - if (dir_ni) + if (dir_ni != NULL) ntfs_inode_close(dir_ni); free(uname); - return res; -} - - -static status_t -do_unlink(fs_volume *_vol, vnode *dir, const char *name, bool isdir) -{ - nspace *ns = (nspace*)_vol->private_volume; - ino_t vnid; - vnode *node = NULL; - ntfs_inode *ni = NULL; - ntfs_inode *bi = NULL; - ntfschar *uname = NULL; - int unameLength; - - status_t result = B_NO_ERROR; - - unameLength = ntfs_mbstoucs(name, &uname); - if (unameLength < 0) { - result = EINVAL; - goto exit1; - } - - bi = ntfs_inode_open(ns->ntvol, dir->vnid); - if (bi == NULL) { - result = ENOENT; - goto exit1; - } - - vnid = MREF(ntfs_inode_lookup_by_name(bi, uname, unameLength)); - - if ( vnid == (u64)-1 || vnid == FILE_root) { - result = EINVAL; - goto exit1; - } - - result = get_vnode(_vol, vnid, (void**)&node); - - if (result != B_NO_ERROR || node==NULL) { - result = ENOENT; - goto exit1; - } - - ni = ntfs_inode_open(ns->ntvol, node->vnid); - if (ni == NULL) { - result = ENOENT; - goto exit2; - } - - if (isdir) { - if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { - result = ENOTDIR; - goto exit2; - } - if (ntfs_check_empty_dir(ni)<0) { - result = ENOTEMPTY; - goto exit2; - } - } else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { - result = EISDIR; - goto exit2; - } - - // TODO: the file must not be deleted here, only unlinked! - if (ntfs_delete(ns->ntvol, (char*)NULL, ni, bi, uname, unameLength)) - result = errno; - - ni = bi = NULL; - - node->parent_vnid = dir->vnid; - - notify_entry_removed(ns->id, dir->vnid, name, vnid); - - remove_vnode(_vol, vnid); - - result = 0; -exit2: - put_vnode(_vol, vnid); -exit1: - free(uname); - - if (ni) - ntfs_inode_close(ni); - if (bi) - ntfs_inode_close(bi); - return result; } @@ -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_stat = fake_read_attrib_stat; gNTFSVnodeOps.write_attr = fake_write_attrib; + gNTFSVnodeOps.remove_attr = NULL; } 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) { ERROR("ntfs is read-only\n"); - return EROFS; + return B_READ_ONLY_DEVICE; } 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; vnode *baseNode = (vnode*)_dir->private_node; vnode *newNode = NULL; - ntfschar *unicode = NULL; - ntfs_inode *bi = NULL; + ntfschar *uname = NULL; + ntfs_inode *dir_ni = NULL; status_t result = B_NO_ERROR; - int len; + int uname_len; 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) result = ENOENT; } else { - unicode = ntfs_calloc(MAX_PATH); - len = ntfs_mbstoucs(file, &unicode); - if (len < 0) { + uname = ntfs_calloc(MAX_PATH); + uname_len = ntfs_mbstoucs(file, &uname); + if (uname_len < 0) { result = EILSEQ; goto exit; } - bi = ntfs_inode_open(ns->ntvol, baseNode->vnid); - if (!bi) { + dir_ni = ntfs_inode_open(ns->ntvol, baseNode->vnid); + if (dir_ni == NULL) { result = ENOENT; 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); - ntfs_inode_close(bi); + ntfs_inode_close(dir_ni); if (*vnid == (u64)-1) { result = EINVAL; @@ -636,8 +561,8 @@ fs_walk(fs_volume *_vol, fs_vnode *_dir, const char *file, ino_t *vnid) exit: TRACE("fs_walk - EXIT, result is %s\n", strerror(result)); - if (unicode) - free(unicode); + if (uname) + free(uname); UNLOCK_VOL(ns); @@ -676,7 +601,7 @@ fs_get_vnode_name(fs_volume *_vol, fs_vnode *_vnode, char *buffer, strlcpy(buffer, name, bufferSize); exit: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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); exit: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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); exit: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); TRACE("fs_fsync: EXIT\n"); @@ -1062,10 +987,10 @@ fs_open(fs_volume *_vol, fs_vnode *_node, int omode, void **_cookie) result = ENOMEM; exit: - if (na) + if (na != NULL) ntfs_attr_close(na); - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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; ntfs_attr *na = NULL; ntfs_inode *ni = NULL; - ntfs_inode *bi = NULL; + ntfs_inode *dir_ni = NULL; ntfschar *uname = NULL; status_t result = B_NO_ERROR; int unameLength; - if (ns->flags & B_FS_IS_READONLY) { - ERROR("ntfs is read-only\n"); - return EROFS; - } + if (ns->flags & B_FS_IS_READONLY) { + return B_READ_ONLY_DEVICE; + } LOCK_VOL(ns); @@ -1111,13 +1035,13 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode, goto exit; } - bi = ntfs_inode_open(ns->ntvol, dir->vnid); - if (bi == NULL) { + dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid); + if (dir_ni == NULL) { result = ENOENT; goto exit; } - if (!(bi->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { + if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { result = EINVAL; goto exit; } @@ -1137,53 +1061,51 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode, goto exit; } - ni = ntfs_pathname_to_inode(ns->ntvol, bi, name); - if (ni) { + ni = ntfs_pathname_to_inode(ns->ntvol, dir_ni, name); + if (ni != NULL) { // file exists *_vnid = MREF(ni->mft_no); if (omode & O_TRUNC) { na = ntfs_attr_open(ni, AT_DATA, NULL, 0); - if (na) { + if (na != NULL) { if (ntfs_attr_truncate(na, 0)) result = errno; + ntfs_attr_close(na); } else result = errno; } ntfs_inode_close(ni); } else { le32 securid = const_cpu_to_le32(0); - ni = ntfs_create(bi, securid, uname, unameLength, S_IFREG); - if (ni) { - *_vnid = MREF(ni->mft_no); - + ni = ntfs_create(dir_ni, securid, uname, unameLength, S_IFREG); + if (ni != NULL) { + ino_t vnid = MREF(ni->mft_no); + newNode = (vnode*)ntfs_calloc(sizeof(vnode)); if (newNode == NULL) { result = ENOMEM; goto exit; } - if (ntfs_inode_close_in_dir(ni, bi)) { - result = EINVAL; - goto exit; - } - - newNode->vnid = *_vnid; - newNode->parent_vnid = MREF(bi->mft_no); + newNode->vnid = vnid; + newNode->parent_vnid = MREF(dir_ni->mft_no); - if (ns->fake_attrib) - set_mime(newNode, name); - ni->flags |= FILE_ATTR_ARCHIVE; - ntfs_inode_update_mbsname(bi, name, ni->mft_no); NInoSetDirty(ni); - result = B_NO_ERROR; - result = publish_vnode(_vol, *_vnid, (void*)newNode, &gNTFSVnodeOps, + result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps, S_IFREG, 0); + + if (ntfs_inode_close_in_dir(ni, dir_ni)) { + result = EINVAL; + goto exit; + } + + *_vnid = vnid; ntfs_mark_free_space_outdated(ns); - fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME); - notify_entry_created(ns->id, MREF(bi->mft_no), name, *_vnid); + 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; } @@ -1193,12 +1115,12 @@ exit: *_cookie = cookie; else free(cookie); - - if (na) - ntfs_attr_close(na); - if (bi) - ntfs_inode_close(bi); - free(uname); + + if (dir_ni != NULL) + ntfs_inode_close(dir_ni); + + if (uname != NULL) + free(uname); 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); - if (!na) { + if (na == NULL) { *len = 0; result = EINVAL; 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); exit: - if (na) + if (na != NULL) ntfs_attr_close(na); exit2: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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) { ERROR("ntfs is read-only\n"); - return EROFS; + return B_READ_ONLY_DEVICE; } 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); - if (!na) { + if (na == NULL) { ERROR("fs_write - ntfs_attr_open()==NULL\n"); *len = 0; result = EINVAL; @@ -1374,10 +1296,10 @@ fs_write(fs_volume *_vol, fs_vnode *_dir, void *_cookie, off_t offset, TRACE("fs_write - OK\n"); exit: - if (na) + if (na != NULL) ntfs_attr_close(na); exit2: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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: free(intxFile); - if (na) + if (na != NULL) ntfs_attr_close(na); - if (ni) + if (ni != NULL) ntfs_inode_close(ni); 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; vnode *dir = (vnode*)_dir->private_node; - ntfs_inode *sym = NULL; - ntfs_inode *bi = NULL; - vnode *symnode = NULL; + ntfs_inode *ni = NULL; + ntfs_inode *dir_ni = NULL; + vnode *newNode = NULL; ntfschar *uname = NULL; ntfschar *utarget = NULL; int unameLength; int utargetLength; status_t result = B_NO_ERROR; - int fmode = FS_FILE_MODE; - le32 securid = 0; + le32 securid = const_cpu_to_le32(0); + + if (ns->flags & B_FS_IS_READONLY) { + return B_READ_ONLY_DEVICE; + } LOCK_VOL(ns); @@ -1544,10 +1469,10 @@ fs_create_symlink(fs_volume *_vol, fs_vnode *_dir, const char *name, result = EINVAL; goto exit; } - - bi = ntfs_inode_open(ns->ntvol, dir->vnid); - if (bi == NULL) { - result = ENOENT; + + dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid); + if (dir_ni == NULL) { + result = ENOENT; goto exit; } @@ -1563,51 +1488,45 @@ fs_create_symlink(fs_volume *_vol, fs_vnode *_dir, const char *name, goto exit; } - sym = ntfs_create_symlink(bi, securid, uname, unameLength, utarget, + ni = ntfs_create_symlink(dir_ni, securid, uname, unameLength, utarget, utargetLength); - if (sym == NULL) { - result = EINVAL; - goto exit; - } - - symnode = (vnode*)ntfs_calloc(sizeof(vnode)); - 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); + if (ni) { + ino_t vnid = MREF(ni->mft_no); + newNode = (vnode*)ntfs_calloc(sizeof(vnode)); + if (newNode == NULL) { + result = ENOMEM; + goto exit; } - } - result = publish_vnode(_vol, MREF(sym->mft_no), symnode, &gNTFSVnodeOps, - S_IFLNK | fmode, 0); - if (result != 0) { - ERROR("fs_symlink - new_vnode failed for vnid %Ld: %s\n", - MREF(sym->mft_no), strerror(result)); - } + newNode->vnid = vnid; + newNode->parent_vnid = MREF(dir_ni->mft_no); + + ni->flags |= FILE_ATTR_ARCHIVE; + NInoSetDirty(ni); - put_vnode(_vol, MREF(sym->mft_no)); - fs_ntfs_update_times(_vol, sym, NTFS_UPDATE_CTIME); - fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME); + result = B_NO_ERROR; + result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps, + 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: - if (sym) - ntfs_inode_close(sym); - if (bi) - ntfs_inode_close(bi); - free(utarget); - free(uname); + if (dir_ni != NULL) + ntfs_inode_close(dir_ni); + if (utarget != NULL) + free(utarget); + if (uname != NULL) + free(uname); 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; int unameLength; ntfs_inode *ni = NULL; - ntfs_inode *bi = NULL; + ntfs_inode *dir_ni = NULL; status_t result = B_NO_ERROR; le32 securid = const_cpu_to_le32(0); if (ns->flags & B_FS_IS_READONLY) { ERROR("ntfs is read-only\n"); - return EROFS; + return B_READ_ONLY_DEVICE; } LOCK_VOL(ns); @@ -1644,13 +1563,13 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms) goto exit; } - bi = ntfs_inode_open(ns->ntvol, dir->vnid); - if (bi == NULL) { + dir_ni = ntfs_inode_open(ns->ntvol, dir->vnid); + if (dir_ni == NULL) { result = ENOENT; goto exit; } - if (!(bi->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { + if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { result = EINVAL; goto exit; } @@ -1661,8 +1580,8 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms) goto exit; } - ni = ntfs_create(bi, securid, uname, unameLength, S_IFDIR); - if (ni) { + ni = ntfs_create(dir_ni, securid, uname, unameLength, S_IFDIR); + if (ni != NULL) { ino_t vnid = MREF(ni->mft_no); 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; } - if (ntfs_inode_close_in_dir(ni, bi)) { - result = EINVAL; - goto exit; - } - newNode->vnid = vnid; - newNode->parent_vnid = MREF(bi->mft_no); - - if (ns->fake_attrib) - set_mime(newNode, ".***"); + newNode->parent_vnid = MREF(dir_ni->mft_no); ni->flags |= FILE_ATTR_ARCHIVE; - ntfs_inode_update_mbsname(bi, name, ni->mft_no); NInoSetDirty(ni); 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); + if (ntfs_inode_close_in_dir(ni, dir_ni)) { + result = EINVAL; + goto exit; + } + ntfs_mark_free_space_outdated(ns); - fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME); - notify_entry_created(ns->id, MREF(bi->mft_no), name, vnid); + 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: - if (bi) - ntfs_inode_close(bi); - free(uname); + if (dir_ni != NULL) + ntfs_inode_close(dir_ni); + if (uname != NULL) + free(uname); 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) { nspace *ns = (nspace*)_vol->private_volume; - vnode *odir = (vnode*)_odir->private_node; - vnode *ndir = (vnode*)_ndir->private_node; + vnode *parent_vnode = (vnode*)_odir->private_node; + vnode *newparent_vnode = (vnode*)_ndir->private_node; 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 *dir_ni = NULL; status_t result = B_NO_ERROR; - if (ns->flags & B_FS_IS_READONLY) { ERROR("ntfs is read-only\n"); - return EROFS; + return B_READ_ONLY_DEVICE; } LOCK_VOL(ns); TRACE("NTFS:fs_rename - oldname:%s newname:%s\n", name, newname); - ino = ntfs_inode_lookup(_vol, parent, name); - if (ino == (u64)-1) { + inode = ntfs_inode_lookup(_vol, parent_vnid, name); + if (inode == (u64)-1) { result = EINVAL; goto exit; } /* 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; int uname_len; - result = get_vnode(_vol, ino, (void**)&file); + result = get_vnode(_vol, inode, (void**)&file); if (result != B_NO_ERROR) goto exit; - ni = ntfs_inode_open(ns->ntvol, ino); + ni = ntfs_inode_open(ns->ntvol, inode); if (!ni) { result = EINVAL; goto exit; @@ -1769,7 +1685,7 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name, goto exit; } - dir_ni = ntfs_inode_open(ns->ntvol, newparent); + dir_ni = ntfs_inode_open(ns->ntvol, newparent_vnid); if (!dir_ni) { result = EINVAL; goto exit; @@ -1780,8 +1696,6 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name, goto exit; } - ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no); - ni->flags |= FILE_ATTR_ARCHIVE; 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, ".***"); else set_mime(file, newname); + notify_attribute_changed(ns->id, file->vnid, "BEOS:TYPE", + B_ATTR_CHANGED); } ntfs_inode_close(dir_ni); @@ -1799,13 +1715,14 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name, 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); - notify_entry_moved(ns->id, parent, name, newparent, newname, ino); + notify_entry_moved(ns->id, parent_vnid, name, newparent_vnid, + newname, inode); } else result = EINVAL; exit: @@ -1822,11 +1739,15 @@ fs_rmdir(fs_volume *_vol, fs_vnode *_dir, const char *name) { nspace *ns = (nspace*)_vol->private_volume; vnode *dir = (vnode*)_dir->private_node; + vnode *file = NULL; + ntfs_inode *ni = NULL; + ntfs_inode *dir_ni = NULL; status_t result = B_NO_ERROR; + ino_t ino; if (ns->flags & B_FS_IS_READONLY) { ERROR("ntfs is read-only\n"); - return EROFS; + return B_READ_ONLY_DEVICE; } 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) { result = EINVAL; - goto exit1; + goto exit; } if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { 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); -exit1: +exit: + if (ni != NULL) + ntfs_inode_close(ni); + TRACE("fs_rmdir - EXIT, result is %s\n", strerror(result)); UNLOCK_VOL(ns); @@ -1862,11 +1827,14 @@ fs_unlink(fs_volume *_vol, fs_vnode *_dir, const char *name) { nspace *ns = (nspace*)_vol->private_volume; vnode *dir = (vnode*)_dir->private_node; + vnode *file = NULL; + ntfs_inode *dir_ni = NULL; status_t result = B_NO_ERROR; + ino_t inode; if (ns->flags & B_FS_IS_READONLY) { ERROR("ntfs is read-only\n"); - return EROFS; + return B_READ_ONLY_DEVICE; } LOCK_VOL(ns); @@ -1883,11 +1851,35 @@ fs_unlink(fs_volume *_vol, fs_vnode *_dir, const char *name) 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); - + exit: TRACE("fs_unlink - EXIT, result is %s\n", strerror(result)); diff --git a/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c b/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c index b9e7930fe8..9e12359598 100644 --- a/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c +++ b/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c @@ -156,7 +156,7 @@ fs_vnode_ops gNTFSVnodeOps = { &fs_read_attrib_stat, NULL, //&fs_write_attr_stat, NULL, //&fs_rename_attr, - NULL, //&fs_remove_attr, + &fs_remove_attrib, }; diff --git a/src/add-ons/kernel/file_systems/ntfs/ntfs.h b/src/add-ons/kernel/file_systems/ntfs/ntfs.h index e26147d1e7..16bbcf8ae5 100644 --- a/src/add-ons/kernel/file_systems/ntfs/ntfs.h +++ b/src/add-ons/kernel/file_systems/ntfs/ntfs.h @@ -87,19 +87,20 @@ typedef struct vnode { } vnode; typedef struct filecookie { - int omode; - off_t last_size; + int omode; + off_t last_size; } filecookie; typedef struct attrcookie { - int omode; - ntfs_inode *inode; - ntfs_attr *stream; - // MFT ref for EA ? + int omode; + ino_t vnid; + ntfschar* uname; + int uname_len; + uint32 type; } attrcookie; typedef struct attrdircookie { - ntfs_inode *inode; + ntfs_inode* inode; ntfs_attr_search_ctx *ctx; } attrdircookie; diff --git a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.c b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.c index bc3bb5e92f..46f5e0f1a9 100644 --- a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.c +++ b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.c @@ -33,8 +33,8 @@ #include -//callback function for readdir() -static int _ntfs_dirent_filler(void *_dirent, const ntfschar *name, +static int +_ntfs_dirent_filler(void *_dirent, const ntfschar *name, const int name_len, const int name_type, const s64 pos, const MFT_REF mref, const unsigned dt_type) { @@ -45,42 +45,64 @@ static int _ntfs_dirent_filler(void *_dirent, const ntfschar *name, return 0; if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user - || cookie->show_sys_files) { - if (cookie->readed == 1) { - cookie->pos=pos; - cookie->readed = 0; - return -1; - } else { - if (ntfs_ucstombs(name, name_len, &filename, 0) >= 0) { - if (filename) { - strcpy(cookie->name,filename); - cookie->ino=MREF(mref); - cookie->readed = 1; - free(filename); - return 0; - } + || cookie->show_sys_files) { + int len = ntfs_ucstombs(name, name_len, &filename, 0); + if (len >= 0 && filename != NULL) { + cache_entry* new_entry = + (cache_entry*)ntfs_calloc(sizeof(cache_entry)); + if (new_entry == NULL) { + free(filename); + return -1; + } + + new_entry->ent = + (struct dirent*)ntfs_calloc(sizeof(struct dirent) + len); + 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; } 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; - - LOCK_VOL(ns); + dircookie *cookie = (dircookie*)_cookie; + + LOCK_VOL(ns); 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); + } TRACE("fs_free_dircookie - EXIT\n"); - UNLOCK_VOL(ns); return B_NO_ERROR; @@ -93,11 +115,10 @@ fs_opendir(fs_volume *_vol, fs_vnode *_node, void** _cookie) nspace *ns = (nspace*)_vol->private_volume; vnode *node = (vnode*)_node->private_node; dircookie *cookie = NULL; - int result = B_NO_ERROR; ntfs_inode *ni = NULL; + int result = B_NO_ERROR; LOCK_VOL(ns); - TRACE("fs_opendir - ENTER\n"); 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)); if (cookie != NULL) { cookie->pos = 0; - cookie->ino = 0; - cookie->readed = 0; - cookie->last = 0; - cookie->name[0] = 0; + cookie->dev_id = ns->id; cookie->show_sys_files = ns->show_sys_files; + cookie->cache_root = NULL; + cookie->entry = cookie->cache_root; *_cookie = (void*)cookie; } else result = ENOMEM; exit: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); TRACE("fs_opendir - EXIT\n"); - UNLOCK_VOL(ns); return result; @@ -138,32 +157,7 @@ exit: status_t fs_closedir(fs_volume *_vol, fs_vnode *_node, void *cookie) { - nspace *ns = (nspace*)_vol->private_volume; - 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; + return B_NO_ERROR; } @@ -174,12 +168,12 @@ fs_readdir(fs_volume *_vol, fs_vnode *_node, void *_cookie, struct dirent *buf, nspace *ns = (nspace*)_vol->private_volume; vnode *node = (vnode*)_node->private_node; dircookie *cookie = (dircookie*)_cookie; - uint32 nameLength = bufsize - sizeof(struct dirent), realLen; - int result = B_NO_ERROR; 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", sizeof(buf), bufsize, *num); @@ -188,36 +182,47 @@ fs_readdir(fs_volume *_vol, fs_vnode *_node, void *_cookie, struct dirent *buf, goto exit; } - if (cookie->readed == 1 || cookie->last == 1) { - result = ENOENT; - goto exit; - } - ni = ntfs_inode_open(ns->ntvol, node->vnid); if (ni == NULL) { - ERROR("fs_readdir - dir not opened\n"); + TRACE("fs_readdir - dir not opened\n"); result = ENOENT; goto exit; } - result = ntfs_readdir(ni, &cookie->pos, cookie, - (ntfs_filldir_t)_ntfs_dirent_filler); + if(cookie->cache_root == NULL) { + 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; + buf->d_dev = ns->id; - buf->d_ino = cookie->ino; - strlcpy(buf->d_name, cookie->name, realLen + 1); + buf->d_ino = cookie->entry->ent->d_ino; + strlcpy(buf->d_name, cookie->entry->ent->d_name, realLen + 1); buf->d_reclen = sizeof(struct dirent) + realLen; - - if (result == 0) - cookie->last = 1; - - result = B_NO_ERROR; + + cookie->entry = (cache_entry*)cookie->entry->next; TRACE("fs_readdir - FILE: [%s]\n",buf->d_name); exit: - if (ni) + if (ni != NULL) ntfs_inode_close(ni); if (result == B_NO_ERROR) @@ -228,8 +233,7 @@ exit: if (result == ENOENT) 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); return result; @@ -244,19 +248,26 @@ fs_rewinddir(fs_volume *_vol, fs_vnode *vnode, void *_cookie) int result = EINVAL; LOCK_VOL(ns); - TRACE("fs_rewinddir - ENTER\n"); + 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->ino = 0; - cookie->readed = 0; - cookie->last = 0; - cookie->name[0] = 0; + cookie->dev_id = ns->id; + cookie->show_sys_files = ns->show_sys_files; + cookie->cache_root = NULL; + cookie->entry = cookie->cache_root; result = B_NO_ERROR; } TRACE("fs_rewinddir - EXIT, result is %s\n", strerror(result)); - UNLOCK_VOL(ns); return result; diff --git a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h index a84df3d131..2fa305cc40 100644 --- a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h +++ b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h @@ -24,15 +24,21 @@ #include "ntfs.h" +typedef struct cache_entry { + struct dirent *ent; + struct cache_entry *next; +} cache_entry; + + typedef struct dircookie { u64 pos; - int readed; - int last; - ino_t ino; - BOOL show_sys_files; - char name[MAX_PATH]; + dev_t dev_id; + BOOL show_sys_files; + cache_entry *cache_root; + cache_entry *entry; } dircookie; + 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_opendir(fs_volume *volume, fs_vnode *vnode, void** cookie);