📄 write.c
字号:
~(SECTOR_SIZE - 1); } memcpy(directory_buffer + dir_index, &s_entry->isorec, offsetof(struct iso_directory_record, name[0]) + s_entry->isorec.name_len[0]); dir_index += offsetof(struct iso_directory_record, name[0]) + s_entry->isorec.name_len[0]; /* Add the Rock Ridge attributes, if present */ if (s_entry->rr_attr_size) { if (dir_index & 1) { directory_buffer[dir_index++] = 0; } /* * If the RR attributes were too long, then write the * CE records, as required. */ if (s_entry->rr_attr_size != s_entry->total_rr_attr_size) { unsigned char *pnt; int len, nbytes; /* * Go through the entire record and fix up the * CE entries so that the extent and offset * are correct */ pnt = s_entry->rr_attributes; len = s_entry->total_rr_attr_size; while (len > 3) {#ifdef DEBUG if (ce_size <= 0) { fprintf(stderr, "Warning: ce_index(%d) && ce_address(%d) not initialized\n", ce_index, ce_address); }#endif if (pnt[0] == 'C' && pnt[1] == 'E') { nbytes = get_733((char *) pnt + 20); if ((ce_index & (SECTOR_SIZE - 1)) + nbytes >= SECTOR_SIZE) { ce_index = ISO_ROUND_UP(ce_index); } set_733((char *) pnt + 4, (ce_address + ce_index) >> 11); set_733((char *) pnt + 12, (ce_address + ce_index) & (SECTOR_SIZE - 1)); /* * Now store the block in the * ce buffer */ memcpy(ce_buffer + ce_index, pnt + pnt[2], nbytes); ce_index += nbytes; if (ce_index & 1) { ce_index++; } } len -= pnt[2]; pnt += pnt[2]; } } rockridge_size += s_entry->total_rr_attr_size; memcpy(directory_buffer + dir_index, s_entry->rr_attributes, s_entry->rr_attr_size); dir_index += s_entry->rr_attr_size; } if (dir_index & 1) { directory_buffer[dir_index++] = 0; } s_entry_d = s_entry; s_entry = s_entry->next; /* * Joliet doesn't use the Rock Ridge attributes, so we free * it here. */ if (s_entry_d->rr_attributes) { free(s_entry_d->rr_attributes); s_entry_d->rr_attributes = NULL; } } if (dpnt->size != dir_index) {#ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Unexpected directory length %d expected: %d '%s'\n", dpnt->size, dir_index, dpnt->de_name);#else fprintf(stderr, "Unexpected directory length %d expected: %d '%s'\n", dpnt->size, dir_index, dpnt->de_name);#endif } xfwrite(directory_buffer, 1, total_size, outfile); last_extent_written += total_size >> 11; free(directory_buffer); directory_buffer = NULL; if (ce_size > 0) { if (ce_index != dpnt->ce_bytes) {#ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Continuation entry record length mismatch %d expected: %d.\n", ce_index, dpnt->ce_bytes);#else fprintf(stderr, "Continuation entry record length mismatch %d expected: %d.\n", ce_index, dpnt->ce_bytes);#endif } xfwrite(ce_buffer, 1, ce_size, outfile); last_extent_written += ce_size >> 11; free(ce_buffer); ce_buffer = NULL; }}/* generate_one_directory(... */static voidbuild_pathlist(node) struct directory *node;{ struct directory *dpnt; dpnt = node; while (dpnt) { /* skip if it's hidden */ if ((dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0) pathlist[dpnt->path_index] = dpnt; if (dpnt->subdir) build_pathlist(dpnt->subdir); dpnt = dpnt->next; }}/* build_pathlist(... */static intcompare_paths(r, l) void const *r; void const *l;{ struct directory const *ll = *(struct directory * const *) l; struct directory const *rr = *(struct directory * const *) r; if (rr->parent->path_index < ll->parent->path_index) { return -1; } if (rr->parent->path_index > ll->parent->path_index) { return 1; } return strcmp(rr->self->isorec.name, ll->self->isorec.name);}/* compare_paths(... */static intgenerate_path_tables(){ struct directory_entry *de = NULL; struct directory *dpnt; int fix; int i; int j; int namelen; char *npnt; char *npnt1; int tablesize; /* First allocate memory for the tables and initialize the memory */ tablesize = path_blocks << 11; path_table_m = (char *) e_malloc(tablesize); path_table_l = (char *) e_malloc(tablesize); memset(path_table_l, 0, tablesize); memset(path_table_m, 0, tablesize); /* * Now start filling in the path tables. Start with root directory */ if (next_path_index > 0xffff) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Unable to generate sane path tables - too many directories (%d)\n", next_path_index);#else fprintf(stderr, "Unable to generate sane path tables - too many directories (%d)\n", next_path_index); exit(1);#endif } path_table_index = 0; pathlist = (struct directory **) e_malloc(sizeof(struct directory *) * next_path_index); memset(pathlist, 0, sizeof(struct directory *) * next_path_index); build_pathlist(root); do { fix = 0;#ifdef __STDC__ qsort(&pathlist[1], next_path_index - 1, sizeof(struct directory *), (int (*) (const void *, const void *)) compare_paths);#else qsort(&pathlist[1], next_path_index - 1, sizeof(struct directory *), compare_paths);#endif for (j = 1; j < next_path_index; j++) { if (pathlist[j]->path_index != j) { pathlist[j]->path_index = j; fix++; } } } while (fix); for (j = 1; j < next_path_index; j++) { dpnt = pathlist[j]; if (!dpnt) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Entry %d not in path tables\n", j);#else fprintf(stderr, "Entry %d not in path tables\n", j); exit(1);#endif } npnt = dpnt->de_name; /* So the root comes out OK */ if ((*npnt == 0) || (dpnt == root)) { npnt = "."; } npnt1 = strrchr(npnt, PATH_SEPARATOR); if (npnt1) { npnt = npnt1 + 1; } de = dpnt->self; if (!de) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Fatal ISO9660 goof - directory has amnesia\n");#else fprintf(stderr, "Fatal ISO9660 goof - directory has amnesia\n"); exit(1);#endif } namelen = de->isorec.name_len[0]; path_table_l[path_table_index] = namelen; path_table_m[path_table_index] = namelen; path_table_index += 2; set_731(path_table_l + path_table_index, dpnt->extent); set_732(path_table_m + path_table_index, dpnt->extent); path_table_index += 4; set_721(path_table_l + path_table_index, dpnt->parent->path_index); set_722(path_table_m + path_table_index, dpnt->parent->path_index); path_table_index += 2; for (i = 0; i < namelen; i++) { path_table_l[path_table_index] = de->isorec.name[i]; path_table_m[path_table_index] = de->isorec.name[i]; path_table_index++; } if (path_table_index & 1) { path_table_index++; /* For odd lengths we pad */ } } free(pathlist); pathlist = NULL; if (path_table_index != path_table_size) {#ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Path table lengths do not match %d expected: %d\n", path_table_index, path_table_size);#else fprintf(stderr, "Path table lengths do not match %d expected: %d\n", path_table_index, path_table_size);#endif } return 0;}/* generate_path_tables(... */voidmemcpy_max(to, from, max) char *to; char *from; int max;{ int n = strlen(from); if (n > max) { n = max; } memcpy(to, from, n);}/* memcpy_max(... */voidoutputlist_insert(frag) struct output_fragment *frag;{ if (out_tail == NULL) { out_list = out_tail = frag; } else { out_tail->of_next = frag; out_tail = frag; }}static intfile_write(outfile) FILE *outfile;{ int should_write;#ifdef APPLE_HYB char buffer[SECTOR_SIZE]; memset(buffer, 0, sizeof(buffer)); if (apple_hyb) { int i; /* * write out padding to round up to HFS allocation block */ for (i = 0; i < hfs_pad; i++) xfwrite(buffer, 1, sizeof(buffer), outfile); last_extent_written += hfs_pad; }#endif /* APPLE_HYB */ /* OK, all done with that crap. Now write out the directories. This is where the fur starts to fly, because we need to keep track of each file as we find it and keep track of where we put it. */ should_write = last_extent - session_start; if (verbose > 2) {#ifdef DBG_ISO fprintf(stderr, "Total directory extents being written = %d\n", last_extent);#endif#ifdef APPLE_HYB if (apple_hyb) fprintf(stderr, "Total extents scheduled to be written (inc HFS) = %d\n", last_extent - session_start); else#endif /* APPLE_HYB */ fprintf(stderr, "Total extents scheduled to be written = %d\n", last_extent - session_start); } /* Now write all of the files that we need. */ write_files(outfile);#ifdef APPLE_HYB /* write out extents/catalog/dt file */ if (apple_hyb) { xfwrite(hce->hfs_ce, hce->hfs_tot_size, HFS_BLOCKSZ, outfile); /* round up to a whole CD block */ if (HFS_ROUND_UP(hce->hfs_tot_size) - hce->hfs_tot_size * HFS_BLOCKSZ) { xfwrite(buffer, 1, HFS_ROUND_UP(hce->hfs_tot_size) - hce->hfs_tot_size * HFS_BLOCKSZ, outfile); } last_extent_written += ISO_ROUND_UP(hce->hfs_tot_size * HFS_BLOCKSZ) / SECTOR_SIZE; /* write out HFS boot block */ if (mac_boot.name) write_one_file(mac_boot.name, mac_boot.size, outfile, mac_boot.off); }#endif /* APPLE_HYB */ /* The rest is just fluff. */ if (verbose == 0) { return 0; }#ifdef APPLE_HYB if (apple_hyb) { fprintf(stderr, "Total extents actually written (inc HFS) = %d\n", last_extent_written - session_start); fprintf(stderr, "(Size of ISO volume = %d, HFS extra = %d)\n", last_extent_written - session_start - hfs_extra, hfs_extra); } else#else fprintf(stderr, "Total extents actually written = %d\n", last_extent_written - session_start);#endif /* APPLE_HYB */ /* Hard links throw us off here */ if (should_write != last_extent - session_start) { fprintf(stderr, "Number of extents written not what was predicted. Please fix.\n"); fprintf(stderr, "Predicted = %d, written = %d\n", should_write, last_extent); } fprintf(stderr, "Total translation table size: %d\n", table_size); fprintf(stderr, "Total rockridge attributes bytes: %d\n", rockridge_size); fprintf(stderr, "Total directory bytes: %d\n", total_dir_size); fprintf(stderr, "Path table size(bytes): %d\n", path_table_size);#ifdef DEBUG fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n", next_extent, last_extent, last_extent_written);#endif return 0;}/* iso_write(... *//* * Function to write the PVD for the disc. */static intpvd_write(outfile) FILE *outfile;{ char iso_time[17]; int should_write; struct tm local; struct tm gmt; time(&begun); local = *localtime(&begun); gmt = *gmtime(&begun); /* * There was a comment here about breaking in the year 2000. * That's not true, in 2000 tm_year == 100, so 1900+tm_year == 2000. */ sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local.tm_year, local.tm_mon + 1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec); local.tm_min -= gmt.tm_min; local.tm_hour -= gmt.tm_hour; local.tm_yday -= gmt.tm_yday; iso_time[16] = (local.tm_min + 60 * (local.tm_hour + 24 * local.tm_yday)) / 15; /* Next we write out the primary descriptor for the disc */ memset(&vol_desc, 0, sizeof(vol_desc)); vol_desc.type[0] = ISO_VD_PRIMARY; memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); vol_desc.version[0] = 1; memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id)); memcpy_max(vol_desc.system_id, system_id, strlen(system_id)); memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id)); memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id)); should_write = last_extent - session_start; set_733((char *) vol_desc.volume_space_size, should_write); set_723(vol_desc.volume_set_size, volume_set_size); set_723(vol_desc.volume_sequence_number, volume_sequence_number); set_723(vol_desc.logical_block_size, SECTOR_SIZE); /* * The path tables are used by DOS based machines to cache directory * locations */ set_733((char *) vol_desc.path_table_size, path_table_size); set_731(vol_desc.type_l_path_table, path_table[0]); set_731(vol_desc.opt_type_l_path_table, path_table[1]); set_732(vol_desc.type_m_path_table, path_table[2]); set_732(vol_desc.opt_type_m_path_table, path_table[3]); /* Now we copy the actual root directory record */ memcpy(vol_desc.root_directory_record, &root_record, offsetof(struct iso_directory_record, name[0]) + 1); /* * The rest is just fluff. It looks nice to fill in many of these * fields, though. */ FILL_SPACE(volume_set_id); if (volset_id) memcpy_max(vol_desc.volume_set_id, volset_id, strlen(volset_id)); FILL_SPACE(publisher_id); if (publisher) memcpy_max(vol_desc.publisher_id, publisher, strlen(publisher)); FILL_SPACE(preparer_id); if (preparer) memcpy_max(vol_desc.preparer_id, preparer, strlen(preparer)); FILL_SPACE(application_id); if (appid) memcpy_max(vol_desc.application_id, appid, strlen(appid)); FILL_SPACE(copyright_file_id); if (copyright) memcpy_max(vol_desc.copyright_file_id, copyright, strlen(copyright)); FILL_SPACE(abstract_file_id); if (abstract) memcpy_max(vol_desc.abstract_file_id, abstract, strlen(abstract)); FILL_SPACE(bibliographic_file_id); if (biblio) memcpy_max(vol_desc.bibliographic_file_id, biblio, strlen(biblio)); FILL_SPACE(creation_date); FILL_SPACE(modification_date); FILL_SPACE(expiration_date); FILL_SPACE(effective_date); vol_desc.file_structure_version[0] = 1; FILL_SPACE(application_data); memcpy(vol_desc.creation_date, iso_time, 17); memcpy(vol_desc.modification_date, iso_time, 17); memcpy(vol_desc.expiration_date, "0000000000000000", 17); memcpy(vol_desc.effective_date, iso_time, 17); /* if not a bootable cd do it the old way */ xfwrite(&vol_desc, 1, SECTOR_SIZE, outfile); last_extent_written++; return 0;}/* * Function to write the EVD for the disc. */static intevd_write(outfile) FILE *outfile;{ struct iso_primary_descriptor evol_desc; /* * Now write the end volume descriptor. Much simpler than the other * one */ memset(&evol_desc, 0, sizeof(evol_desc)); evol_desc.type[0] = (unsigned char) ISO_VD_END; memcpy(evol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); evol_desc.version[0] = 1; xfwrite(&evol_desc, 1, SECTOR_SIZE, outfile); last_extent_written += 1; return 0;}/* * Function to write the version information for the disc. */static intvers_write(outfile) FILE *outfile;{ char vers[SECTOR_SIZE]; int X_ac; char **X_av; char *cp; int i; int idx = 4; int len; extern char version_string[]; /* Now write the version descriptor. */ memset(vers, 0, sizeof(vers)); strcpy(vers, "MKI "); cp = vers; X_ac = saved_ac(); X_av = saved_av(); strcpy(&cp[idx], ctime(&begun)); idx += 25; strcpy(&cp[idx], version_string); idx += strlen(version_string); for (i = 1; i < X_ac; i++) { len = strlen(X_av[i]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -