📄 fs_attr.c
字号:
"Null fs_attr in tsk_fs_attr_add_run"); return 1; } // we only support the case of a null run if it is the only run... if (a_data_run_new == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_attr_put_run: Error, NULL run added to existing attribute"); return 1; } run_len = 0; data_run_cur = a_data_run_new; while (data_run_cur) { run_len += data_run_cur->len; data_run_cur = data_run_cur->next; } /* First thing, is to check if we can just add it to the end */ if ((a_fs_attr->nrd.run_end) && (a_fs_attr->nrd.run_end->offset + a_fs_attr->nrd.run_end->len == a_data_run_new->offset)) { a_fs_attr->nrd.run_end->next = a_data_run_new; a_fs_attr->nrd.initsize += (run_len * a_fs->block_size); // update the pointer to the end of the list while (a_fs_attr->nrd.run_end->next) a_fs_attr->nrd.run_end = a_fs_attr->nrd.run_end->next; /* return head of a_fs_attr list */ return 0; } data_run_cur = a_fs_attr->nrd.run; data_run_prev = NULL; while (data_run_cur) { /* Do we replace this filler spot? */ if (data_run_cur->flags & TSK_FS_ATTR_RUN_FLAG_FILLER) { /* This should never happen because we always add * the filler to start from VCN 0 */ if (data_run_cur->offset > a_data_run_new->offset) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_attr_put_run: could not add data_run"); return 1; } /* Check if the new run starts inside of this filler. */ if (data_run_cur->offset + data_run_cur->len > a_data_run_new->offset) { TSK_FS_ATTR_RUN *endrun; /* if the new starts at the same as the filler, * replace the pointer */ if (data_run_cur->offset == a_data_run_new->offset) { if (data_run_prev) data_run_prev->next = a_data_run_new; else a_fs_attr->nrd.run = a_data_run_new; } /* The new run does not start at the begining of * the filler, so make a new start filler */ else { TSK_FS_ATTR_RUN *newfill = tsk_fs_attr_run_alloc(); if (newfill == NULL) return 1; if (data_run_prev) data_run_prev->next = newfill; else a_fs_attr->nrd.run = newfill; newfill->next = a_data_run_new; newfill->len = a_data_run_new->offset - data_run_cur->offset; newfill->offset = data_run_cur->offset; newfill->flags = TSK_FS_ATTR_RUN_FLAG_FILLER; data_run_cur->len -= newfill->len; } /* get to the end of the run that we are trying to add */ endrun = a_data_run_new; while (endrun->next) endrun = endrun->next; /* if the filler is the same size as the * new one, replace it */ if (run_len == data_run_cur->len) { endrun->next = data_run_cur->next; // update the pointer to the end of the list (if we are the end) if (endrun->next == NULL) a_fs_attr->nrd.run_end = endrun; free(data_run_cur); } /* else adjust the last filler entry */ else { endrun->next = data_run_cur; data_run_cur->len -= run_len; } return 0; } } data_run_prev = data_run_cur; data_run_cur = data_run_cur->next; } /* * There is no filler holding the location of this run, so * we will add it to the end of the list * * we got here because it did not fit in the current list or * because the current list is NULL * * At this point data_run_prev is the end of the existing list or * 0 if there is no list */ /* this is an error condition. * it means that we are currently at a greater VCN than * what we are inserting, but we never found the filler * for where we were to insert */ if ((data_run_prev) && (data_run_prev->offset + data_run_prev->len > a_data_run_new->offset)) { /* MAYBE this is because of a duplicate entry .. */ if ((data_run_prev->addr == a_data_run_new->addr) && (data_run_prev->len == a_data_run_new->len)) { // @@@ Sould be we freeing this....? What if the caller tries to write ti it? tsk_fs_attr_run_free(a_data_run_new); return 0; } tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "fs_attr_run: error adding aditional run: %" PRIuDADDR ", Previous %" PRIuDADDR " -> %" PRIuDADDR " Current %" PRIuDADDR " -> %" PRIuDADDR "\n", a_data_run_new->offset, data_run_prev->addr, data_run_prev->len, a_data_run_new->addr, a_data_run_new->len); return 1; } /* we should add it right here */ else if (((data_run_prev) && (data_run_prev->offset + data_run_prev->len == a_data_run_new->offset)) || (a_data_run_new->offset == 0)) { if (data_run_prev) data_run_prev->next = a_data_run_new; else a_fs_attr->nrd.run = a_data_run_new; } /* we need to make a filler before it */ else { TSK_FS_ATTR_RUN *tmprun = tsk_fs_attr_run_alloc(); if (tmprun == NULL) return 1; if (data_run_prev) { data_run_prev->next = tmprun; tmprun->offset = data_run_prev->offset + data_run_prev->len; } else { a_fs_attr->nrd.run = tmprun; } tmprun->len = a_data_run_new->offset - tmprun->offset; tmprun->flags = TSK_FS_ATTR_RUN_FLAG_FILLER; tmprun->next = a_data_run_new; /* Adjust the length of the TSK_FS_ATTR structure to reflect the * new FILLER run */ a_fs_attr->nrd.initsize += (tmprun->len * a_fs->block_size); } /* Adjust the length of the TSK_FS_ATTR structure to reflect the * new run */ a_fs_attr->nrd.initsize += (run_len * a_fs->block_size); // update the pointer to the end of the list a_fs_attr->nrd.run_end = a_data_run_new; while (a_fs_attr->nrd.run_end->next) a_fs_attr->nrd.run_end = a_fs_attr->nrd.run_end->next; return 0;}/** * Append a data run to the end of the attribute and update its offset * value. This ignores the offset in the data run and blindly appends. * * @param a_fs File system run is from * @param a_fs_attr Data attribute to append to * @param a_data_run Data run to append. */voidtsk_fs_attr_append_run(TSK_FS_INFO * a_fs, TSK_FS_ATTR * a_fs_attr, TSK_FS_ATTR_RUN * a_data_run){ TSK_FS_ATTR_RUN *data_run_cur; if ((a_fs_attr == NULL) || (a_data_run == NULL)) { return; } if (a_fs_attr->nrd.run == NULL) { a_fs_attr->nrd.run = a_data_run; a_data_run->offset = 0; } else { // just in case this was not updated if ((a_fs_attr->nrd.run_end == NULL) || (a_fs_attr->nrd.run_end->next != NULL)) { data_run_cur = a_fs_attr->nrd.run; while (data_run_cur->next) { data_run_cur = data_run_cur->next; } a_fs_attr->nrd.run_end = data_run_cur; } a_fs_attr->nrd.run_end->next = a_data_run; a_data_run->offset = a_fs_attr->nrd.run_end->offset + a_fs_attr->nrd.run_end->len; } // update the rest of the offsets in the run (if any exist) data_run_cur = a_data_run; a_fs_attr->nrd.initsize += (data_run_cur->len * a_fs->block_size); while (data_run_cur->next) { data_run_cur->next->offset = data_run_cur->offset + data_run_cur->len; a_fs_attr->nrd.initsize += (data_run_cur->next->len * a_fs->block_size); a_fs_attr->nrd.run_end = data_run_cur->next; data_run_cur = data_run_cur->next; }}/** \internal * Processes a resident TSK_FS_ATTR structure and calls the callback with the associated * data. The size of the buffer in the callback will be block_size at max. * * @param a_fs File system being analyzed * @param fs_attr Resident data structure to be walked * @param a_flags Flags for walking * @param a_action Callback action * @param a_ptr Pointer to data that is passed to callback * @returns 1 on error or 0 on success */static uint8_ttsk_fs_attr_walk_res(const TSK_FS_ATTR * fs_attr, TSK_FS_FILE_WALK_FLAG_ENUM a_flags, TSK_FS_FILE_WALK_CB a_action, void *a_ptr){ char *buf = NULL; int myflags; int retval; size_t buf_len = 0; TSK_OFF_T off; size_t read_len; TSK_FS_INFO *fs; fs = fs_attr->fs_file->fs_info; if ((fs_attr->flags & TSK_FS_ATTR_RES) == 0) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_file_walk_res: called with non-resident data"); return 1; } /* Allocate a buffer that is at most a block size in length */ if ((a_flags & TSK_FS_FILE_WALK_FLAG_AONLY) == 0) { buf_len = (size_t) fs_attr->size; if (buf_len > fs->block_size) buf_len = fs->block_size; if ((buf = tsk_malloc(buf_len)) == NULL) { return 1; } } myflags = TSK_FS_BLOCK_FLAG_CONT | TSK_FS_BLOCK_FLAG_ALLOC | TSK_FS_BLOCK_FLAG_RES; // Call the callback in (at max) block-sized chunks. retval = TSK_WALK_CONT; for (off = 0; off < fs_attr->size; off += read_len) { if (fs_attr->size - off > buf_len) read_len = buf_len; else read_len = (size_t) (fs_attr->size - off); if (buf) { // wipe rest of buffer if we are not going to read into all of it if (read_len != buf_len) memset(&buf[read_len], 0, buf_len - read_len); memcpy(buf, &fs_attr->rd.buf[off], read_len); } retval = a_action(fs_attr->fs_file, off, 0, buf, read_len, myflags, a_ptr); if (retval != TSK_WALK_CONT) break; } if (buf) free(buf); if (retval == TSK_WALK_ERROR) return 1; else return 0;}/** \internal * Processes a non-resident TSK_FS_ATTR structure and calls the callback with the associated * data. * * @param fs_attr Resident data structure to be walked * @param a_flags Flags for walking * @param a_action Callback action * @param a_ptr Pointer to data that is passed to callback * @returns 1 on error or 0 on success */static uint8_ttsk_fs_attr_walk_nonres(const TSK_FS_ATTR * fs_attr, TSK_FS_FILE_WALK_FLAG_ENUM a_flags, TSK_FS_FILE_WALK_CB a_action, void *a_ptr){ char *buf = NULL; TSK_OFF_T tot_size; TSK_OFF_T off = 0; TSK_FS_ATTR_RUN *fs_attr_run; int retval; uint32_t skip_remain; TSK_FS_INFO *fs = fs_attr->fs_file->fs_info; uint8_t stop_loop = 0; if ((fs_attr->flags & TSK_FS_ATTR_NONRES) == 0) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_file_walk_nonres: called with non-non-resident data"); return 1; } /* if we want the slack space too, then use the allocsize */ if (a_flags & TSK_FS_FILE_WALK_FLAG_SLACK) tot_size = fs_attr->nrd.allocsize; else tot_size = fs_attr->size; skip_remain = fs_attr->nrd.skiplen; if ((a_flags & TSK_FS_FILE_WALK_FLAG_AONLY) == 0) { if ((buf = (char *) tsk_malloc(fs->block_size)) == NULL) { return 1; } } /* cycle through the number of runs we have */ retval = TSK_WALK_CONT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -