📄 write.c
字号:
add_hash(s_entry); s_entry->starting_block = dpnt->parent->extent; set_733((char *) s_entry->isorec.size, ISO_ROUND_UP(dpnt->parent->size)); continue; } if ((use_Md5Opt) && (s_entry->whole_name != NULL)) { /* calc the MD5 hash value */ memset(md5result,0,33); if (s_entry->size && MD5File(md5result,s_entry->whole_name)) { // md5 calc ok, make hash key struct directory_entry *hash_result; sprintf(tempbuf,"%d%s",s_entry->size,md5result);#define WR_SHOWF#ifdef WR_SHOWF if (showcount <=0) fprintf(stderr, "Scanning the Source files: (using MD5 Technology!)\n"); showcount ++; fprintf(stderr, "\r[%05d]%.72s", showcount, s_entry->whole_name); // printf("\r[%05d]%.73s", showcount, s_entry->whole_name); i = 1; j = 73 - strlen(s_entry->whole_name);
while (i < j)
{
fprintf (stderr," "); // printf (" ");
i++;
}
#endif/* #define WR_DEBUG */#ifdef WR_DEBUG // debug enable, check detail if size is 377 or 7238
if ((s_entry->size != 377) || (s_entry->size == 7238)) {
fprintf(stderr, "\nFile=%s \nSize=%d \nMd5s=",
s_entry->whole_name,s_entry->size);
fprintf (stderr,"%s\n", md5result);
} #endif /* !WR_DEBUG */ hash_result = (struct directory_entry *)htInTable(md5_hash,tempbuf); if (!hash_result) { htAddToTable(md5_hash,tempbuf,(void *) s_entry); } else { // found a matching md5 hash! using the duplicate file set_733((char *) s_entry->isorec.extent, hash_result->starting_block); set_733((char *) s_entry->isorec.size, hash_result->size); continue; } } } /* * Some ordinary non-directory file. Just schedule * the file to be written. This is all quite * straightforward, just make a list and assign * extents as we go. Once we get through writing all * of the directories, we should be ready write out * these files */ if (s_entry->size) { dwpnt = (struct deferred_write *) e_malloc(sizeof(struct deferred_write)); /* save this directory entry for later use */ dwpnt->s_entry = s_entry; /* set the initial padding to zero */ dwpnt->pad = 0;#ifdef DVD_VIDEO if (dvd_video && (title_set_info != 0)) { dwpnt->pad = DVDGetFilePad(title_set_info, s_entry->name);#ifdef DEBUG fprintf(stderr, "The pad was %d for file %s\n", dwpnt->pad, s_entry->name);#endif }#endif /*DVD_VIDEO*/#ifdef APPLE_HYB /* * maybe an offset to start of the real * file/fork */ dwpnt->off = s_entry->hfs_off;#else dwpnt->off = (off_t)0;#endif /* APPLE_HYB */ if (dw_tail) { dw_tail->next = dwpnt; dw_tail = dwpnt; } else { dw_head = dwpnt; dw_tail = dwpnt; } if (s_entry->inode == TABLE_INODE) { dwpnt->table = s_entry->table; dwpnt->name = NULL; sprintf(whole_path, "%s%s%s", s_entry->filedir->whole_name, SPATH_SEPARATOR, trans_tbl); } else { dwpnt->table = NULL; strcpy(whole_path, s_entry->whole_name); dwpnt->name = strdup(whole_path); } dwpnt->next = NULL; dwpnt->size = s_entry->size; dwpnt->extent = last_extent; set_733((char *) s_entry->isorec.extent, last_extent); s_entry->starting_block = last_extent; add_hash(s_entry); last_extent += ISO_BLOCKS(s_entry->size);#ifdef DVD_VIDEO /* Shouldn't we always add the pad info? */ if (dvd_video) { last_extent += dwpnt->pad; }#endif /*DVD_VIDEO*/ if (verbose > 2) { fprintf(stderr, "%d %d %s\n", s_entry->starting_block, last_extent - 1, whole_path); }#ifdef DBG_ISO if (ISO_BLOCKS(s_entry->size) > 500) { fprintf(stderr, "Warning: large file '%s'\n", whole_path); fprintf(stderr, "Starting block is %d\n", s_entry->starting_block); fprintf(stderr, "Reported file size is %d extents\n", s_entry->size); }#endif#ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */ if (last_extent > (800000000 >> 11)) { /* More than 800Mb? Punt */ fprintf(stderr, "Extent overflow processing file '%s'\n", whole_path); fprintf(stderr, "Starting block is %d\n", s_entry->starting_block); fprintf(stderr, "Reported file size is %d extents\n", s_entry->size); exit(1); }#endif continue; } /* * This is for zero-length files. If we leave the * extent 0, then we get screwed, because many readers * simply drop files that have an extent of zero. * Thus we leave the size 0, and just assign the * extent number. */ set_733((char *) s_entry->isorec.extent, last_extent); } if (dpnt->subdir) { assign_file_addresses(dpnt->subdir); } dpnt = dpnt->next; }#ifdef DVD_VIDEO if (title_set_info != NULL) { DVDFreeFileSet(title_set_info); }#endif /*DVD_VIDEO*/}/* assign_file_addresses(... */static voidfree_one_directory(dpnt) struct directory *dpnt;{ struct directory_entry *s_entry; struct directory_entry *s_entry_d; s_entry = dpnt->contents; while (s_entry) { s_entry_d = s_entry; s_entry = s_entry->next; if (s_entry_d->rr_attributes) { free(s_entry_d->rr_attributes); s_entry_d->rr_attributes = NULL; } if (s_entry_d->name != NULL) { free(s_entry_d->name); s_entry_d->name = NULL; } if (s_entry_d->whole_name != NULL) { free(s_entry_d->whole_name); s_entry_d->whole_name = NULL; }#ifdef APPLE_HYB if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc) free(s_entry_d->hfs_ent);#endif /* APPLE_HYB */ free(s_entry_d); s_entry_d = NULL; } dpnt->contents = NULL;}/* free_one_directory(... */static voidfree_directories(dpnt) struct directory *dpnt;{ while (dpnt) { free_one_directory(dpnt); if (dpnt->subdir) free_directories(dpnt->subdir); dpnt = dpnt->next; }}voidgenerate_one_directory(dpnt, outfile) struct directory *dpnt; FILE *outfile;{ unsigned int ce_address = 0; char *ce_buffer; unsigned int ce_index = 0; unsigned int ce_size; unsigned int dir_index; char *directory_buffer; int new_reclen; struct directory_entry *s_entry; struct directory_entry *s_entry_d; unsigned int total_size; total_size = ISO_ROUND_UP(dpnt->size); directory_buffer = (char *) e_malloc(total_size); memset(directory_buffer, 0, total_size); dir_index = 0; ce_size = ISO_ROUND_UP(dpnt->ce_bytes); ce_buffer = NULL; if (ce_size > 0) { ce_buffer = (char *) e_malloc(ce_size); memset(ce_buffer, 0, ce_size); ce_index = 0; /* Absolute byte address of CE entries for this directory */ ce_address = last_extent_written + (total_size >> 11); ce_address = ce_address << 11; } s_entry = dpnt->contents; while (s_entry) { /* skip if it's hidden */ if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { s_entry = s_entry->next; continue; } /* * We do not allow directory entries to cross sector * boundaries. Simply pad, and then start the next entry at * the next sector */ new_reclen = s_entry->isorec.length[0]; if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) { dir_index = ISO_ROUND_UP(dir_index); } 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 */ 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; if (dpnt->parent->path_index > 0xffff) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Unable to generate sane path tables - too many directories (%d)\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -