/* Set attributes, security descriptor, and timestamps on the NTFS inode @ni. */ static int ntfs_3g_set_metadata(ntfs_inode *ni, const struct wim_inode *inode, const struct ntfs_3g_apply_ctx *ctx) { int extract_flags; const struct wim_security_data *sd; struct wim_dentry *one_dentry; int ret; extract_flags = ctx->common.extract_flags; sd = wim_get_current_security_data(ctx->common.wim); one_dentry = inode_first_extraction_dentry(inode); /* Attributes */ if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)) { u32 attrib = inode->i_attributes; attrib &= ~(FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_ENCRYPTED); if (ntfs_set_ntfs_attrib(ni, (const char *)&attrib, sizeof(attrib), 0)) { ERROR_WITH_ERRNO("Failed to set attributes on \"%s\" " "in NTFS volume", dentry_full_path(one_dentry)); return WIMLIB_ERR_SET_ATTRIBUTES; } } /* Security descriptor */ if ((inode->i_security_id >= 0) && !(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS)) { const void *desc; size_t desc_size; desc = sd->descriptors[inode->i_security_id]; desc_size = sd->sizes[inode->i_security_id]; ret = ntfs_3g_set_security_descriptor(ni, desc, desc_size); if (ret) { if (wimlib_print_errors) { ERROR_WITH_ERRNO("Failed to set security descriptor " "on \"%s\" in NTFS volume", dentry_full_path(one_dentry)); fprintf(wimlib_error_file, "The security descriptor is: "); print_byte_field(desc, desc_size, wimlib_error_file); fprintf(wimlib_error_file, "\n"); } return ret; } } /* Timestamps */ ret = ntfs_3g_set_timestamps(ni, inode); if (ret) { ERROR_WITH_ERRNO("Failed to set timestamps on \"%s\" " "in NTFS volume", dentry_full_path(one_dentry)); return ret; } return 0; }
static int init_wimlib_dentry(struct wimlib_dir_entry *wdentry, struct wim_dentry *dentry, WIMStruct *wim, int flags) { int ret; size_t dummy; const struct wim_inode *inode = dentry->d_inode; const struct wim_inode_stream *strm; struct wimlib_unix_data unix_data; const void *object_id; u32 object_id_len; ret = utf16le_get_tstr(dentry->d_name, dentry->d_name_nbytes, &wdentry->filename, &dummy); if (ret) return ret; ret = utf16le_get_tstr(dentry->d_short_name, dentry->d_short_name_nbytes, &wdentry->dos_name, &dummy); if (ret) return ret; ret = calculate_dentry_full_path(dentry); if (ret) return ret; wdentry->full_path = dentry->d_full_path; for (struct wim_dentry *d = dentry; !dentry_is_root(d); d = d->d_parent) wdentry->depth++; if (inode_has_security_descriptor(inode)) { struct wim_security_data *sd; sd = wim_get_current_security_data(wim); wdentry->security_descriptor = sd->descriptors[inode->i_security_id]; wdentry->security_descriptor_size = sd->sizes[inode->i_security_id]; } wdentry->reparse_tag = inode->i_reparse_tag; wdentry->num_links = inode->i_nlink; wdentry->attributes = inode->i_attributes; wdentry->hard_link_group_id = inode->i_ino; wdentry->creation_time = wim_timestamp_to_timespec(inode->i_creation_time); wdentry->last_write_time = wim_timestamp_to_timespec(inode->i_last_write_time); wdentry->last_access_time = wim_timestamp_to_timespec(inode->i_last_access_time); if (inode_get_unix_data(inode, &unix_data)) { wdentry->unix_uid = unix_data.uid; wdentry->unix_gid = unix_data.gid; wdentry->unix_mode = unix_data.mode; wdentry->unix_rdev = unix_data.rdev; } object_id = inode_get_object_id(inode, &object_id_len); if (unlikely(object_id != NULL)) { memcpy(&wdentry->object_id, object_id, min(object_id_len, sizeof(wdentry->object_id))); } strm = inode_get_unnamed_stream(inode, get_default_stream_type(inode)); if (strm) { ret = stream_to_wimlib_stream_entry(inode, strm, &wdentry->streams[0], wim->blob_table, flags); if (ret) return ret; } for (unsigned i = 0; i < inode->i_num_streams; i++) { strm = &inode->i_streams[i]; if (!stream_is_named_data_stream(strm)) continue; wdentry->num_named_streams++; ret = stream_to_wimlib_stream_entry(inode, strm, &wdentry->streams[ wdentry->num_named_streams], wim->blob_table, flags); if (ret) return ret; } return 0; }
static int execute_update_commands(WIMStruct *wim, const struct wimlib_update_command *cmds, size_t num_cmds, int update_flags) { struct wim_inode_table *inode_table; struct wim_sd_set *sd_set; struct list_head unhashed_streams; struct update_command_journal *j; union wimlib_progress_info info; int ret; if (have_command_type(cmds, num_cmds, WIMLIB_UPDATE_OP_ADD)) { /* If we have at least one "add" command, create the inode and * security descriptor tables to index new inodes and new * security descriptors, respectively. */ inode_table = alloca(sizeof(struct wim_inode_table)); sd_set = alloca(sizeof(struct wim_sd_set)); ret = init_inode_table(inode_table, 9001); if (ret) goto out; ret = init_sd_set(sd_set, wim_get_current_security_data(wim)); if (ret) goto out_destroy_inode_table; INIT_LIST_HEAD(&unhashed_streams); } else { inode_table = NULL; sd_set = NULL; } /* Start an in-memory journal to allow rollback if something goes wrong */ j = new_update_command_journal(num_cmds, &wim_get_current_image_metadata(wim)->root_dentry, wim->lookup_table); if (!j) { ret = WIMLIB_ERR_NOMEM; goto out_destroy_sd_set; } info.update.completed_commands = 0; info.update.total_commands = num_cmds; ret = 0; for (size_t i = 0; i < num_cmds; i++) { DEBUG("Executing update command %zu of %zu (op=%"TS")", i + 1, num_cmds, update_op_to_str(cmds[i].op)); info.update.command = &cmds[i]; if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS) { ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_UPDATE_BEGIN_COMMAND, &info, wim->progctx); if (ret) goto rollback; } switch (cmds[i].op) { case WIMLIB_UPDATE_OP_ADD: ret = execute_add_command(j, wim, &cmds[i], inode_table, sd_set, &unhashed_streams); break; case WIMLIB_UPDATE_OP_DELETE: ret = execute_delete_command(j, wim, &cmds[i]); break; case WIMLIB_UPDATE_OP_RENAME: ret = execute_rename_command(j, wim, &cmds[i]); break; } if (unlikely(ret)) goto rollback; info.update.completed_commands++; if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS) { ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND, &info, wim->progctx); if (ret) goto rollback; } next_command(j); } commit_update(j); if (inode_table) { struct wim_image_metadata *imd; imd = wim_get_current_image_metadata(wim); list_splice_tail(&unhashed_streams, &imd->unhashed_streams); inode_table_prepare_inode_list(inode_table, &imd->inode_list); } goto out_destroy_sd_set; rollback: if (sd_set) rollback_new_security_descriptors(sd_set); rollback_update(j); out_destroy_sd_set: if (sd_set) destroy_sd_set(sd_set); out_destroy_inode_table: if (inode_table) destroy_inode_table(inode_table); out: return ret; }