📄 write.c
字号:
} /* * Each directory is required to contain at least . and .. */ if( dcount < 2 ) {#ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Directory size too small (. or .. missing ???)\n"); #else fprintf(stderr, "Directory size too small (. or .. missing ???)\n"); #endif sort_goof = 1; } else { /* only sort the non-hidden entries */ sort_goof = 0; is_rr_dir = rr;#ifdef __STDC__ qsort(sortlist, dcount, sizeof(struct directory_entry *), (int (*)(const void *, const void *))compare_dirs);#else qsort(sortlist, dcount, sizeof(struct directory_entry *), compare_dirs);#endif /* * Now reassemble the linked list in the proper sorted order * We still need the hidden entries, as they may be used in the * Joliet tree. */ for(i=0; i<dcount+xcount-1; i++) { sortlist[i]->next = sortlist[i+1]; } sortlist[dcount+xcount-1]->next = NULL; *sort_dir = sortlist[0]; } free(sortlist); sortlist = NULL; return sort_goof;}static int root_gen(){ init_fstatbuf(); root_record.length[0] = 1 + offsetof(struct iso_directory_record, name[0]); root_record.ext_attr_length[0] = 0; set_733((char *) root_record.extent, root->extent); set_733((char *) root_record.size, ROUND_UP(root->size)); iso9660_date(root_record.date, root_statbuf.st_mtime); root_record.flags[0] = 2; root_record.file_unit_size[0] = 0; root_record.interleave[0] = 0; set_723(root_record.volume_sequence_number, volume_sequence_number); root_record.name_len[0] = 1; return 0;}static void FDECL1(assign_file_addresses, struct directory *, dpnt){ struct directory * finddir; struct directory_entry * s_entry; struct file_hash *s_hash; struct deferred_write * dwpnt; char whole_path[1024]; while (dpnt) { s_entry = dpnt->contents; for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) { /* * If we already have an extent for this entry, * then don't assign a new one. It must have come * from a previous session on the disc. Note that * we don't end up scheduling the thing for writing * either. */ if( isonum_733((unsigned char *) s_entry->isorec.extent) != 0 ) { continue; } /* * This saves some space if there are symlinks present */ s_hash = find_hash(s_entry->dev, s_entry->inode); if(s_hash) { if(verbose > 2) { fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name, SPATH_SEPARATOR, s_entry->name); } set_733((char *) s_entry->isorec.extent, s_hash->starting_block); set_733((char *) s_entry->isorec.size, s_hash->size); continue; } /* * If this is for a directory that is not a . or a .. entry, * then look up the information for the entry. We have already * assigned extents for directories, so we just need to * fill in the blanks here. */ if (strcmp(s_entry->name,".") != 0 && strcmp(s_entry->name,"..") != 0 && s_entry->isorec.flags[0] == 2) { finddir = dpnt->subdir; while(1==1) { if(finddir->self == s_entry) break; finddir = finddir->next; if(!finddir) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Fatal goof - could not find dir entry for '%s'\n", s_entry->name);#else fprintf(stderr, "Fatal goof - could not find dir entry for '%s'\n", s_entry->name); exit(1);#endif } } set_733((char *) s_entry->isorec.extent, finddir->extent); s_entry->starting_block = finddir->extent; s_entry->size = ROUND_UP(finddir->size); total_dir_size += s_entry->size; add_hash(s_entry); set_733((char *) s_entry->isorec.size, ROUND_UP(finddir->size)); continue; } /* * If this is . or .., then look up the relevant info from the * tables. */ if(strcmp(s_entry->name,".") == 0) { set_733((char *) s_entry->isorec.extent, dpnt->extent); /* * Set these so that the hash table has the * correct information */ s_entry->starting_block = dpnt->extent; s_entry->size = ROUND_UP(dpnt->size); add_hash(s_entry); s_entry->starting_block = dpnt->extent; set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->size)); continue; } if(strcmp(s_entry->name,"..") == 0) { if(dpnt == root) { total_dir_size += root->size; } set_733((char *) s_entry->isorec.extent, dpnt->parent->extent); /* * Set these so that the hash table has the * correct information */ s_entry->starting_block = dpnt->parent->extent; s_entry->size = ROUND_UP(dpnt->parent->size); add_hash(s_entry); s_entry->starting_block = dpnt->parent->extent; set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->parent->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)); 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 += ROUND_UP(s_entry->size) >> 11; if(verbose > 2) { fprintf(stderr,"%d %d %s\n", s_entry->starting_block, last_extent-1, whole_path); }#ifdef DBG_ISO if((ROUND_UP(s_entry->size) >> 11) > 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; }} /* assign_file_addresses(... */static void FDECL1(free_one_directory, 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; } free (s_entry_d); s_entry_d = NULL; } dpnt->contents = NULL;} /* free_one_directory(... */static void FDECL1(free_directories, struct directory *, dpnt){ while (dpnt) { free_one_directory(dpnt); if(dpnt->subdir) free_directories(dpnt->subdir); dpnt = dpnt->next; }}void FDECL2(generate_one_directory, 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 = (dpnt->size + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); directory_buffer = (char *) e_malloc(total_size); memset(directory_buffer, 0, total_size); dir_index = 0; ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); 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 = (dir_index + (SECTOR_SIZE - 1)) & ~(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 = 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 void FDECL1(build_pathlist, 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 int FDECL2(compare_paths, void const *, r, void const *, l)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -