📄 write.c
字号:
}#endifstatic intcompare_dirs(rr, ll) const void *rr; const void *ll;{ char *rpnt, *lpnt; struct directory_entry **r, **l; r = (struct directory_entry **) rr; l = (struct directory_entry **) ll; rpnt = (*r)->isorec.name; lpnt = (*l)->isorec.name;#ifdef APPLE_HYB /* * resource fork MUST (not sure if this is true for HFS volumes) be * before the data fork - so force it here */ if ((*r)->assoc && (*r)->assoc == (*l)) return 1; if ((*l)->assoc && (*l)->assoc == (*r)) return -1;#endif /* APPLE_HYB */ /* If the entries are the same, this is an error. */ if (strcmp(rpnt, lpnt) == 0) {#ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n", (*r)->whole_name, (*l)->whole_name, rpnt);#else fprintf(stderr, "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n", (*r)->whole_name, (*l)->whole_name, rpnt);#endif sort_goof++; } /* Check we don't have the same RR name */ if (use_RockRidge && !is_rr_dir) { /* * entries *can* have the same RR name in the "rr_moved" * directory so skip checks if we're in reloc_dir */ if (!(strcmp((*r)->name, (*l)->name))) {#ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n", (*r)->whole_name, (*l)->whole_name, (*r)->name);#else fprintf(stderr, "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n", (*r)->whole_name, (*l)->whole_name, (*r)->name);#endif sort_goof++; } } /* * Put the '.' and '..' entries on the head of the sorted list. For * normal ASCII, this always happens to be the case, but out of band * characters cause this not to be the case sometimes. * FIXME(eric) - these tests seem redundant, in that the name is never * assigned these values. It will instead be \000 or \001, and thus * should always be sorted correctly. I need to figure out why I * thought I needed this in the first place. */#if 0 if (strcmp(rpnt, ".") == 0) return -1; if (strcmp(lpnt, ".") == 0) return 1; if (strcmp(rpnt, "..") == 0) return -1; if (strcmp(lpnt, "..") == 0) return 1;#else /* * The code above is wrong (as explained in Eric's comment), leading to * incorrect sort order iff the -L option ("allow leading dots") is in * effect and a directory contains entries that start with a dot. * (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; if (r_sort != l_sort) return (r_sort < l_sort ? 1 : -1); else return (*r)->extent - (*l)->extent;}/* * 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_BLOCKS(s_entry->size);#ifdef DVD_VIDEO /* * Shouldn't this be done for every type of sort? Otherwise * we will loose every pad info we add if we sort the files */ if (dvd_video) { start_extent += dwpnt->pad; }#endif /*DVD_VIDEO*/ /* 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[PATH_MAX]; char tempbuf[255]; char md5result[33]; int i, j;#ifdef DVD_VIDEO char dvd_path[PATH_MAX]; title_set_info_t * title_set_info=NULL;#endif#ifdef DVD_VIDEO if (dvd_video && (strstr(dpnt->whole_name, "VIDEO_TS") != 0)) { int maxlen = strlen(dpnt->whole_name)-8; if (maxlen > (sizeof(dvd_path)-1)) maxlen = sizeof(dvd_path)-1; strncpy(dvd_path, dpnt->whole_name, maxlen); dvd_path[maxlen] = '\0'; #ifdef DEBUG fprintf(stderr, "Found it the path is %s \n", dvd_path);#endif title_set_info = DVDGetFileSet(dvd_path); if (title_set_info == 0) { dvd_video = 0; errmsgno(EX_BAD, "Unable to make a DVD-Video image.\n"); } }#endif /*DVD_VIDEO*/ 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#ifdef DVD_VIDEO if (title_set_info != 0) { DVDFreeFileSet(title_set_info); }#endif 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);#ifdef DVD_VIDEO if (title_set_info != 0) { DVDFreeFileSet(title_set_info); }#endif 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -