static imgtoolerr_t os9_diskimage_createdir(imgtool_partition *partition, const char *path) { imgtoolerr_t err; imgtool_image *image = imgtool_partition_image(partition); struct os9_fileinfo file_info; UINT8 dir_data[64]; UINT32 parent_lsn; err = os9_lookup_path(image, path, CREATE_DIR, &file_info, &parent_lsn, NULL, NULL); if (err) goto done; err = os9_set_file_size(image, &file_info, 64); if (err) goto done; /* create intial directories */ memset(dir_data, 0, sizeof(dir_data)); place_string(dir_data, 0, 32, ".."); place_integer_be(dir_data, 29, 3, parent_lsn); place_string(dir_data, 32, 32, "."); place_integer_be(dir_data, 61, 3, file_info.lsn); err = os9_write_lsn(image, file_info.sector_map[0].lsn, 0, dir_data, sizeof(dir_data)); if (err) goto done; done: return err; }
static imgtoolerr_t os9_diskimage_writefile(imgtool_partition *partition, const char *path, const char *fork, imgtool_stream *sourcef, option_resolution *opts) { imgtoolerr_t err; imgtool_image *image = imgtool_partition_image(partition); struct os9_fileinfo file_info; size_t write_size; void *buf = NULL; int i = -1; UINT32 lsn = 0; UINT32 count = 0; UINT32 sz; const os9_diskinfo *disk_info; disk_info = os9_get_diskinfo(image); buf = malloc(disk_info->sector_size); if (!buf) { err = IMGTOOLERR_OUTOFMEMORY; goto done; } err = os9_lookup_path(image, path, CREATE_FILE, &file_info, NULL, NULL, NULL); if (err) goto done; sz = (UINT32) stream_size(sourcef); err = os9_set_file_size(image, &file_info, sz); if (err) goto done; while(sz > 0) { write_size = (size_t) MIN(sz, (UINT64) disk_info->sector_size); stream_read(sourcef, buf, write_size); while(count == 0) { i++; lsn = file_info.sector_map[i].lsn; count = file_info.sector_map[i].count; } err = os9_write_lsn(image, lsn, 0, buf, write_size); if (err) goto done; lsn++; count--; sz -= write_size; } done: if (buf) free(buf); return err; }
static imgtoolerr_t os9_lookup_path(imgtool_image *img, const char *path, creation_policy_t create, struct os9_fileinfo *file_info, UINT32 *parent_lsn, UINT32 *dirent_lsn, UINT32 *dirent_index) { imgtoolerr_t err = IMGTOOLERR_SUCCESS; struct os9_fileinfo dir_info; UINT32 index, current_lsn, dir_size; UINT32 entry_index = 0; UINT32 free_entry_index = 0xffffffff; UINT32 entry_lsn = 0; UINT32 allocated_lsn = 0; UINT8 entry[32]; UINT8 block[64]; char *filename; const os9_diskinfo *disk_info; disk_info = os9_get_diskinfo(img); current_lsn = disk_info->root_dir_lsn; if (parent_lsn) *parent_lsn = 0; /* we have to transverse each path element */ while(*path) { if (parent_lsn) *parent_lsn = current_lsn; /* decode the directory header of this directory */ err = os9_decode_file_header(img, current_lsn, &dir_info); if (err) goto done; dir_size = dir_info.file_size; /* sanity check directory */ if (!dir_info.directory) { err = (current_lsn == disk_info->root_dir_lsn) ? IMGTOOLERR_CORRUPTIMAGE : IMGTOOLERR_INVALIDPATH; goto done; } /* walk the directory */ for (index = 0; index < dir_size; index += 32) { entry_index = index; entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index); err = os9_read_lsn(img, entry_lsn, entry_index, entry, sizeof(entry)); if (err) goto done; /* remember first free entry found */ if( free_entry_index == 0xffffffff ) { if( entry[0] == 0 ) free_entry_index = index; } if (os9_interpret_dirent(entry, &filename, ¤t_lsn, NULL)) { if (!strcmp(path, filename)) break; } } /* at the end of the file? */ if (index >= dir_size) { /* if we're not creating, or we are creating but we have not fully * transversed the directory, error out */ if (!create || path[strlen(path) + 1]) { err = IMGTOOLERR_PATHNOTFOUND; goto done; } /* allocate a new LSN */ err = os9_allocate_lsn(img, &allocated_lsn); if (err) goto done; /* write the file */ memset(block, 0, sizeof(block)); place_integer_be(block, 0, 1, 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00)); err = os9_write_lsn(img, allocated_lsn, 0, block, sizeof(block)); if (err) goto done; if( free_entry_index == 0xffffffff ) { /* expand the directory to hold the new entry */ err = os9_set_file_size(img, &dir_info, dir_size + 32); if (err) goto done; } else /* use first unused entry in directory */ dir_size = free_entry_index; /* now prepare the directory entry */ memset(entry, 0, sizeof(entry)); place_string(entry, 0, 28, path); place_integer_be(entry, 29, 3, allocated_lsn); /* now write the directory entry */ entry_index = dir_size; entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index); err = os9_write_lsn(img, entry_lsn, entry_index, entry, 32); if (err) goto done; /* directory entry append complete; no need to hold this lsn */ current_lsn = allocated_lsn; allocated_lsn = 0; } path += strlen(path) + 1; } if (file_info) { err = os9_decode_file_header(img, current_lsn, file_info); if (err) goto done; } if (dirent_lsn) *dirent_lsn = entry_lsn; if (dirent_index) *dirent_index = entry_index; done: if (allocated_lsn != 0) os9_deallocate_lsn(img, allocated_lsn); return err; }