/* Create empty named data streams. * * Since these won't have 'struct wim_lookup_table_entry's, they won't show up * in the call to extract_stream_list(). Hence the need for the special case. */ static int ntfs_3g_create_any_empty_ads(ntfs_inode *ni, const struct wim_inode *inode, const struct ntfs_3g_apply_ctx *ctx) { for (u16 i = 0; i < inode->i_num_ads; i++) { const struct wim_ads_entry *entry; entry = &inode->i_ads_entries[i]; /* Not named? */ if (!entry->stream_name_nbytes) continue; /* Not empty? */ if (entry->lte) continue; if (ntfs_attr_add(ni, AT_DATA, entry->stream_name, entry->stream_name_nbytes / sizeof(utf16lechar), NULL, 0)) { ERROR_WITH_ERRNO("Failed to create named data stream " "of \"%s\"", dentry_full_path( inode_first_extraction_dentry(inode))); return WIMLIB_ERR_NTFS_3G; } } return 0; }
static int add_object_id(ntfs_inode *ni, int flags) { int res; u8 dummy; res = -1; /* default return */ if (!ntfs_attr_exist(ni,AT_OBJECT_ID, AT_UNNAMED,0)) { if (!(flags & XATTR_REPLACE)) { /* * no object id attribute : add one, * apparently, this does not feed the new value in * Note : NTFS version must be >= 3 */ if (ni->vol->major_ver >= 3) { res = ntfs_attr_add(ni, AT_OBJECT_ID, AT_UNNAMED, 0, &dummy, (s64)0); NInoSetDirty(ni); } else errno = ENOTSUP; } else errno = ENODATA; } else { if (flags & XATTR_CREATE) errno = EEXIST; else res = 0; } return (res); }
static int ntfs_ibm_add(ntfs_index_context *icx) { u8 bmp[8]; ntfs_log_trace("Entering\n"); if (ntfs_attr_exist(icx->ni, AT_BITMAP, icx->name, icx->name_len)) return STATUS_OK; /* * AT_BITMAP must be at least 8 bytes. */ memset(bmp, 0, sizeof(bmp)); if (ntfs_attr_add(icx->ni, AT_BITMAP, icx->name, icx->name_len, bmp, sizeof(bmp))) { ntfs_log_perror("Failed to add AT_BITMAP"); return STATUS_ERROR; } return STATUS_OK; }
static int ntfs_ia_add(ntfs_index_context *icx) { ntfs_log_trace("Entering\n"); if (ntfs_ibm_add(icx)) return -1; if (!ntfs_attr_exist(icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len)) { if (ntfs_attr_add(icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len, NULL, 0)) { ntfs_log_perror("Failed to add AT_INDEX_ALLOCATION"); return -1; } } icx->ia_na = ntfs_ia_open(icx, icx->ni); if (!icx->ia_na) return -1; return 0; }
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; 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; ERROR("%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) { uname = ntfs_calloc(MAX_PATH); ulen = ntfs_mbstoucs(name, &uname); if (ulen < 0) { result = EILSEQ; ERROR("%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 (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) { 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; } 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; }
bool ntfsSetVolumeName (const char *name, const char *volumeName) { ntfs_vd *vd = NULL; ntfs_attr *na = NULL; ntfschar *ulabel = NULL; int ulabel_len; // Sanity check if (!name) { errno = EINVAL; return false; } // Get the devices volume descriptor vd = ntfsGetVolume(name); if (!vd) { errno = ENODEV; return false; } // Lock ntfsLock(vd); // Convert the new volume name to unicode ulabel_len = ntfsLocalToUnicode(volumeName, &ulabel) * sizeof(ntfschar); if (ulabel_len < 0) { ntfsUnlock(vd); errno = EINVAL; return false; } // Check if the volume name attribute exists na = ntfs_attr_open(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0); if (na) { // It does, resize it to match the length of the new volume name if (ntfs_attr_truncate(na, ulabel_len)) { ntfs_free(ulabel); ntfsUnlock(vd); return false; } // Write the new volume name if (ntfs_attr_pwrite(na, 0, ulabel_len, ulabel) != ulabel_len) { ntfs_free(ulabel); ntfsUnlock(vd); return false; } } else { // It doesn't, create it now if (ntfs_attr_add(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0, (u8*)ulabel, ulabel_len)) { ntfs_free(ulabel); ntfsUnlock(vd); return false; } } // Reset the volumes name cache (as it has now been changed) vd->name[0] = '\0'; // Close the volume name attribute if (na) ntfs_attr_close(na); // Sync the volume node if (ntfs_inode_sync(vd->vol->vol_ni)) { ntfs_free(ulabel); ntfsUnlock(vd); return false; } // Clean up ntfs_free(ulabel); // Unlock ntfsUnlock(vd); return true; }
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}; 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; 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; }
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; }
int ntfs_set_ntfs_reparse_data(ntfs_inode *ni, const char *value, size_t size, int flags) { int res; u8 dummy; ntfs_inode *xrni; ntfs_index_context *xr; res = 0; if (ni && valid_reparse_data(ni, (const REPARSE_POINT*)value, size)) { xr = open_reparse_index(ni->vol); if (xr) { if (!ntfs_attr_exist(ni,AT_REPARSE_POINT, AT_UNNAMED,0)) { if (!(flags & XATTR_REPLACE)) { /* * no reparse data attribute : add one, * apparently, this does not feed the new value in * Note : NTFS version must be >= 3 */ if (ni->vol->major_ver >= 3) { res = ntfs_attr_add(ni, AT_REPARSE_POINT, AT_UNNAMED,0,&dummy, (s64)0); if (!res) { ni->flags |= FILE_ATTR_REPARSE_POINT; NInoFileNameSetDirty(ni); } NInoSetDirty(ni); } else { errno = EOPNOTSUPP; res = -1; } } else { errno = ENODATA; res = -1; } } else { if (flags & XATTR_CREATE) { errno = EEXIST; res = -1; } } if (!res) { /* update value and index */ res = update_reparse_data(ni,xr,value,size); } xrni = xr->ni; ntfs_index_entry_mark_dirty(xr); NInoSetDirty(xrni); ntfs_index_ctx_put(xr); ntfs_inode_close(xrni); } else { res = -1; } } else { errno = EINVAL; res = -1; } return (res ? -1 : 0); }