📄 write.c
字号:
* (TF, Tue Dec 29 13:49:24 CET 1998) */ if ((*r)->isorec.name_len[0] == 1 && *rpnt == 0) return -1; /* '.' */ if ((*l)->isorec.name_len[0] == 1 && *lpnt == 0) return 1; if ((*r)->isorec.name_len[0] == 1 && *rpnt == 1) return -1; /* '..' */ if ((*l)->isorec.name_len[0] == 1 && *lpnt == 1) return 1;#endif while (*rpnt && *lpnt) { if (*rpnt == ';' && *lpnt != ';') return -1; if (*rpnt != ';' && *lpnt == ';') return 1; if (*rpnt == ';' && *lpnt == ';') return 0; if (*rpnt == '.' && *lpnt != '.') return -1; if (*rpnt != '.' && *lpnt == '.') return 1; if ((unsigned char) *rpnt < (unsigned char) *lpnt) return -1; if ((unsigned char) *rpnt > (unsigned char) *lpnt) return 1; rpnt++; lpnt++; } if (*rpnt) return 1; if (*lpnt) return -1; return 0;}/* * Function: sort_directory * * Purpose: Sort the directory in the appropriate ISO9660 * order. * * Notes: Returns 0 if OK, returns > 0 if an error occurred. */intsort_directory(sort_dir, rr) struct directory_entry **sort_dir; int rr;{ int dcount = 0; int xcount = 0; int j; int i, len; struct directory_entry *s_entry; struct directory_entry **sortlist; /* need to keep a count of how many entries are hidden */ s_entry = *sort_dir; while (s_entry) { if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) xcount++; dcount++; s_entry = s_entry->next; } if (dcount == 0) { return 0; } /* OK, now we know how many there are. Build a vector for sorting. */ sortlist = (struct directory_entry **) e_malloc(sizeof(struct directory_entry *) * dcount); j = dcount - 1; dcount = 0; s_entry = *sort_dir; while (s_entry) { if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { /* put any hidden entries at the end of the vector */ sortlist[j--] = s_entry; } else { sortlist[dcount] = s_entry; dcount++; } len = s_entry->isorec.name_len[0]; s_entry->isorec.name[len] = 0; s_entry = s_entry->next; } /* 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 introot_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, ISO_ROUND_UP(root->size)); iso9660_date(root_record.date, root_statbuf.st_mtime); root_record.flags[0] = ISO_DIRECTORY; 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;}#ifdef SORTING/* * sorts deferred_write entries based on the sort weight */static intcompare_sort(rr, ll) const void *rr; const void *ll;{ struct deferred_write **r; struct deferred_write **l; int r_sort; int l_sort; r = (struct deferred_write **) rr; l = (struct deferred_write **) ll; r_sort = (*r)->s_entry->sort; l_sort = (*l)->s_entry->sort; return (r_sort < l_sort ? 1 : -1);}/* * reassign start extents to files that are "hard links" to * files that may have been sorted */static voidreassign_link_addresses(dpnt) struct directory *dpnt;{ struct directory_entry *s_entry; struct file_hash *s_hash; while (dpnt) { s_entry = dpnt->contents; for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) { /* link files have already been given the weight NOT_SORTED */ if (s_entry->sort != NOT_SORTED) continue; /* update the start extent */ s_hash = find_hash(s_entry->dev, s_entry->inode); if(s_hash) { set_733((char *) s_entry->isorec.extent, s_hash->starting_block); s_entry->starting_block = s_hash->starting_block; } } if(dpnt->subdir) { reassign_link_addresses(dpnt->subdir); } dpnt = dpnt->next; }}/* * sort files in order of the given sort weight */static intsort_file_addresses(){ struct deferred_write *dwpnt; struct deferred_write **sortlist; struct directory_entry *s_entry; int start_extent; int num = 0; int i; /* need to store start extents for linked files */ flush_hash(); /* find out how many files we have */ dwpnt = dw_head; while (dwpnt) { num++; dwpnt = dwpnt->next; } /* return if we have none */ if (num == 0) { return (1); } /* save the start extent of the first file */ start_extent = dw_head->extent; /* set up vector to store entries */ sortlist = (struct deferred_write **) e_malloc(sizeof(struct deferred_write *) * num); for (i=0,dwpnt=dw_head;i<num;i++,dwpnt=dwpnt->next) sortlist[i] = dwpnt; /* sort the list */#ifdef __STDC__ qsort(sortlist, num, sizeof(struct deferred_write *), (int (*)(const void *, const void *))compare_sort);#else qsort(sortlist, num, sizeof(struct deferred_write *), compare_sort);#endif /* reconstruct the linked list */ for(i=0; i<num-1; i++) { sortlist[i]->next = sortlist[i+1]; } sortlist[num-1]->next = NULL; dw_head = sortlist[0]; free(sortlist); /* set the new start extents for the sorted list */ for (i=0,dwpnt=dw_head;i<num;i++,dwpnt=dwpnt->next) { s_entry = dwpnt->s_entry; dwpnt->extent = s_entry->starting_block = start_extent; set_733((char *) s_entry->isorec.extent, start_extent); start_extent += ISO_ROUND_UP(s_entry->size) >> 11; /* cache start extents for any linked files */ add_hash(s_entry); } return (0);}#endif /* SORTING */static voidassign_file_addresses(dpnt) 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);#ifdef SORTING /* check for non-directory files */ if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) { /* make sure the real file has the highest weighting */ s_hash->de->sort = MAX(s_entry->sort, s_hash->de->sort); /* flag this as a potential non-sorted file */ s_entry->sort = NOT_SORTED; }#endif /* SORTING */ 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] & ISO_DIRECTORY) { 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 = ISO_ROUND_UP(finddir->size); total_dir_size += s_entry->size; add_hash(s_entry); set_733((char *) s_entry->isorec.size, ISO_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 = ISO_ROUND_UP(dpnt->size); add_hash(s_entry); s_entry->starting_block = dpnt->extent; set_733((char *) s_entry->isorec.size, ISO_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 = ISO_ROUND_UP(dpnt->parent->size); 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; } /* * 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 APPLE_HYB /* * maybe an offset to start of the real * file/fork */ dwpnt->off = s_entry->hfs_off;#else dwpnt->off = 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_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 ((ISO_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 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 = (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)) &
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -