📄 multi.c
字号:
pnt[i]->next = this_dir->contents; pnt[i]->filedir = this_dir; this_dir->contents = pnt[i]; pnt[i] = NULL; } /* * If we don't have an entry for the translation table, then don't * bother trying to copy the starting extent over. Note that it is * possible that if we are copying the entire directory, the entry for * the translation table will have already been inserted into the * linked list and removed from the old entries list, in which case we * want to leave the extent number as it was before. */ if (ttbl_extent == 0) { return; } /* * Finally, check the directory we are creating to see whether there * are any new entries in it. If there are not, we can reuse the same * translation table. */ for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { /* * Don't care about '.' or '..'. They are never in the table * anyways. */ if (s_entry->name != NULL && strcmp(s_entry->name, ".") == 0) { continue; } if (s_entry->name != NULL && strcmp(s_entry->name, "..") == 0) { continue; }/* if( strcmp(s_entry->name, "<translation table>") == 0)*/ if (strcmp(s_entry->name, trans_tbl) == 0) { continue; } if ((s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0) { return; } } /* * Locate the translation table, and re-use the same extent. It isn't * clear that there should ever be one in there already so for now we * try and muddle through the best we can. */ for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {/* if( strcmp(s_entry->name, "<translation table>") == 0)*/ if (strcmp(s_entry->name, trans_tbl) == 0) { fprintf(stderr, "Should never get here\n"); set_733(s_entry->isorec.extent, ttbl_extent); return; } } pnt[ttbl_index]->next = this_dir->contents; pnt[ttbl_index]->filedir = this_dir; this_dir->contents = pnt[ttbl_index]; pnt[ttbl_index] = NULL;}/* * Here we have a case of a directory that has completely disappeared from * the face of the earth on the tree we are mastering from. Go through and * merge it into the tree, as well as everything beneath it. * * Note that if a directory has been moved for some reason, this will * incorrectly pick it up and attempt to merge it back into the old * location. FIXME(eric). */static intmerge_old_directory_into_tree(dpnt, parent) struct directory_entry *dpnt; struct directory *parent;{ struct directory_entry **contents = NULL; int i; int n_orig; struct directory *this_dir, *next_brother; char whole_path[1024]; this_dir = (struct directory *) e_malloc(sizeof(struct directory)); memset(this_dir, 0, sizeof(struct directory)); this_dir->next = NULL; this_dir->subdir = NULL; this_dir->self = dpnt; this_dir->contents = NULL; this_dir->size = 0; this_dir->extent = 0; this_dir->depth = parent->depth + 1; this_dir->parent = parent; if (!parent->subdir) parent->subdir = this_dir; else { next_brother = parent->subdir; while (next_brother->next) next_brother = next_brother->next; next_brother->next = this_dir; } /* Set the name for this directory. */ strcpy(whole_path, parent->de_name); strcat(whole_path, SPATH_SEPARATOR); strcat(whole_path, dpnt->name); this_dir->de_name = strdup(whole_path); this_dir->whole_name = strdup(whole_path); /* * Now fill this directory using information from the previous session. */ contents = read_merging_directory(&dpnt->isorec, &n_orig); /* * Start by simply copying the '.', '..' and non-directory entries to * this directory. Technically we could let merge_remaining_entries * handle this, but it gets rather confused by the '.' and '..' entries */ for (i = 0; i < n_orig; i++) { /* * We can always reuse the TRANS.TBL in this particular case. */ contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; if (((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) && (i >= 2)) { continue; } /* If we have a directory, don't reuse the extent number. */ if ((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) { memset(contents[i]->isorec.extent, 0, 8); if (strcmp(contents[i]->name, ".") == 0) this_dir->dir_flags |= DIR_HAS_DOT; if (strcmp(contents[i]->name, "..") == 0) this_dir->dir_flags |= DIR_HAS_DOTDOT; } /* * for regilar files, we do it here. * If it has CL or RE attributes, remember its extent */ check_rr_relocation(contents[i]); /* * Set the whole name for this file. */ strcpy(whole_path, this_dir->whole_name); strcat(whole_path, SPATH_SEPARATOR); strcat(whole_path, contents[i]->name); contents[i]->whole_name = strdup(whole_path); contents[i]->next = this_dir->contents; contents[i]->filedir = this_dir; this_dir->contents = contents[i]; contents[i] = NULL; } /* * and for directories, we do it here. * If it has CL or RE attributes, remember its extent */ check_rr_relocation(dpnt); /* * Zero the extent number for ourselves. */ memset(dpnt->isorec.extent, 0, 8); /* * Anything that is left are other subdirectories that need to be * merged. */ merge_remaining_entries(this_dir, contents, n_orig); free_mdinfo(contents, n_orig);#if 0 /* * This is no longer required. The post-scan sort will handle all of * this for us. */ sort_n_finish(this_dir);#endif return 0;}char *cdrecord_data = NULL;intget_session_start(file_addr) int *file_addr;{ char *pnt;#ifdef CDRECORD_DETERMINES_FIRST_WRITABLE_ADDRESS /* * FIXME(eric). We need to coordinate with cdrecord to obtain the * parameters. For now, we assume we are writing the 2nd session, so * we start from the session that starts at 0. */ *file_addr = (16 << 11); /* * We need to coordinate with cdrecord to get the next writable address * from the device. Here is where we use it. */ session_start = last_extent = last_extent_written = cdrecord_result();#else if (cdrecord_data == NULL) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Special parameters for cdrecord not specified with -C\n");#else fprintf(stderr, "Special parameters for cdrecord not specified with -C\n"); exit(1);#endif } /* * Next try and find the ',' in there which delimits the two numbers. */ pnt = strchr(cdrecord_data, ','); if (pnt == NULL) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Malformed cdrecord parameters\n");#else fprintf(stderr, "Malformed cdrecord parameters\n"); exit(1);#endif } *pnt = '\0'; if (file_addr != NULL) { *file_addr = atol(cdrecord_data) * SECTOR_SIZE; } pnt++; session_start = last_extent = last_extent_written = atol(pnt); pnt--; *pnt = ',';#endif return 0;}/* * This function scans the directory tree, looking for files, and it makes * note of everything that is found. We also begin to construct the ISO9660 * directory entries, so that we can determine how large each directory is. */intmerge_previous_session(this_dir, mrootp) struct directory *this_dir; struct iso_directory_record *mrootp;{ struct directory_entry **orig_contents = NULL; struct directory_entry *odpnt = NULL; int n_orig; struct directory_entry *s_entry; int status; int lstatus; struct stat statbuf, lstatbuf; int retcode; /* * Parse the same directory in the image that we are merging for * multisession stuff. */ orig_contents = read_merging_directory(mrootp, &n_orig); if (orig_contents == NULL) { return (0); } /* * Now we scan the directory itself, and look at what is inside of it. */ for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { status = stat_filter(s_entry->whole_name, &statbuf); lstatus = lstat_filter(s_entry->whole_name, &lstatbuf); /* * We always should create an entirely new directory tree * whenever we generate a new session, unless there were * *no* changes whatsoever to any of the directories, in which * case it would be kind of pointless to generate a new * session. * I believe it is possible to rigorously prove that any change * anywhere in the filesystem will force the entire tree to be * regenerated because the modified directory will get a new * extent number. Since each subdirectory of the changed * directory has a '..' entry, all of them will need to be * rewritten too, and since the parent directory of the * modified directory will have an extent pointer to the * directory it too will need to be rewritten. Thus we will * never be able to reuse any directory information when * writing new sessions. * * We still check the previous session so we can mark off the * equivalent entry in the list we got from the original disc, * however. */ /* * The check_prev_session function looks for an identical * entry in the previous session. If we see it, then we copy * the extent number to s_entry, and cross it off the list. * It returns 2 if it's a directory */ retcode = check_prev_session(orig_contents, n_orig, s_entry, &statbuf, &lstatbuf, &odpnt); if (retcode == -1) return (-1); if (retcode == 2 && odpnt != NULL) { int dflag; if (strcmp(s_entry->name, ".") != 0 && strcmp(s_entry->name, "..") != 0) { struct directory *child; /* * XXX It seems that the tree that has been * XXX read from the previous session does not * XXX carry whole_name entries. We provide a * XXX hack in * XXX multi.c:find_or_create_directory() * XXX that should be removed when a * XXX reasonable method could be found. */ child = find_or_create_directory(this_dir, s_entry->whole_name, s_entry, 1); dflag = merge_previous_session(child, &odpnt->isorec); if (dflag == -1) { return (-1); } free(odpnt); odpnt = NULL; } } } /* * Whatever is left over, are things which are no longer in the tree on * disk. We need to also merge these into the tree. */ merge_remaining_entries(this_dir, orig_contents, n_orig); free_mdinfo(orig_contents, n_orig); return (1);}/* * This code deals with relocated directories which may exist * in the previous session. */struct dir_extent_link { unsigned int extent; struct directory_entry *de; struct dir_extent_link *next;};static struct dir_extent_link *cl_dirs = NULL;static struct dir_extent_link *re_dirs = NULL;static voidcheck_rr_relocation(de) struct directory_entry *de;{ unsigned char sector[SECTOR_SIZE]; unsigned char *pnt = de->rr_attributes; int len = de->rr_attr_size; int cont_extent = 0, cont_offset = 0, cont_size = 0; pnt = parse_xa(pnt, &len, /*dpnt*/ 0); while (len >= 4) { if (pnt[3] != 1 && pnt[3] != 2) {#ifdef USE_LIBSCHILY errmsgno(EX_BAD, "**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]);#else fprintf(stderr, "**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]);#endif } if (strncmp((char *) pnt, "CL", 2) == 0) { struct dir_extent_link *dlink = e_malloc(sizeof(*dlink)); dlink->extent = isonum_733(pnt + 4); dlink->de = de; dlink->next = cl_dirs; cl_dirs = dlink; } else if (strncmp((char *) pnt, "RE", 2) == 0) { struct dir_extent_link *dlink = e_malloc(sizeof(*dlink)); dlink->extent = de->starting_block; dlink->de = de; dlink->next = re_dirs; re_dirs = dlink; } else if (strncmp((char *) pnt, "CE", 2) == 0) { cont_extent = isonum_733(pnt + 4); cont_offset = isonum_733(pnt + 12); cont_size = isonum_733(pnt + 20); } else if (strncmp((char *) pnt, "ST", 2) == 0) { len = pnt[2]; } len -= pnt[2]; pnt += pnt[2]; if (len <= 3 && cont_extent) { /* ??? What if cont_offset+cont_size > SECTOR_SIZE */ readsecs(cont_extent, sector, 1); pnt = sector + cont_offset; len = cont_size; cont_extent = cont_offset = cont_size = 0; } }}voidmatch_cl_re_entries(){ struct dir_extent_link *re = re_dirs; /* for each relocated directory */ for (; re; re = re->next) { struct dir_extent_link *cl = cl_dirs; for (; cl; cl = cl->next) { /* find a place where it was relocated from */ if (cl->extent == re->extent) { /* set link to that place */ re->de->parent_rec = cl->de; re->de->filedir = cl->de->filedir; /* * see if it is in rr_moved */ if (reloc_dir != NULL) { struct directory_entry *rr_moved_e = reloc_dir->contents; for (; rr_moved_e; rr_moved_e = rr_moved_e->next) { /* yes it is */ if (re->de == rr_moved_e) { /* forget it */ re->de = NULL; } } } break; } } }}voidfinish_cl_pl_for_prev_session(){ struct dir_extent_link *re = re_dirs; /* for those that were relocated, but NOT to rr_moved */ re = re_dirs; for (; re; re = re->next) { if (re->de != NULL) { /* * here we have hypothetical case when previous session * was not created by mkisofs and contains relocations */ struct directory_entry *s_entry = re->de; struct directory_entry *s_entry1; struct directory *d_entry = reloc_dir->subdir; /* do the same as finish_cl_pl_entries */ if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { continue; } while (d_entry) { if (d_entry->self == s_entry) break; d_entry = d_entry->next; }; if (!d_entry) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Unable to locate directory parent\n");#else fprintf(stderr, "Unable to locate directory parent\n"); exit(1);#endif }; if (s_entry->filedir != NULL && s_entry->parent_rec != NULL) { char *rr_attr; /* * First fix the PL pointer in the directory in the * rr_reloc dir */ s_entry1 = d_entry->contents->next; rr_attr = find_rr_attribute(s_entry1->rr_attributes, s_entry1->total_rr_attr_size, "PL"); if (rr_attr != NULL) set_733(rr_attr + 4, s_entry->filedir->extent); /* Now fix the CL pointer */ s_entry1 = s_entry->parent_rec; rr_attr = find_rr_attribute(s_entry1->rr_attributes, s_entry1->total_rr_attr_size, "CL"); if (rr_attr != NULL) set_733(rr_attr + 4, d_entry->extent); } } } /* free memory */ re = re_dirs; while (re) { struct dir_extent_link *next = re->next; free(re); re = next; } re = cl_dirs; while (re) { struct dir_extent_link *next = re->next; free(re); re = next; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -