📄 multi.c
字号:
i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1); continue; } *pnt = (struct directory_entry *) e_malloc(sizeof(**rtn)); (*pnt)->next = NULL;#ifdef DEBUG error("IDR name: '%s' ist: %d soll: %d\n", idr->name, strlen(idr->name), idr->name_len[0]);#endif (*pnt)->isorec = *idr; (*pnt)->starting_block = isonum_733((unsigned char *) idr->extent); (*pnt)->size = isonum_733((unsigned char *) idr->size); (*pnt)->priority = 0; (*pnt)->name = NULL; (*pnt)->got_rr_name = 0; (*pnt)->table = NULL; (*pnt)->whole_name = NULL; (*pnt)->filedir = NULL; (*pnt)->parent_rec = NULL; /* * Set this information so that we correctly cache previous * session bits of information. */ (*pnt)->inode = (*pnt)->starting_block; (*pnt)->dev = PREV_SESS_DEV; (*pnt)->rr_attributes = NULL; (*pnt)->rr_attr_size = 0; (*pnt)->total_rr_attr_size = 0; (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY; /* * Check for and parse any RR attributes for the file. All we * are really looking for here is the original name of the * file. */ rlen = idr->length[0] & 0xff; cpnt = (unsigned char *) idr; rlen -= offsetof(struct iso_directory_record, name[0]); cpnt += offsetof(struct iso_directory_record, name[0]); rlen -= idr->name_len[0]; cpnt += idr->name_len[0]; if ((idr->name_len[0] & 1) == 0) { cpnt++; rlen--; }; if (no_rr) rlen = 0; if (rlen > 0) { (*pnt)->total_rr_attr_size = (*pnt)->rr_attr_size = rlen; (*pnt)->rr_attributes = e_malloc(rlen); memcpy((*pnt)->rr_attributes, cpnt, rlen); seen_rockridge = 1; }#ifdef DEBUG error("INT name: '%s' ist: %d soll: %d\n", (*pnt)->isorec.name, strlen((*pnt)->isorec.name), idr->name_len[0]);#endif if (idr->name_len[0] < sizeof((*pnt)->isorec.name)) { /* * Now zero out the remainder of the name field. */ cpnt = (unsigned char *) (*pnt)->isorec.name; cpnt += idr->name_len[0]; memset(cpnt, 0, sizeof((*pnt)->isorec.name) - idr->name_len[0]); } else { /* * Simple sanity work to make sure that we have no * illegal data structures in our tree. */ (*pnt)->isorec.name[MAX_ISONAME] = '\0'; (*pnt)->isorec.name_len[0] = MAX_ISONAME; } /* * If the filename len from the old session is more * then 31 chars, there is a high risk of hard violations * if the ISO9660 standard. * Run it through our name canonication machine.... */ if (idr->name_len[0] > LEN_ISONAME || check_oldnames) { iso9660_check(idr, *pnt); } if (parse_rr((*pnt)->rr_attributes, rlen, *pnt) == -1) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Cannot parse Rock Ridge attributes for '%s'.\n", idr->name);#else fprintf(stderr, "Cannot parse Rock Ridge attributes for '%s'.\n", idr->name); exit(1);#endif } if (((*pnt)->isorec.name_len[0] == 1) && (((*pnt)->isorec.name[0] == 0) /* "." entry*/ ||((*pnt)->isorec.name[0] == 1))) { /* ".." entry*/ if ((*pnt)->name != NULL) { free((*pnt)->name); } if ((*pnt)->whole_name != NULL) { free((*pnt)->whole_name); } if ((*pnt)->isorec.name[0] == 0) { (*pnt)->name = strdup("."); } else { (*pnt)->name = strdup(".."); } }#ifdef DEBUG fprintf(stderr, "got DE name: %s\n", (*pnt)->name);#endif if (strncmp(idr->name, trans_tbl, strlen(trans_tbl)) == 0) { if ((*pnt)->name != NULL) { free((*pnt)->name); } if ((*pnt)->whole_name != NULL) { free((*pnt)->whole_name); }/* (*pnt)->name = strdup("<translation table>");*/ (*pnt)->name = strdup(trans_tbl); tt_extent = isonum_733((unsigned char *) idr->extent); tt_size = isonum_733((unsigned char *) idr->size); if (tt_extent == 0) tt_size = 0; } pnt++; i += idr->length[0]; } /* * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it * to get the filenames of the files. Also, save the table info, just * in case we need to use it. * * The entries look something like: F ISODUMP.;1 isodump */ if (tt_extent != 0 && tt_size != 0) { nbytes = roundup(tt_size, SECTOR_SIZE); tt_buf = (unsigned char *) e_malloc(nbytes); readsecs(tt_extent, tt_buf, nbytes / SECTOR_SIZE); /* * Loop through the file, examine each entry, and attempt to * attach it to the correct entry. */ cpnt = tt_buf; cpnt1 = tt_buf; while (cpnt - tt_buf < tt_size) { /* Skip to a line terminator, or end of the file. */ while ((cpnt1 - tt_buf < tt_size) && (*cpnt1 != '\n') && (*cpnt1 != '\0')) { cpnt1++; } /* Zero terminate this particular line. */ if (cpnt1 - tt_buf < tt_size) { *cpnt1 = '\0'; } /* * Now dig through the actual directories, and try and * find the attachment for this particular filename. */ for (pnt = rtn, i = 0; i < *nent; i++, pnt++) { rlen = isonum_711((*pnt)->isorec.name_len); /* * If this filename is so long that it would * extend past the end of the file, it cannot * be the one we want. */ if (cpnt + 2 + rlen - tt_buf >= tt_size) { continue; } /* * Now actually compare the name, and make sure * that the character at the end is a ' '. */ if (strncmp((char *) cpnt + 2, (*pnt)->isorec.name, rlen) == 0 && cpnt[2 + rlen] == ' ' && (p = strchr((char *)&cpnt[2 + rlen], '\t'))) { p++; /* * This is a keeper. Now determine the * correct table entry that we will * use on the new image. */ if (strlen(p) > 0) { (*pnt)->table = e_malloc(strlen(p) + 4); sprintf((*pnt)->table, "%c\t%s\n", *cpnt, p); } if (!(*pnt)->got_rr_name) { if ((*pnt)->name != NULL) { free((*pnt)->name); } (*pnt)->name = strdup(p); } break; } } cpnt = cpnt1 + 1; cpnt1 = cpnt; } free(tt_buf); } else if (!seen_rockridge && !warning_given) { /* * Warn the user that iso (8.3) names were used because neither * Rock Ridge (-R) nor TRANS.TBL (-T) name translations were * found. */ fprintf(stderr, "Warning: Neither Rock Ridge (-R) nor TRANS.TBL (-T) \n"); fprintf(stderr, "name translations were found on previous session.\n"); fprintf(stderr, "ISO (8.3) file names have been used instead.\n"); warning_given = 1; } if (dirbuff != NULL) { free(dirbuff); } return rtn;}/* read_merging_directory *//* * Free any associated data related to the structures. */intfree_mdinfo(ptr, len) struct directory_entry **ptr; int len;{ int i; struct directory_entry **p; p = ptr; for (i = 0; i < len; i++, p++) { /* If the tree-handling code decided that it needed an entry, it will have removed it from the list. Thus we must allow for null pointers here. */ if (*p == NULL) { continue; } free_directory_entry(*p); } free(ptr); return 0;}static voidfree_directory_entry(dirp) struct directory_entry *dirp;{ if (dirp->name != NULL) free(dirp->name); if (dirp->whole_name != NULL) free(dirp->whole_name); if (dirp->rr_attributes != NULL) free(dirp->rr_attributes); if (dirp->table != NULL) free(dirp->table); free(dirp);}/* * Search the list to see if we have any entries from the previous * session that match this entry. If so, copy the extent number * over so we don't bother to write it out to the new session. */intcheck_prev_session(ptr, len, curr_entry, statbuf, lstatbuf, odpnt) struct directory_entry **ptr; int len; struct directory_entry *curr_entry; struct stat *statbuf; struct stat *lstatbuf; struct directory_entry **odpnt;{ int i; int rr; int retcode = 0; /* Default not found */ for (i = 0; i < len; i++) { if (ptr[i] == NULL) { /* Used or empty entry skip */ continue; }#if 0 if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 && ptr[i]->name[0] == '\0') { continue; } if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 && ptr[i]->name[0] == 1) { continue; }#else if (ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0) { continue; } if (ptr[i]->name != NULL && strcmp(ptr[i]->name, "..") == 0) { continue; }#endif if (ptr[i]->name != NULL && strcmp(ptr[i]->name, curr_entry->name) != 0) { /* Not the same name continue */ continue; } /* * It's a directory so we must always merge it with the new * session. Never ever reuse directory extents. See comments * in tree.c for an explaination of why this must be the case. */ if ((curr_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) { retcode = 2; /* Flag directory case */ goto found_it; } /* * We know that the files have the same name. If they also * have the same file type (i.e. file, dir, block, etc), then * we can safely reuse the TRANS.TBL entry for this file. The * check_rr_dates() function will do this for us. * * Verify that the file type and dates are consistent. If not, * we probably have a different file, and we need to write it * out again. */ retcode = 1; /* We found a non directory */ if (ptr[i]->rr_attributes != NULL) { if ((rr = check_rr_dates(ptr[i], curr_entry, statbuf, lstatbuf)) == -1) return (-1); if (rr == 0) { /* Different files */ goto found_it; } } /* * Verify size and timestamp. If rock ridge is in use, we * need to compare dates from RR too. Directories are special, * we calculate their size later. */ if (ptr[i]->size != curr_entry->size) { /* Different files */ goto found_it; } if (memcmp(ptr[i]->isorec.date, curr_entry->isorec.date, 7) != 0) { /* Different files */ goto found_it; } /* We found it and we can reuse the extent */ memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8); curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; goto found_it; } return retcode;found_it: if (odpnt != NULL) { *odpnt = ptr[i]; } else { free(ptr[i]); } ptr[i] = NULL; return retcode;}/* * open_merge_image: Open an existing image. */intopen_merge_image(path) char *path;{#ifndef USE_SCG in_image = fopen(path, "rb"); if (in_image == NULL) { return -1; }#else in_image = fopen(path, "rb"); if (in_image == NULL) { if (scsidev_open(path) < 0) return -1; }#endif return 0;}/* * close_merge_image: Close an existing image. */intclose_merge_image(){#ifdef USE_SCG return (scsidev_close());#else return (fclose(in_image));#endif}/* * merge_isofs: Scan an existing image, and return a pointer * to the root directory for this image. */struct iso_directory_record *merge_isofs(path) char *path;{ char buffer[SECTOR_SIZE]; int file_addr; int i; struct iso_primary_descriptor *pri = NULL; struct iso_directory_record *rootp; struct iso_volume_descriptor *vdp; /* * Start by searching for the volume header. Ultimately, we need to * search for volume headers in multiple places because we might be * starting with a multisession image. FIXME(eric). */ get_session_start(&file_addr); for (i = 0; i < 100; i++) { if (readsecs(file_addr / SECTOR_SIZE, buffer, sizeof(buffer) / SECTOR_SIZE) != sizeof(buffer)) {#ifdef USE_LIBSCHILY comerr(" Read error on old image %s\n", path);#else fprintf(stderr, " Read error on old image %s\n", path); exit(10);#endif } vdp = (struct iso_volume_descriptor *) buffer; if ((strncmp(vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) && (isonum_711((unsigned char *) vdp->type) == ISO_VD_PRIMARY)) { break; } file_addr += SECTOR_SIZE; } if (i == 100) { return NULL; } pri = (struct iso_primary_descriptor *) vdp; /* Check the blocksize of the image to make sure it is compatible. */ if ((isonum_723((unsigned char *) pri->logical_block_size) != SECTOR_SIZE) || (isonum_723((unsigned char *) pri->volume_set_size) != 1)) { return NULL; } /* Get the location and size of the root directory. */ rootp = (struct iso_directory_record *) malloc(sizeof(struct iso_directory_record)); memcpy(rootp, pri->root_directory_record, sizeof(*rootp)); return rootp;}voidmerge_remaining_entries(this_dir, pnt, n_orig) struct directory *this_dir; struct directory_entry **pnt; int n_orig;{ int i; struct directory_entry *s_entry; unsigned int ttbl_extent = 0; unsigned int ttbl_index = 0; char whole_path[1024]; /* * Whatever is leftover in the list needs to get merged back into the * directory. */ for (i = 0; i < n_orig; i++) { if (pnt[i] == NULL) { continue; } if (pnt[i]->name != NULL && pnt[i]->whole_name == NULL) { /* Set the name for this directory. */ strcpy(whole_path, this_dir->de_name); strcat(whole_path, SPATH_SEPARATOR); strcat(whole_path, pnt[i]->name); pnt[i]->whole_name = strdup(whole_path); } if (pnt[i]->name != NULL/* && strcmp(pnt[i]->name, "<translation table>") == 0 )*/ && strcmp(pnt[i]->name, trans_tbl) == 0) { ttbl_extent = isonum_733((unsigned char *) pnt[i]->isorec.extent); ttbl_index = i; continue; } /* * Skip directories for now - these need to be treated * differently. */ if ((pnt[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) { /* * FIXME - we need to insert this directory into the * tree, so that the path tables we generate will be * correct. */ if ((strcmp(pnt[i]->name, ".") == 0) || (strcmp(pnt[i]->name, "..") == 0)) { free_directory_entry(pnt[i]); pnt[i] = NULL; continue; } else { merge_old_directory_into_tree(pnt[i], this_dir); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -