static INDEX_BLOCK *ntfs_ib_alloc(VCN ib_vcn, u32 ib_size, INDEX_HEADER_FLAGS node_type) { INDEX_BLOCK *ib; int ih_size = sizeof(INDEX_HEADER); ntfs_log_trace("ib_vcn: %lld ib_size: %u\n", (long long)ib_vcn, ib_size); ib = ntfs_calloc(ib_size); if (!ib) return NULL; ib->magic = magic_INDX; ib->usa_ofs = cpu_to_le16(sizeof(INDEX_BLOCK)); ib->usa_count = cpu_to_le16(ib_size / NTFS_BLOCK_SIZE + 1); /* Set USN to 1 */ *(u16 *)((char *)ib + le16_to_cpu(ib->usa_ofs)) = cpu_to_le16(1); ib->lsn = cpu_to_le64(0); ib->index_block_vcn = cpu_to_sle64(ib_vcn); ib->index.entries_offset = cpu_to_le32((ih_size + le16_to_cpu(ib->usa_count) * 2 + 7) & ~7); ib->index.index_length = 0; ib->index.allocated_size = cpu_to_le32(ib_size - (sizeof(INDEX_BLOCK) - ih_size)); ib->index.ih_flags = node_type; return ib; }
/** * __ntfs_inode_allocate - Create and initialise an NTFS inode object * @vol: * * Description... * * Returns: */ static ntfs_inode *__ntfs_inode_allocate(ntfs_volume *vol) { ntfs_inode *ni; ni = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode)); if (ni) ni->vol = vol; return ni; }
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) ntfs_attr_put_search_ctx(ctx); if (ni) ntfs_inode_close(ni); TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result)); UNLOCK_VOL(ns); return result; }
status_t 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; LOCK_VOL(ns); TRACE("fs_opendir - ENTER\n"); ni = ntfs_inode_open(ns->ntvol, node->vnid); if (ni == NULL) { result = ENOENT; goto exit; } if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { result = EMFILE; goto exit; } 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->show_sys_files = ns->show_sys_files; *_cookie = (void*)cookie; } else result = ENOMEM; exit: if (ni) ntfs_inode_close(ni); TRACE("fs_opendir - EXIT\n"); UNLOCK_VOL(ns); return result; }
/** * ntfs_index_add_filename - add filename to directory index * @ni: ntfs inode describing directory to which index add filename * @fn: FILE_NAME attribute to add * @mref: reference of the inode which @fn describes * * Return 0 on success or -1 on error with errno set to the error code. */ int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref) { INDEX_ENTRY *ie; ntfs_index_context *icx; int fn_size, ie_size, err, ret = -1; ntfs_log_trace("Entering\n"); if (!ni || !fn) { ntfs_log_error("Invalid arguments.\n"); errno = EINVAL; return -1; } fn_size = (fn->file_name_length * sizeof(ntfschar)) + sizeof(FILE_NAME_ATTR); ie_size = (sizeof(INDEX_ENTRY_HEADER) + fn_size + 7) & ~7; ie = ntfs_calloc(ie_size); if (!ie) return -1; ie->indexed_file = cpu_to_le64(mref); ie->length = cpu_to_le16(ie_size); ie->key_length = cpu_to_le16(fn_size); memcpy(&ie->key, fn, fn_size); icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4); if (!icx) goto out; ret = ntfs_ie_add(icx, ie); err = errno; ntfs_index_ctx_put(icx); errno = err; out: free(ie); return ret; }
/** * ntfs_index_ctx_get - allocate and initialize a new index context * @ni: ntfs inode with which to initialize the context * @name: name of the which context describes * @name_len: length of the index name * * Allocate a new index context, initialize it with @ni and return it. * Return NULL if allocation failed. */ ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni, ntfschar *name, u32 name_len) { ntfs_index_context *icx; ntfs_log_trace("Entering\n"); if (!ni) { errno = EINVAL; return NULL; } if (ni->nr_extents == -1) ni = ni->base_ni; icx = ntfs_calloc(sizeof(ntfs_index_context)); if (icx) *icx = (ntfs_index_context) { .ni = ni, .name = name, .name_len = name_len, }; return icx; }
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; TRACE("%s - ENTER\n", __FUNCTION__); 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) { uname = ntfs_calloc(MAX_PATH); ulen = ntfs_mbstoucs(name, &uname); if (ulen < 0) { result = EILSEQ; goto exit; } na = ntfs_attr_open(ni, AT_DATA, uname, ulen); if (na) { if (openMode & O_TRUNC) { if (ntfs_attr_truncate(na, 0)) result = errno; } } else { result = ENOENT; 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; } else result = ENOMEM; exit: if (uname) free(uname); if (na) ntfs_attr_close(na); if (ni) ntfs_inode_close(ni); TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result)); UNLOCK_VOL(ns); return result; }
/** * ntfs_attrlist_entry_rm - remove an attribute list attribute entry * @ctx: attribute search context describing the attribute list entry * * Remove the attribute list entry @ctx->al_entry from the attribute list. * * Return 0 on success and -1 on error with errno set to the error code. */ int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx) { u8 *new_al; int new_al_len; ntfs_inode *base_ni; ntfs_attr *na; ATTR_LIST_ENTRY *ale; int err; if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) { ntfs_log_trace("Invalid arguments.\n"); errno = EINVAL; return -1; } if (ctx->base_ntfs_ino) base_ni = ctx->base_ntfs_ino; else base_ni = ctx->ntfs_ino; ale = ctx->al_entry; ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n", (long long) ctx->ntfs_ino->mft_no, (unsigned) le32_to_cpu(ctx->al_entry->type), (long long) le64_to_cpu(ctx->al_entry->lowest_vcn)); if (!NInoAttrList(base_ni)) { ntfs_log_trace("Attribute list isn't present.\n"); errno = ENOENT; return -1; } /* Allocate memory for new attribute list. */ new_al_len = base_ni->attr_list_size - le16_to_cpu(ale->length); new_al = (u8 *) ntfs_calloc(new_al_len); if (!new_al) return -1; /* Reisze $ATTRIBUTE_LIST to new length. */ na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); if (!na) { err = errno; ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); goto err_out; } if (ntfs_attr_truncate(na, new_al_len)) { err = errno; ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); goto err_out; } /* Copy entries from old attribute list to new. */ memcpy(new_al, base_ni->attr_list, (u8*)ale - base_ni->attr_list); memcpy(new_al + ((u8*)ale - base_ni->attr_list), (u8*)ale + le16_to_cpu( ale->length), new_al_len - ((u8*)ale - base_ni->attr_list)); /* Set new runlist. */ free(base_ni->attr_list); base_ni->attr_list = new_al; base_ni->attr_list_size = new_al_len; NInoAttrListSetDirty(base_ni); /* Done! */ ntfs_attr_close(na); return 0; err_out: if (na) ntfs_attr_close(na); free(new_al); errno = err; return -1; }
/** * ntfs_attrlist_entry_add - add an attribute list attribute entry * @ni: opened ntfs inode, which contains that attribute * @attr: attribute record to add to attribute list * * Return 0 on success and -1 on error with errno set to the error code. The * following error codes are defined: * EINVAL - Invalid arguments passed to function. * ENOMEM - Not enough memory to allocate necessary buffers. * EIO - I/O error occurred or damaged filesystem. * EEXIST - Such attribute already present in attribute list. */ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr) { ATTR_LIST_ENTRY *ale; MFT_REF mref; ntfs_attr *na = NULL; ntfs_attr_search_ctx *ctx; u8 *new_al; int entry_len, entry_offset, err; ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (long long) ni->mft_no, (unsigned) le32_to_cpu(attr->type)); if (!ni || !attr) { ntfs_log_trace("Invalid arguments.\n"); errno = EINVAL; return -1; } mref = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number)); if (ni->nr_extents == -1) ni = ni->base_ni; if (!NInoAttrList(ni)) { ntfs_log_trace("Attribute list isn't present.\n"); errno = ENOENT; return -1; } /* Determine size and allocate memory for new attribute list. */ entry_len = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * attr->name_length + 7) & ~7; new_al = (u8 *) ntfs_calloc(ni->attr_list_size + entry_len); if (!new_al) return -1; /* Find place for the new entry. */ ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!ctx) { err = errno; goto err_out; } if (!ntfs_attr_lookup(attr->type, (attr->name_length) ? (ntfschar*) ((u8*)attr + le16_to_cpu(attr->name_offset)) : AT_UNNAMED, attr->name_length, CASE_SENSITIVE, (attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) : 0, (attr->non_resident) ? NULL : ((u8*)attr + le16_to_cpu(attr->value_offset)), (attr->non_resident) ? 0 : le32_to_cpu(attr->value_length), ctx)) { /* Found some extent, check it to be before new extent. */ if (ctx->al_entry->lowest_vcn == attr->lowest_vcn) { err = EEXIST; ntfs_log_trace("Such attribute already present in the " "attribute list.\n"); ntfs_attr_put_search_ctx(ctx); goto err_out; } /* Add new entry after this extent. */ ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry + le16_to_cpu(ctx->al_entry->length)); } else { /* Check for real errors. */ if (errno != ENOENT) { err = errno; ntfs_log_trace("Attribute lookup failed.\n"); ntfs_attr_put_search_ctx(ctx); goto err_out; } /* No previous extents found. */ ale = ctx->al_entry; } /* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */ ntfs_attr_put_search_ctx(ctx); /* Determine new entry offset. */ entry_offset = ((u8 *)ale - ni->attr_list); /* Set pointer to new entry. */ ale = (ATTR_LIST_ENTRY *)(new_al + entry_offset); /* Zero it to fix valgrind warning. */ memset(ale, 0, entry_len); /* Form new entry. */ ale->type = attr->type; ale->length = cpu_to_le16(entry_len); ale->name_length = attr->name_length; ale->name_offset = offsetof(ATTR_LIST_ENTRY, name); if (attr->non_resident) ale->lowest_vcn = attr->lowest_vcn; else ale->lowest_vcn = 0; ale->mft_reference = mref; ale->instance = attr->instance; memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset), attr->name_length * sizeof(ntfschar)); /* Resize $ATTRIBUTE_LIST to new length. */ na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); if (!na) { err = errno; ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); goto err_out; } if (ntfs_attr_truncate(na, ni->attr_list_size + entry_len)) { err = errno; ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); goto err_out; } /* Copy entries from old attribute list to new. */ memcpy(new_al, ni->attr_list, entry_offset); memcpy(new_al + entry_offset + entry_len, ni->attr_list + entry_offset, ni->attr_list_size - entry_offset); /* Set new runlist. */ free(ni->attr_list); ni->attr_list = new_al; ni->attr_list_size = ni->attr_list_size + entry_len; NInoAttrListSetDirty(ni); /* Done! */ ntfs_attr_close(na); return 0; err_out: if (na) ntfs_attr_close(na); free(new_al); errno = err; return -1; }
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; }
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}; 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; } 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_read_vnode(fs_volume *_vol, ino_t vnid, fs_vnode *_node, int *_type, uint32 *_flags, bool reenter) { nspace *ns = (nspace*)_vol->private_volume; vnode *newNode = NULL; ntfs_inode *ni = NULL; status_t result = B_NO_ERROR; if (!reenter) LOCK_VOL(ns); ERRPRINT("fs_read_vnode - ENTER\n"); _node->private_node = NULL; _node->ops = &gNTFSVnodeOps; _flags = 0; newNode = (vnode*)ntfs_calloc(sizeof(vnode)); if (newNode != NULL) { char *name = NULL; ni = ntfs_inode_open(ns->ntvol, vnid); if (ni == NULL) { result = ENOENT; goto exit; } // get the node type result = get_node_type(ni, _type); if (result != B_OK) goto exit; newNode->vnid = vnid; newNode->parent_vnid = ntfs_get_parent_ref(ni); if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) set_mime(newNode, ".***"); else { name = (char*)malloc(MAX_PATH); if (name != NULL) { if (utils_inode_get_name(ni, name,MAX_PATH) == 1) set_mime(newNode, name); free(name); } } _node->private_node = newNode; } else result = ENOMEM; exit: if (ni != NULL) ntfs_inode_close(ni); if (result != B_OK && newNode != NULL) free(newNode); ERRPRINT("fs_read_vnode - EXIT, result is %s\n", strerror(result)); if (!reenter) UNLOCK_VOL(ns); return result; }
status_t 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; status_t result = B_NO_ERROR; int len; LOCK_VOL(ns); ERRPRINT("fs_walk - ENTER : find for \"%s\"\n",file); if (ns == NULL || _dir == NULL || file == NULL || vnid == NULL) { result = EINVAL; goto exit; } if (!strcmp(file, ".")) { *vnid = baseNode->vnid; if (get_vnode(_vol, *vnid, (void**)&newNode) != 0) result = ENOENT; } else if (!strcmp(file, "..") && baseNode->vnid != FILE_root) { *vnid = baseNode->parent_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) { result = EILSEQ; goto exit; } bi = ntfs_inode_open(ns->ntvol, baseNode->vnid); if (!bi) { result = ENOENT; goto exit; } *vnid = MREF(ntfs_inode_lookup_by_name(bi, unicode, len)); ERRPRINT("fs_walk - VNID = %d\n",*vnid); ntfs_inode_close(bi); free(unicode); if (*vnid == (u64)-1) { result = EINVAL; goto exit; } if (get_vnode(_vol, *vnid, (void**)&newNode) != 0) result = ENOENT; if (newNode!=NULL) newNode->parent_vnid = baseNode->vnid; } exit: ERRPRINT("fs_walk - EXIT, result is %s\n", strerror(result)); UNLOCK_VOL(ns); return result; }
status_t fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args, ino_t *_rootID) { nspace *ns; vnode *newNode = NULL; char lockname[32]; void *handle; unsigned long mountFlags = 0; status_t result = B_NO_ERROR; ERRPRINT("fs_mount - ENTER\n"); ns = ntfs_malloc(sizeof(nspace)); if (!ns) { result = ENOMEM; goto exit; } *ns = (nspace) { .state = NF_FreeClustersOutdate | NF_FreeMFTOutdate, .show_sys_files = false, .ro = false, .flags = 0 }; strcpy(ns->devicePath,device); sprintf(lockname, "ntfs_lock %lx", ns->id); recursive_lock_init_etc(&(ns->vlock), lockname, MUTEX_FLAG_CLONE_NAME); handle = load_driver_settings("ntfs"); ns->show_sys_files = ! (strcasecmp(get_driver_parameter(handle, "hide_sys_files", "true", "true"), "true") == 0); ns->ro = strcasecmp(get_driver_parameter(handle, "read_only", "false", "false"), "false") != 0; ns->noatime = strcasecmp(get_driver_parameter(handle, "no_atime", "true", "true"), "true") == 0; unload_driver_settings(handle); if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0) { mountFlags |= MS_RDONLY; ns->flags |= B_FS_IS_READONLY; } // TODO: this does not take read-only volumes into account! ns->ntvol = utils_mount_volume(device, mountFlags, true); if (ns->ntvol != NULL) result = B_NO_ERROR; else result = errno; if (result == B_NO_ERROR) { *_rootID = FILE_root; ns->id = _vol->id; _vol->private_volume = (void *)ns; _vol->ops = &gNTFSVolumeOps; newNode = (vnode*)ntfs_calloc(sizeof(vnode)); if (newNode == NULL) result = ENOMEM; else { newNode->vnid = *_rootID; newNode->parent_vnid = -1; result = publish_vnode(_vol, *_rootID, (void*)newNode, &gNTFSVnodeOps, S_IFDIR, 0); if (result != B_NO_ERROR) { free(ns); result = EINVAL; goto exit; } else { result = B_NO_ERROR; ntfs_mark_free_space_outdated(ns); ntfs_calc_free_space(ns); } } } exit: ERRPRINT("fs_mount - EXIT, result code is %s\n", strerror(result)); return result; } status_t fs_unmount(fs_volume *_vol) { nspace *ns = (nspace*)_vol->private_volume; status_t result = B_NO_ERROR; ERRPRINT("fs_unmount - ENTER\n"); ntfs_umount(ns->ntvol, true); recursive_lock_destroy(&(ns->vlock)); free(ns); ERRPRINT("fs_unmount - EXIT, result is %s\n", strerror(result)); return result; }
int ntfs_sd_add_everyone(ntfs_inode *ni) { SECURITY_DESCRIPTOR_ATTR *sd; ACL *acl; ACCESS_ALLOWED_ACE *ace; SID *sid; int ret, sd_len; /* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */ /* * Calculate security descriptor length. We have 2 sub-authorities in * owner and group SIDs, but structure SID contain only one, so add * 4 bytes to every SID. */ sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); sd = ntfs_calloc(sd_len); if (!sd) return -1; sd->revision = 1; sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE; sid = (SID *)((u8 *)sd + sizeof(SECURITY_DESCRIPTOR_ATTR)); sid->revision = 1; sid->sub_authority_count = 2; sid->sub_authority[0] = cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); sid->identifier_authority.value[5] = 5; sd->owner = cpu_to_le32((u8 *)sid - (u8 *)sd); sid = (SID *)((u8 *)sid + sizeof(SID) + 4); sid->revision = 1; sid->sub_authority_count = 2; sid->sub_authority[0] = cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); sid->identifier_authority.value[5] = 5; sd->group = cpu_to_le32((u8 *)sid - (u8 *)sd); acl = (ACL *)((u8 *)sid + sizeof(SID) + 4); acl->revision = 2; acl->size = cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)); acl->ace_count = cpu_to_le16(1); sd->dacl = cpu_to_le32((u8 *)acl - (u8 *)sd); ace = (ACCESS_ALLOWED_ACE *)((u8 *)acl + sizeof(ACL)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; ace->size = cpu_to_le16(sizeof(ACCESS_ALLOWED_ACE)); ace->mask = cpu_to_le32(0x1f01ff); /* FIXME */ ace->sid.revision = 1; ace->sid.sub_authority_count = 1; ace->sid.sub_authority[0] = 0; ace->sid.identifier_authority.value[5] = 1; ret = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0, (u8 *)sd, sd_len); if (ret) ntfs_log_perror("Failed to add SECURITY_DESCRIPTOR\n"); free(sd); return ret; }