int cdfs_opendir(struct file *filp, char *name) { struct cdfs *cdfs = (struct cdfs *) filp->fs->data; struct iso_directory_record *rec; struct cdfs_file *cdfile; struct buf *buf; time_t date; int size; int extent; int flags; int rc; // Locate directory rc = cdfs_find_file(cdfs, name, strlen(name), &buf, &rec); if (rc < 0) return rc; flags = isonum_711(rec->flags); extent = isonum_733(rec->extent); date = cdfs_isodate(rec->date); size = isonum_733(rec->size); release_buffer(cdfs->cache, buf); if (!(flags & 2)) return -ENOTDIR; // Allocate and initialize file block cdfile = (struct cdfs_file *) kmalloc(sizeof(struct cdfs_file)); if (!cdfile) return -ENOMEM; cdfile->extent = extent; cdfile->date = date; cdfile->size = size; filp->data = cdfile; filp->mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; return 0; }
static APIRET getSetAllocInfo(ServerData * pServerData, struct fsinfo * pfsinfo) { PFSALLOCATE pfsalloc; if (pfsinfo->fsFlag == INFO_RETRIEVE) { if (pfsinfo->cbData < sizeof(FSALLOCATE)) return ERROR_BUFFER_OVERFLOW; pfsinfo->cbData = sizeof(FSALLOCATE); pfsalloc = (PFSALLOCATE) pServerData->pData; pfsalloc->idFileSystem = 0; pfsalloc->cSectorUnit = 1; pfsalloc->cUnitAvail = 0; if (pfsinfo->pVolData->high_sierra) { struct hs_primary_descriptor *hpd = (struct hs_primary_descriptor *) &pfsinfo->pVolData->ipd; pfsalloc->cUnit = isonum_733((unsigned char *)&(hpd->volume_space_size)); pfsalloc->cbSector = isonum_723(hpd->logical_block_size); } else { pfsalloc->cUnit = isonum_733((unsigned char *)&(pfsinfo->pVolData->ipd.volume_space_size)); pfsalloc->cbSector = isonum_723(pfsinfo->pVolData->ipd.logical_block_size); } return NO_ERROR; } else { logMsg(L_EVIL, "cannot set FSALLOCATE"); return ERROR_NOT_SUPPORTED; } }
/* * Make a mount point from a volume descriptor */ static int iso_makemp(struct iso_mnt *isomp, struct buf *bp, int *ea_len) { struct iso_primary_descriptor *pri; int logical_block_size; struct iso_directory_record *rootp; pri = (struct iso_primary_descriptor *)bp->b_data; logical_block_size = isonum_723 (pri->logical_block_size); if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE || (logical_block_size & (logical_block_size - 1)) != 0) return -1; rootp = (struct iso_directory_record *)pri->root_directory_record; isomp->logical_block_size = logical_block_size; isomp->volume_space_size = isonum_733 (pri->volume_space_size); memcpy(isomp->root, rootp, sizeof(isomp->root)); isomp->root_extent = isonum_733 (rootp->extent); isomp->root_size = isonum_733 (rootp->size); isomp->im_joliet_level = 0; isomp->im_bmask = logical_block_size - 1; isomp->im_bshift = 0; while ((1 << isomp->im_bshift) < isomp->logical_block_size) isomp->im_bshift++; if (ea_len != NULL) *ea_len = isonum_711(rootp->ext_attr_length); return 0; }
int cdfs_stat(struct fs *fs, char *name, struct stat64 *buffer) { struct cdfs *cdfs = (struct cdfs *) fs->data; struct iso_directory_record *rec; struct buf *buf; int rc; int size; rc = cdfs_find_file(cdfs, name, strlen(name), &buf, &rec); if (rc < 0) return rc; size = isonum_733(rec->size); if (buffer) { memset(buffer, 0, sizeof(struct stat64)); if (rec->flags[0] & 2) { buffer->st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; } else { buffer->st_mode = S_IFREG | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; } buffer->st_ino = isonum_733(rec->extent); buffer->st_nlink = 1; buffer->st_dev = cdfs->devno; buffer->st_atime = buffer->st_mtime = buffer->st_ctime = cdfs_isodate(rec->date); buffer->st_size = size; }; release_buffer(cdfs->cache, buf); return size; }
/* * Continuation pointer */ static int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana) { ana->iso_ce_blk = isonum_733(p->location); ana->iso_ce_off = isonum_733(p->offset); ana->iso_ce_len = isonum_733(p->length); return ISO_SUSP_CONT; }
/* * POSIX file attribute */ static int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana) { ana->inop->inode.iso_mode = isonum_733(p->mode); ana->inop->inode.iso_uid = isonum_733(p->uid); ana->inop->inode.iso_gid = isonum_733(p->gid); ana->inop->inode.iso_links = isonum_733(p->links); ana->fields &= ~ISO_SUSP_ATTR; return ISO_SUSP_ATTR; }
static iso9660_DIR* iso9660_opendir_node(iso9660_VOLUME *volume, struct iso_directory_record *node) { iso9660_DIR *dir; dir = (iso9660_DIR*)malloc(sizeof(iso9660_DIR)); if (dir == NULL) return NULL; dir->extent = isonum_733((char *)node->extent); dir->len = isonum_733((char *)node->size); dir->index = sizeof (dir->buffer); dir->volume = volume; return dir; }
/* * POSIX device modes */ static int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana) { u_int high, low; high = isonum_733(p->dev_t_high); low = isonum_733(p->dev_t_low); if (high == 0) ana->inop->inode.iso_rdev = makeudev(umajor(low), uminor(low)); else ana->inop->inode.iso_rdev = makeudev(high, uminor(low)); ana->fields &= ~ISO_SUSP_DEVICE; return ISO_SUSP_DEVICE; }
/* * Parent or Child Link */ static int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana) { *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; }
static void dir_fs ( file_desc_t *fd ) { iso9660_COMMON *common = (iso9660_COMMON *)fd; struct iso_directory_record *idr; char name_buf[256]; if (common->type != DIR) return; forth_printf("\n"); while ( (idr = iso9660_readdir(common->dir)) ) { forth_printf("% 10d ", isonum_733(idr->size)); forth_printf("%d-%02d-%02d %02d:%02d:%02d ", idr->date[0] + 1900, /* year */ idr->date[1], /* month */ idr->date[2], /* day */ idr->date[3], idr->date[4], idr->date[5]); iso9660_name(common->dir->volume, idr, name_buf); if (idr->flags[0] & 2) forth_printf("%s\\\n", name_buf); else forth_printf("%s\n", name_buf); } }
main(int argc, char * argv[]){ int file_addr, file_size; char c; int nbyte; struct iso_primary_descriptor ipd; struct iso_directory_record * idr; int typel_extent, typem_extent; int path_table_size; int i,j; if(argc < 2) return 0; infile = fopen(argv[1],"rb"); file_addr = 32768; lseek(fileno(infile), file_addr, 0); read(fileno(infile), &ipd, sizeof(ipd)); idr = (struct iso_directory_record *) &ipd.root_directory_record; blocksize = isonum_723((char *)ipd.logical_block_size); if( blocksize != 512 && blocksize != 1024 && blocksize != 2048 ) { blocksize = 2048; } file_addr = isonum_733(idr->extent) + isonum_711((char *)idr->ext_attr_length); file_size = isonum_733(idr->size); printf("Root at extent %x, %d bytes\n", file_addr, file_size); file_addr = file_addr * blocksize; check_tree(file_addr, file_size, file_addr); typel_extent = isonum_731((char *)ipd.type_l_path_table); typem_extent = isonum_732((char *)ipd.type_m_path_table); path_table_size = isonum_733(ipd.path_table_size); /* Enable this to get the dump of the path tables */ #if 0 check_path_tables(typel_extent, typem_extent, path_table_size); #endif fclose(infile); if(!ngoof) printf("No errors found\n"); }
int isofs_read(const char *path,char *read_buf,size_t size,off_t offset) { log_msg("i am now in read_block\n"); struct iso_inode *inode = isofs_lookup(path); if(!inode) { fprintf(stderr,"no such file or directory found \n"); return -ENOENT; } if(ISO_FLAGS_DIR(inode->record->flags)) { fprintf(stderr,"not a regular file may be a directory\n"); return -EINVAL; } int data_size = gvar->data_size; struct iso_directory_record *dr = inode->record; int start_block = isonum_733(dr->extent); int end_block = isonum_733(dr->size)/data_size; int in_block = end_block - start_block ; int offset_block_start = offset / data_size; int offset_block_end = (offset + size) / data_size; int offset_shift_point = (offset%data_size); int block = offset_block_start + start_block; log_msg("malloced .....\n"); char *buf = (char *) malloc(data_size); if(!buf) { perror("isofs_read:cannot malloc"); exit(0); } int total = 0; int count = 0; int len; do{ log_msg("read_raw_block.....\n"); len = read_raw_block(block,buf); log_msg("buffer is now ....%s\n",buf); memcpy(read_buf+count*data_size,buf+offset_shift_point,data_size); log_msg("the read_buf is %s",read_buf); offset_shift_point = 0; count ++; block++; total += len; }while(count <= in_block); return total; }
static ISO_SUSP_HEADER * susp_lookup_record(struct open_file *f, const char *identifier, struct iso_directory_record *dp, int lenskip) { static char susp_buffer[ISO_DEFAULT_BLOCK_SIZE]; ISO_SUSP_HEADER *sh; ISO_RRIP_CONT *shc; char *p, *end; int error; size_t read; p = dp->name + isonum_711(dp->name_len) + lenskip; /* Names of even length have a padding byte after the name. */ if ((isonum_711(dp->name_len) & 1) == 0) p++; end = (char *)dp + isonum_711(dp->length); while (p + 3 < end) { sh = (ISO_SUSP_HEADER *)p; if (bcmp(sh->type, identifier, 2) == 0) return (sh); if (bcmp(sh->type, SUSP_STOP, 2) == 0) return (NULL); if (bcmp(sh->type, SUSP_CONTINUATION, 2) == 0) { shc = (ISO_RRIP_CONT *)sh; error = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(isonum_733(shc->location)), ISO_DEFAULT_BLOCK_SIZE, susp_buffer, &read); /* Bail if it fails. */ if (error != 0 || read != ISO_DEFAULT_BLOCK_SIZE) return (NULL); p = susp_buffer + isonum_733(shc->offset); end = p + isonum_733(shc->length); } else { /* Ignore this record and skip to the next. */ p += isonum_711(sh->length); /* Avoid infinite loops with corrupted file systems */ if (isonum_711(sh->length) == 0) return (NULL); } } return (NULL); }
static int cdfs_find_in_dir(struct cdfs *cdfs, int dir, char *name, int len, struct buf **dirbuf, struct iso_directory_record **dirrec) { struct buf *buf; char *p; struct iso_directory_record *rec; int blk; int left; int reclen; int namelen; // The first two directory records are . (current) and .. (parent) blk = cdfs->path_table[dir]->extent; buf = get_buffer(cdfs->cache, blk++); if (!buf) return -EIO; // Get length of directory from the first record p = buf->data; rec = (struct iso_directory_record *) p; left = isonum_733(rec->size); // Find named entry in directory while (left > 0) { // Read next block if all records in current block has been read // Directory records never cross block boundaries if (p >= buf->data + CDFS_BLOCKSIZE) { release_buffer(cdfs->cache, buf); if (p > buf->data + CDFS_BLOCKSIZE) return -EIO; buf = get_buffer(cdfs->cache, blk++); if (!buf) return -EIO; p = buf->data; } // Check for match rec = (struct iso_directory_record *) p; reclen = isonum_711(rec->length); namelen = isonum_711(rec->name_len); if (reclen > 0) { if (cdfs_fnmatch(cdfs, name, len, (char *) rec->name, namelen)) { *dirrec = rec; *dirbuf = buf; return 0; } // Skip to next record p += reclen; left -= reclen; } else { // Skip to next block left -= (buf->data + CDFS_BLOCKSIZE) - p; p = buf->data + CDFS_BLOCKSIZE; } } release_buffer(cdfs->cache, buf); return -ENOENT; }
void K3b::Iso9660::createSimplePrimaryDesc( struct iso_primary_descriptor* desc ) { d->primaryDesc.volumeId = QString::fromLocal8Bit( desc->volume_id, 32 ).trimmed(); d->primaryDesc.systemId = QString::fromLocal8Bit( desc->system_id, 32 ).trimmed(); d->primaryDesc.volumeSetId = QString::fromLocal8Bit( desc->volume_set_id, 128 ).trimmed(); d->primaryDesc.publisherId = QString::fromLocal8Bit( desc->publisher_id, 128 ).trimmed(); d->primaryDesc.preparerId = QString::fromLocal8Bit( desc->preparer_id, 128 ).trimmed(); d->primaryDesc.applicationId = QString::fromLocal8Bit( desc->application_id, 128 ).trimmed(); d->primaryDesc.volumeSetSize = isonum_723(desc->volume_set_size); d->primaryDesc.volumeSetNumber = isonum_723(desc->volume_set_size); d->primaryDesc.logicalBlockSize = isonum_723(desc->logical_block_size); d->primaryDesc.volumeSpaceSize = isonum_733(desc->volume_space_size); }
int devopen(u_int32_t session) { int rv; u_int32_t rootdirblk; struct iso_directory_record *rootdirp; if ((rv = bread(session + 16, 1, &pdesc)) != 0) { printf("Error reading primary ISO descriptor: %d\n", rv); return -1; } rootdirp = (struct iso_directory_record *)pdesc.root_directory_record; rootdirblk = isonum_733(rootdirp->extent); rootdirsize = isonum_733(rootdirp->size); /* just in case, round up */ rootdirsize = (rootdirsize + BLKSIZE - 1) & ~(BLKSIZE - 1); if (rootdirbuf != NULL) free(rootdirbuf); if ((rootdirbuf = malloc(rootdirsize)) == 0) { printf("Cannot allocate memory for the root " "directory buffer.\n"); return -1; } if ((rv = bread(rootdirblk, rootdirsize / BLKSIZE, rootdirbuf)) != 0) { printf("Error reading root directory: %d\n", rv); return -1; } DPRINTF(("Root directory is 0x%x bytes @ %d\n", rootdirsize, rootdirblk)); return 0; }
static void isosize(int argc, char *filenamep, int xflag, long divisor) { int fd, nsecs, ssize; struct iso_primary_descriptor ipd; if ((fd = open(filenamep, O_RDONLY)) < 0) err(EXIT_FAILURE, _("cannot open %s"), filenamep); if (is_iso(fd)) warnx(_("%s: might not be an ISO filesystem"), filenamep); if (lseek(fd, 16 << 11, 0) == (off_t) - 1) err(EXIT_FAILURE, _("seek error on %s"), filenamep); if (read(fd, &ipd, sizeof(ipd)) <= 0) err(EXIT_FAILURE, _("read error on %s"), filenamep); nsecs = isonum_733(ipd.volume_space_size, xflag); /* isonum_723 returns nowadays always 2048 */ ssize = isonum_723(ipd.logical_block_size, xflag); if (1 < argc) printf("%s: ", filenamep); if (xflag) { printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize); } else { long long product = nsecs; if (divisor == 0) printf("%lld\n", product * ssize); else if (divisor == ssize) printf("%d\n", nsecs); else printf("%lld\n", (product * ssize) / divisor); } close(fd); }
static void hf_probe_volume_advanced_disc_detect (int fd) { size_t secsz = ISO_DEFAULT_BLOCK_SIZE; int readoff; struct iso_primary_descriptor desc; u_char *ptbl; int ptbl_size, ptbl_bsize; int ptbl_lbn; struct iso_path_table_entry *pte; int pte_len; int name_len; int off; readoff = ISO_VOLDESC_SEC * secsz; do { if (pread(fd, &desc, sizeof desc, readoff) != sizeof desc) { hfp_warning("volume descriptor read error"); return; } if (isonum_711(desc.type) == ISO_VD_END) return; readoff += secsz; } while (isonum_711(desc.type) != ISO_VD_PRIMARY); ptbl_size = isonum_733(desc.path_table_size); #if BYTE_ORDER == LITTLE_ENDIAN ptbl_lbn = isonum_731(desc.type_l_path_table); #else ptbl_lbn = isonum_732(desc.type_m_path_table); #endif ptbl_bsize = (ptbl_size + secsz - 1) / secsz * secsz; ptbl = g_malloc(ptbl_bsize); if (ptbl == NULL) { hfp_warning("path table allocation failure"); return; } readoff = ptbl_lbn * secsz; if (pread(fd, ptbl, ptbl_bsize, readoff) != ptbl_bsize) { g_free(ptbl); hfp_warning("path table read error"); } for (off = 0; off < ptbl_size; off += pte_len) { pte = (struct iso_path_table_entry *)(ptbl + off); name_len = *pte->name_len; pte_len = ISO_PATH_TABLE_ENTRY_SIZE + name_len + (name_len % 2); if (*(short *)pte->parent_no != 1) continue; if (name_len == 8 && strncmp(pte->name, "VIDEO_TS", 8) == 0) { libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_videodvd", TRUE, &hfp_error); break; } else if (name_len == 3 && strncmp(pte->name, "VCD", 8) == 0) { libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_vcd", TRUE, &hfp_error); break; } else if (name_len == 4 && strncmp(pte->name, "SVCD", 4) == 0) { libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_svcd", TRUE, &hfp_error); break; } } g_free(ptbl); }
/* * cdfs_read_dir - copy the current directory names into the input * buffer. Copy up to length bytes. '*length' is set to the number * of bytes actually copied. */ long cdfs_read_dir(struct cdfs_file *file, char *buffer, long *length) { void *bp; struct iso_directory_record *dp = &file->node; long status, lbn, file_off, file_size = isonum_733(dp->size); int dplen, buff_off, index, count, finished; int unsigned file_flags; static char *myname = "cdfs_read_dir"; CDFS_DEBUG_FCN_ENTRY(myname); if(*length > file_size) *length = file_size; /* * Skip the first 2 directory entries. */ if(file->position < 2) file->position = 2; status = CDFS_SUCCESS; buff_off = 0; file_off = 0; index = 0; finished = 0; while((buff_off < *length) && (file_off < file_size) && (status == CDFS_SUCCESS) && !finished) { /* * Get the next block from the directory. */ lbn = cdfs_bmap(file, file_off); bp = cdfs_getblk(file->cdfs, lbn, 1, (void **)&dp); if(bp == NULL) { *length = 0; CDFS_DEBUG_FCN_EXIT(myname, CDFS_EIO); return(CDFS_EIO); } /* * Get the maximum number of bytes to copy from the current block. */ count = file_size - file_off; if(count > file->cdfs->lbsize) count = file->cdfs->lbsize; if(count > *length) count = *length; /* * Get the 'name' of each directory entry in the current block. */ while(count > 0) { dplen = isonum_711(dp->length); /* * Unused byte positions after the last directory record are set to 0. */ if(dplen == 0) break; /* * The 'flags' field is in a different place for High Sierra CDROM's. */ if(file->cdfs->flags & CDFS_HIGH_SIERRA) file_flags = *((struct hs_directory_record *)dp)->flags; else file_flags = *dp->flags; /* * For directories, the file's position field is a directory entry index. * Don't copy directory names until the file's directory entry index * is reached. Also, only copy the last directory name of an multi-extent * file and don't copy associated file names. */ if((index >= file->position) && (dplen > 0)) { if(((file_flags & ISO_MULT_EXTENT) == 0) && ((file_flags & ISO_ASSOC_FILE) == 0)) { if(!cdfs_get_fname(file, dp, buffer + buff_off, *length - buff_off)) { finished = TRUE; break; } buff_off += strlen(buffer + buff_off); } /* * Count all directory entries in the file's position field. */ file->position++; } /* * Update for the next directory entry. */ count -= dplen; dp = (struct iso_directory_record *) ((char *)dp + dplen); index++; } cdfs_relblk(file->cdfs, bp); file_off += file->cdfs->lbsize; } *length = buff_off; CDFS_DEBUG_FCN_EXIT(myname, status); return(status); }
static int cd9660_open(const char *path, struct open_file *f) { struct file *fp = NULL; void *buf; struct iso_primary_descriptor *vd; size_t buf_size, read, dsize, off; daddr_t bno, boff; struct iso_directory_record rec; struct iso_directory_record *dp = NULL; int rc, first, use_rrip, lenskip; /* First find the volume descriptor */ buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE); vd = buf; for (bno = 16;; bno++) { twiddle(1); rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &read); if (rc) goto out; if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } rc = EINVAL; if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) goto out; if (isonum_711(vd->type) == ISO_VD_END) goto out; if (isonum_711(vd->type) == ISO_VD_PRIMARY) break; } if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) goto out; rec = *(struct iso_directory_record *) vd->root_directory_record; if (*path == '/') path++; /* eat leading '/' */ first = 1; use_rrip = 0; while (*path) { bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); dsize = isonum_733(rec.size); off = 0; boff = 0; while (off < dsize) { if ((off % ISO_DEFAULT_BLOCK_SIZE) == 0) { twiddle(1); rc = f->f_dev->dv_strategy (f->f_devdata, F_READ, cdb2devb(bno + boff), ISO_DEFAULT_BLOCK_SIZE, buf, &read); if (rc) goto out; if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } boff++; dp = (struct iso_directory_record *) buf; } if (isonum_711(dp->length) == 0) { /* skip to next block, if any */ off = boff * ISO_DEFAULT_BLOCK_SIZE; continue; } /* See if RRIP is in use. */ if (first) use_rrip = rrip_check(f, dp, &lenskip); if (dirmatch(f, path, dp, use_rrip, first ? 0 : lenskip)) { first = 0; break; } else first = 0; dp = (struct iso_directory_record *) ((char *) dp + isonum_711(dp->length)); /* If the new block has zero length, it is padding. */ if (isonum_711(dp->length) == 0) { /* Skip to next block, if any. */ off = boff * ISO_DEFAULT_BLOCK_SIZE; continue; } off += isonum_711(dp->length); } if (off >= dsize) { rc = ENOENT; goto out; } rec = *dp; while (*path && *path != '/') /* look for next component */ path++; if (*path) path++; /* skip '/' */ } /* allocate file system specific data structure */ fp = malloc(sizeof(struct file)); bzero(fp, sizeof(struct file)); f->f_fsdata = (void *)fp; if ((isonum_711(rec.flags) & 2) != 0) { fp->f_flags = F_ISDIR; } if (first) { fp->f_flags |= F_ROOTDIR; /* Check for Rock Ridge since we didn't in the loop above. */ bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); twiddle(1); rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &read); if (rc) goto out; if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } dp = (struct iso_directory_record *)buf; use_rrip = rrip_check(f, dp, &lenskip); } if (use_rrip) { fp->f_flags |= F_RR; fp->f_susp_skip = lenskip; } fp->f_off = 0; fp->f_bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); fp->f_size = isonum_733(rec.size); free(buf); return 0; out: if (fp) free(fp); free(buf); return rc; }
static int cd9660_readdir(struct open_file *f, struct dirent *d) { struct file *fp = (struct file *)f->f_fsdata; struct iso_directory_record *ep; size_t buf_size, reclen, namelen; int error = 0; int lenskip; char *buf, *name; again: if (fp->f_off >= fp->f_size) return (ENOENT); error = buf_read_file(f, &buf, &buf_size); if (error) return (error); ep = (struct iso_directory_record *)buf; if (isonum_711(ep->length) == 0) { daddr_t blkno; /* skip to next block, if any */ blkno = fp->f_off / ISO_DEFAULT_BLOCK_SIZE; fp->f_off = (blkno + 1) * ISO_DEFAULT_BLOCK_SIZE; goto again; } if (fp->f_flags & F_RR) { if (fp->f_flags & F_ROOTDIR && fp->f_off == 0) lenskip = 0; else lenskip = fp->f_susp_skip; name = rrip_lookup_name(f, ep, lenskip, &namelen); } else name = NULL; if (name == NULL) { namelen = isonum_711(ep->name_len); name = ep->name; if (namelen == 1) { if (ep->name[0] == 0) name = "."; else if (ep->name[0] == 1) { namelen = 2; name = ".."; } } } reclen = sizeof(struct dirent) - (MAXNAMLEN+1) + namelen + 1; reclen = (reclen + 3) & ~3; d->d_fileno = isonum_733(ep->extent); d->d_reclen = reclen; if (isonum_711(ep->flags) & 2) d->d_type = DT_DIR; else d->d_type = DT_REG; d->d_namlen = namelen; bcopy(name, d->d_name, d->d_namlen); d->d_name[d->d_namlen] = 0; fp->f_off += isonum_711(ep->length); return (0); }
static int cd9660_findfile(int disk, const char *path, int *startp, int *lenp) { void *buf; struct iso_primary_descriptor *vd; size_t buf_size, read, dsize, off; daddr_t bno, boff; struct iso_directory_record rec; struct iso_directory_record *dp = 0; int rc = 0; /* First find the volume descriptor */ buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE); vd = buf; for (bno = 16;; bno++) { read = pread(disk, buf, ISO_DEFAULT_BLOCK_SIZE, cdb2off(bno)); if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } rc = EINVAL; if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) goto out; if (isonum_711(vd->type) == ISO_VD_END) goto out; if (isonum_711(vd->type) == ISO_VD_PRIMARY) break; } if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) { rc = EINVAL; goto out; } rec = *(struct iso_directory_record *) vd->root_directory_record; if (*path == '/') path++; /* eat leading '/' */ while (*path) { bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); dsize = isonum_733(rec.size); off = 0; boff = 0; while (off < dsize) { if ((off % ISO_DEFAULT_BLOCK_SIZE) == 0) { read = pread(disk, buf, ISO_DEFAULT_BLOCK_SIZE, cdb2off(bno + boff)); if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } boff++; dp = (struct iso_directory_record *) buf; } if (isonum_711(dp->length) == 0) { /* skip to next block, if any */ off = boff * ISO_DEFAULT_BLOCK_SIZE; continue; } if (dirmatch(path, dp)) break; dp = (struct iso_directory_record *) ((char *) dp + isonum_711(dp->length)); off += isonum_711(dp->length); } if (off == dsize) { rc = ENOENT; goto out; } rec = *dp; while (*path && *path != '/') /* look for next component */ path++; if (*path) path++; /* skip '/' */ } *startp = cdb2off(isonum_733(rec.extent) + isonum_711(rec.ext_attr_length)); *lenp = isonum_733(rec.size); rc = 0; out: free(buf); return rc; }
int find_rock_ridge_relocation(struct iso_directory_record * de, struct inode * inode) { int flag; int len; int retval; unsigned char * chr; CONTINUE_DECLS; flag = 0; /* If this is a '..' then we are looking for the parent, otherwise we are looking for the child */ if (de->name[0]==1 && de->name_len[0]==1) flag = 1; /* Return value if we do not find appropriate record. */ retval = isonum_733 (de->extent); if (!inode->i_sb->u.isofs_sb.s_rock) return retval; SETUP_ROCK_RIDGE(de, chr, len); repeat: { int rrflag, sig; struct rock_ridge * rr; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; switch(sig){ case SIG('R','R'): rrflag = rr->u.RR.flags[0]; if (flag && !(rrflag & RR_PL)) goto out; if (!flag && !(rrflag & RR_CL)) goto out; break; case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','L'): if (flag == 0) { retval = isonum_733(rr->u.CL.location); goto out; } break; case SIG('P','L'): if (flag != 0) { retval = isonum_733(rr->u.PL.location); goto out; } break; case SIG('C','E'): CHECK_CE; /* This tells is if there is a continuation record */ break; default: break; } } } MAYBE_CONTINUE(repeat, inode); return retval; out: if(buffer) kfree(buffer); return retval; }
int parse_rock_ridge_inode_internal(struct iso_directory_record * de, struct inode * inode,int regard_xa){ int len; unsigned char * chr; int symlink_len = 0; CONTINUE_DECLS; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; SETUP_ROCK_RIDGE(de, chr, len); if (regard_xa) { chr+=14; len-=14; if (len<0) len=0; }; repeat: { int cnt, sig; struct inode * reloc; struct rock_ridge * rr; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; switch(sig){ #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ case SIG('R','R'): if((rr->u.RR.flags[0] & (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; break; #endif case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): CHECK_CE; break; case SIG('E','R'): inode->i_sb->u.isofs_sb.s_rock = 1; printk(KERN_DEBUG "ISO 9660 Extensions: "); { int p; for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]); } printk("\n"); break; case SIG('P','X'): inode->i_mode = isonum_733(rr->u.PX.mode); inode->i_nlink = isonum_733(rr->u.PX.n_links); inode->i_uid = isonum_733(rr->u.PX.uid); inode->i_gid = isonum_733(rr->u.PX.gid); break; case SIG('P','N'): { int high, low; high = isonum_733(rr->u.PN.dev_high); low = isonum_733(rr->u.PN.dev_low); /* * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4, * then the high field is unused, and the device number is completely * stored in the low field. Some writers may ignore this subtlety, * and as a result we test to see if the entire device number is * stored in the low field, and use that. */ if((low & ~0xff) && high == 0) { inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { inode->i_rdev = MKDEV(high, low); } } break; case SIG('T','F'): /* Some RRIP writers incorrectly place ctime in the TF_CREATE field. Try to handle this correctly for either case. */ cnt = 0; /* Rock ridge never appears on a High Sierra disk */ if(rr->u.TF.flags & TF_CREATE) inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0); if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0); if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0); if(rr->u.TF.flags & TF_ATTRIBUTES) inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0); break; case SIG('S','L'): {int slen; struct SL_component * slp; struct SL_component * oldslp; slen = rr->len - 5; slp = &rr->u.SL.link; inode->i_size = symlink_len; while (slen > 1){ rootflag = 0; switch(slp->flags &~1){ case 0: inode->i_size += slp->len; break; case 2: inode->i_size += 1; break; case 4: inode->i_size += 2; break; case 8: rootflag = 1; inode->i_size += 1; break; default: printk("Symlink component flag not implemented\n"); } slen -= slp->len + 2; oldslp = slp; slp = (struct SL_component *) (((char *) slp) + slp->len + 2); if(slen < 2) { if( ((rr->u.SL.flags & 1) != 0) && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; break; } /* * If this component record isn't continued, then append a '/'. */ if (!rootflag && (oldslp->flags & 1) == 0) inode->i_size += 1; } } symlink_len = inode->i_size; break; case SIG('R','E'): printk(KERN_WARNING "Attempt to read inode for relocated directory\n"); goto out; case SIG('C','L'): inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location); reloc = iget(inode->i_sb, (inode->u.isofs_i.i_first_extent << inode -> i_sb -> u.isofs_sb.s_log_zone_size)); if (!reloc) goto out; inode->i_mode = reloc->i_mode; inode->i_nlink = reloc->i_nlink; inode->i_uid = reloc->i_uid; inode->i_gid = reloc->i_gid; inode->i_rdev = reloc->i_rdev; inode->i_size = reloc->i_size; inode->i_blocks = reloc->i_blocks; inode->i_atime = reloc->i_atime; inode->i_ctime = reloc->i_ctime; inode->i_mtime = reloc->i_mtime; iput(reloc); break; #ifdef CONFIG_ZISOFS case SIG('Z','F'): if ( !inode->i_sb->u.isofs_sb.s_nocompress ) { int algo; algo = isonum_721(rr->u.ZF.algorithm); if ( algo == SIG('p','z') ) { int block_shift = isonum_711(&rr->u.ZF.parms[1]); if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) { printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift); } else { /* Note: we don't change i_blocks here */ inode->u.isofs_i.i_file_format = isofs_file_compressed; /* Parameters to compression algorithm (header size, block size) */ inode->u.isofs_i.i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]); inode->u.isofs_i.i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]); inode->i_size = isonum_733(rr->u.ZF.real_size); } } else { printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n", rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]); } } break; #endif default: break; } }
/* * return length of name field; 0: not found, -1: to be ignored */ int get_rock_ridge_filename(struct iso_directory_record *de, char *retname, struct inode *inode) { struct rock_state rs; struct rock_ridge *rr; int sig; int retnamlen = 0; int truncate = 0; int ret = 0; if (!ISOFS_SB(inode->i_sb)->s_rock) return 0; *retname = 0; init_rock_state(&rs, inode); setup_rock_ridge(de, inode, &rs); repeat: while (rs.len > 2) { /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *)rs.chr; /* * Ignore rock ridge info if rr->len is out of range, but * don't return -EIO because that would make the file * invisible. */ if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(rs.chr); if (rock_check_overflow(&rs, sig)) goto eio; rs.chr += rr->len; rs.len -= rr->len; /* * As above, just ignore the rock ridge info if rr->len * is bogus. */ if (rs.len < 0) goto out; /* Something got screwed up here */ switch (sig) { case SIG('R', 'R'): if ((rr->u.RR.flags[0] & RR_NM) == 0) goto out; break; case SIG('S', 'P'): if (check_sp(rr, inode)) goto out; break; case SIG('C', 'E'): rs.cont_extent = isonum_733(rr->u.CE.extent); rs.cont_offset = isonum_733(rr->u.CE.offset); rs.cont_size = isonum_733(rr->u.CE.size); break; case SIG('N', 'M'): if (truncate) break; if (rr->len < 5) break; /* * If the flags are 2 or 4, this indicates '.' or '..'. * We don't want to do anything with this, because it * screws up the code that calls us. We don't really * care anyways, since we can just use the non-RR * name. */ if (rr->u.NM.flags & 6) break; if (rr->u.NM.flags & ~1) { printk("Unsupported NM flag settings (%d)\n", rr->u.NM.flags); break; } if ((strlen(retname) + rr->len - 5) >= 254) { truncate = 1; break; } strncat(retname, rr->u.NM.name, rr->len - 5); retnamlen += rr->len - 5; break; case SIG('R', 'E'): kfree(rs.buffer); return -1; default: break; } } ret = rock_continue(&rs); if (ret == 0) goto repeat; if (ret == 1) return retnamlen; /* If 0, this file did not have a NM field */ out: kfree(rs.buffer); return ret; eio: ret = -EIO; goto out; }
static int cd9660_rrip_loop(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table) { RRIP_TABLE *ptable; ISO_SUSP_HEADER *phead; ISO_SUSP_HEADER *pend; struct buf *bp = NULL; char *pwhead; u_short c; int result; /* * Note: If name length is odd, * it will be padding 1 byte after the name */ pwhead = isodir->name + isonum_711(isodir->name_len); if (!(isonum_711(isodir->name_len)&1)) pwhead++; isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL, ana->imp->im_flags, ana->imp->im_d2l); /* If it's not the '.' entry of the root dir obey SP field */ if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) pwhead += ana->imp->rr_skip; else pwhead += ana->imp->rr_skip0; phead = (ISO_SUSP_HEADER *)pwhead; pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); result = 0; while (1) { ana->iso_ce_len = 0; /* * Note: "pend" should be more than one SUSP header */ while (pend >= phead + 1) { if (isonum_711(phead->version) == 1) { for (ptable = table; ptable->func; ptable++) { if (*phead->type == *ptable->type && phead->type[1] == ptable->type[1]) { result |= ptable->func(phead,ana); break; } } if (!ana->fields) break; } if (result&ISO_SUSP_STOP) { result &= ~ISO_SUSP_STOP; break; } /* plausibility check */ if (isonum_711(phead->length) < sizeof(*phead)) break; /* * move to next SUSP * Hopefully this works with newer versions, too */ phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); } if (ana->fields && ana->iso_ce_len) { if (ana->iso_ce_blk >= ana->imp->volume_space_size || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size || bread(ana->imp->im_devvp, lblktooff(ana->imp, ana->iso_ce_blk), ana->imp->logical_block_size, &bp)) /* what to do now? */ break; phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); } else break; } if (bp) brelse(bp); /* * If we don't find the Basic SUSP stuffs, just set default value * (attribute/time stamp) */ for (ptable = table; ptable->func2; ptable++) if (!(ptable->result&result)) ptable->func2(isodir,ana); return result; }
int cd9660_open(const char *path, struct open_file *f) { struct file *fp = 0; void *buf; struct iso_primary_descriptor *vd; size_t buf_size, nread, psize, dsize; daddr_t bno; int parent, ent; struct ptable_ent *pp; struct iso_directory_record *dp = 0; int rc; /* First find the volume descriptor */ buf_size = ISO_DEFAULT_BLOCK_SIZE; buf = alloc(buf_size); vd = buf; for (bno = 16;; bno++) { #if !defined(LIBSA_NO_TWIDDLE) twiddle(); #endif rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &nread); if (rc) goto out; if (nread != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } rc = EINVAL; if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) goto out; if (isonum_711(vd->type) == ISO_VD_END) goto out; if (isonum_711(vd->type) == ISO_VD_PRIMARY) break; } if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) goto out; /* Now get the path table and lookup the directory of the file */ bno = isonum_732(vd->type_m_path_table); psize = isonum_733(vd->path_table_size); if (psize > ISO_DEFAULT_BLOCK_SIZE) { dealloc(buf, ISO_DEFAULT_BLOCK_SIZE); buf = alloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE)); } #if !defined(LIBSA_NO_TWIDDLE) twiddle(); #endif rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), buf_size, buf, &nread); if (rc) goto out; if (nread != buf_size) { rc = EIO; goto out; } parent = 1; pp = (struct ptable_ent *)buf; ent = 1; bno = isonum_732(pp->block) + isonum_711(pp->extlen); rc = ENOENT; /* * Remove extra separators */ while (*path == '/') path++; while (*path) { if ((char *)pp >= (char *)buf + psize) break; if (isonum_722(pp->parent) != parent) break; if (!pnmatch(path, pp)) { pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp)); ent++; continue; } path += isonum_711(pp->namlen) + 1; parent = ent; bno = isonum_732(pp->block) + isonum_711(pp->extlen); while ((char *)pp < (char *)buf + psize) { if (isonum_722(pp->parent) == parent) break; pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp)); ent++; } } /* * Now bno has the start of the directory that supposedly * contains the file */ bno--; dsize = 1; /* Something stupid, but > 0 XXX */ for (psize = 0; psize < dsize;) { if (!(psize % ISO_DEFAULT_BLOCK_SIZE)) { bno++; #if !defined(LIBSA_NO_TWIDDLE) twiddle(); #endif rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &nread); if (rc) goto out; if (nread != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } dp = (struct iso_directory_record *)buf; } if (!isonum_711(dp->length)) { if ((void *)dp == buf) psize += ISO_DEFAULT_BLOCK_SIZE; else psize = roundup(psize, ISO_DEFAULT_BLOCK_SIZE); continue; } if (dsize == 1) dsize = isonum_733(dp->size); if (dirmatch(path, dp)) break; psize += isonum_711(dp->length); dp = (struct iso_directory_record *) ((char *)dp + isonum_711(dp->length)); } if (psize >= dsize) { rc = ENOENT; goto out; } /* allocate file system specific data structure */ fp = alloc(sizeof(struct file)); memset(fp, 0, sizeof(struct file)); f->f_fsdata = (void *)fp; fp->off = 0; fp->bno = isonum_733(dp->extent); fp->size = isonum_733(dp->size); dealloc(buf, buf_size); return 0; out: if (fp) dealloc(fp, sizeof(struct file)); dealloc(buf, buf_size); return rc; }
int parse_rock_ridge_inode(struct iso_directory_record * de, struct inode * inode){ int len; unsigned char * chr; int symlink_len = 0; CONTINUE_DECLS; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; SETUP_ROCK_RIDGE(de, chr, len); repeat: { int cnt, sig; struct inode * reloc; struct rock_ridge * rr; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = (chr[0] << 8) + chr[1]; chr += rr->len; len -= rr->len; switch(sig){ case SIG('R','R'): if((rr->u.RR.flags[0] & (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; break; case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): CHECK_CE; break; case SIG('E','R'): inode->i_sb->u.isofs_sb.s_rock = 1; printk(KERN_DEBUG"ISO9660 Extensions: "); { int p; for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]); }; printk("\n"); break; case SIG('P','X'): inode->i_mode = isonum_733(rr->u.PX.mode); inode->i_nlink = isonum_733(rr->u.PX.n_links); inode->i_uid = isonum_733(rr->u.PX.uid); inode->i_gid = isonum_733(rr->u.PX.gid); break; case SIG('P','N'): { int high, low; high = isonum_733(rr->u.PN.dev_high); low = isonum_733(rr->u.PN.dev_low); /* * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4, * then the high field is unused, and the device number is completely * stored in the low field. Some writers may ignore this subtlety, * and as a result we test to see if the entire device number is * stored in the low field, and use that. */ if((low & ~0xff) && high == 0) { inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { inode->i_rdev = MKDEV(high, low); } }; break; case SIG('T','F'): { struct stamp *times = (struct stamp *) &(rr->u.TF.__times); /* Some RRIP writers incorrectly place ctime in the TF_CREATE field. Try to handle this correctly for either case. */ cnt = 0; /* Rock ridge never appears on a High Sierra disk */ if(rr->u.TF.flags & TF_CREATE) inode->i_ctime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_ATTRIBUTES) inode->i_ctime = iso_date(times[cnt++].time, 0); break; } case SIG('S','L'): {int slen; struct SL_component * slp; struct SL_component * oldslp; slen = rr->len - 5; slp = (struct SL_component *)&rr->u.SL.__link; inode->i_size = symlink_len; while (slen > 1){ rootflag = 0; switch(slp->flags &~1){ case 0: inode->i_size += slp->len; break; case 2: inode->i_size += 1; break; case 4: inode->i_size += 2; break; case 8: rootflag = 1; inode->i_size += 1; break; default: printk("Symlink component flag not implemented\n"); }; slen -= slp->len + 2; oldslp = slp; slp = (struct SL_component *) (((char *) slp) + slp->len + 2); if(slen < 2) { if( ((rr->u.SL.flags & 1) != 0) && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; break; } /* * If this component record isn't continued, then append a '/'. */ if( (!rootflag) && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; } } symlink_len = inode->i_size; break; case SIG('R','E'): printk("Attempt to read inode for relocated directory\n"); goto out; case SIG('C','L'): #ifdef DEBUG printk("RR CL (%x)\n",inode->i_ino); #endif inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) << inode -> i_sb -> u.isofs_sb.s_log_zone_size; reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent); inode->i_mode = reloc->i_mode; inode->i_nlink = reloc->i_nlink; inode->i_uid = reloc->i_uid; inode->i_gid = reloc->i_gid; inode->i_rdev = reloc->i_rdev; inode->i_size = reloc->i_size; inode->i_atime = reloc->i_atime; inode->i_ctime = reloc->i_ctime; inode->i_mtime = reloc->i_mtime; iput(reloc); break; default: break; } };
static int parse_rock_ridge_inode_internal(struct iso_directory_record *de, struct inode *inode, int regard_xa) { int symlink_len = 0; int cnt, sig; struct inode *reloc; struct rock_ridge *rr; int rootflag; struct rock_state rs; int ret = 0; if (!ISOFS_SB(inode->i_sb)->s_rock) return 0; init_rock_state(&rs, inode); setup_rock_ridge(de, inode, &rs); if (regard_xa) { rs.chr += 14; rs.len -= 14; if (rs.len < 0) rs.len = 0; } repeat: while (rs.len > 2) { /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *)rs.chr; /* * Ignore rock ridge info if rr->len is out of range, but * don't return -EIO because that would make the file * invisible. */ if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(rs.chr); if (rock_check_overflow(&rs, sig)) goto eio; rs.chr += rr->len; rs.len -= rr->len; /* * As above, just ignore the rock ridge info if rr->len * is bogus. */ if (rs.len < 0) goto out; /* Something got screwed up here */ switch (sig) { #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ case SIG('R', 'R'): if ((rr->u.RR.flags[0] & (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; break; #endif case SIG('S', 'P'): if (check_sp(rr, inode)) goto out; break; case SIG('C', 'E'): rs.cont_extent = isonum_733(rr->u.CE.extent); rs.cont_offset = isonum_733(rr->u.CE.offset); rs.cont_size = isonum_733(rr->u.CE.size); break; case SIG('E', 'R'): ISOFS_SB(inode->i_sb)->s_rock = 1; printk(KERN_DEBUG "ISO 9660 Extensions: "); { int p; for (p = 0; p < rr->u.ER.len_id; p++) printk("%c", rr->u.ER.data[p]); } printk("\n"); break; case SIG('P', 'X'): inode->i_mode = isonum_733(rr->u.PX.mode); set_nlink(inode, isonum_733(rr->u.PX.n_links)); inode->i_uid = isonum_733(rr->u.PX.uid); inode->i_gid = isonum_733(rr->u.PX.gid); break; case SIG('P', 'N'): { int high, low; high = isonum_733(rr->u.PN.dev_high); low = isonum_733(rr->u.PN.dev_low); /* * The Rock Ridge standard specifies that if * sizeof(dev_t) <= 4, then the high field is * unused, and the device number is completely * stored in the low field. Some writers may * ignore this subtlety, * and as a result we test to see if the entire * device number is * stored in the low field, and use that. */ if ((low & ~0xff) && high == 0) { inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { inode->i_rdev = MKDEV(high, low); } } break; case SIG('T', 'F'): /* * Some RRIP writers incorrectly place ctime in the * TF_CREATE field. Try to handle this correctly for * either case. */ /* Rock ridge never appears on a High Sierra disk */ cnt = 0; if (rr->u.TF.flags & TF_CREATE) { inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_ctime.tv_nsec = 0; } if (rr->u.TF.flags & TF_MODIFY) { inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_mtime.tv_nsec = 0; } if (rr->u.TF.flags & TF_ACCESS) { inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_atime.tv_nsec = 0; } if (rr->u.TF.flags & TF_ATTRIBUTES) { inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_ctime.tv_nsec = 0; } break; case SIG('S', 'L'): { int slen; struct SL_component *slp; struct SL_component *oldslp; slen = rr->len - 5; slp = &rr->u.SL.link; inode->i_size = symlink_len; while (slen > 1) { rootflag = 0; switch (slp->flags & ~1) { case 0: inode->i_size += slp->len; break; case 2: inode->i_size += 1; break; case 4: inode->i_size += 2; break; case 8: rootflag = 1; inode->i_size += 1; break; default: printk("Symlink component flag " "not implemented\n"); } slen -= slp->len + 2; oldslp = slp; slp = (struct SL_component *) (((char *)slp) + slp->len + 2); if (slen < 2) { if (((rr->u.SL. flags & 1) != 0) && ((oldslp-> flags & 1) == 0)) inode->i_size += 1; break; } /* * If this component record isn't * continued, then append a '/'. */ if (!rootflag && (oldslp->flags & 1) == 0) inode->i_size += 1; } } symlink_len = inode->i_size; break; case SIG('R', 'E'): printk(KERN_WARNING "Attempt to read inode for " "relocated directory\n"); goto out; case SIG('C', 'L'): ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location); reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0); if (IS_ERR(reloc)) { ret = PTR_ERR(reloc); goto out; } inode->i_mode = reloc->i_mode; set_nlink(inode, reloc->i_nlink); inode->i_uid = reloc->i_uid; inode->i_gid = reloc->i_gid; inode->i_rdev = reloc->i_rdev; inode->i_size = reloc->i_size; inode->i_blocks = reloc->i_blocks; inode->i_atime = reloc->i_atime; inode->i_ctime = reloc->i_ctime; inode->i_mtime = reloc->i_mtime; iput(reloc); break; #ifdef CONFIG_ZISOFS case SIG('Z', 'F'): { int algo; if (ISOFS_SB(inode->i_sb)->s_nocompress) break; algo = isonum_721(rr->u.ZF.algorithm); if (algo == SIG('p', 'z')) { int block_shift = isonum_711(&rr->u.ZF.parms[1]); if (block_shift > 17) { printk(KERN_WARNING "isofs: " "Can't handle ZF block " "size of 2^%d\n", block_shift); } else { /* * Note: we don't change * i_blocks here */ ISOFS_I(inode)->i_file_format = isofs_file_compressed; /* * Parameters to compression * algorithm (header size, * block size) */ ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]); ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]); inode->i_size = isonum_733(rr->u.ZF. real_size); } } else { printk(KERN_WARNING "isofs: Unknown ZF compression " "algorithm: %c%c\n", rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]); } break; } #endif default: break; }
int openrd(char *name) { char *cp; const char *fname; u_int32_t oldsession; int session, list_only; struct iso_directory_record *dirp; session = 0; fname = name; /* * We accept the following boot string: * * [@sessionstart] name */ for (cp = name; *cp; cp++) switch (*cp) { /* we don't support filenames with spaces */ case ' ': case '\t': break; case '@': if (session) { printf("Syntax error\n"); return -1; } session++; oldsession = sessionstart; sessionstart = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (session == 1) { sessionstart *= 10; sessionstart += *cp - '0'; } break; default: if (session == 1) { session++; fname = cp; } } if (session && devopen(sessionstart) == -1) { (void)devopen(oldsession); sessionstart = oldsession; } if (session == 1) /* XXX no filename, only session arg */ return -1; list_only = fname[0] == '?' && fname[1] == 0; DPRINTF(("Calling find(%s, %d):\n", fname, list_only)); dirp = find(fname, list_only); DPRINTF(("find() returned 0x%x\n", (int)dirp)); if (list_only) return -1; if (dirp == 0) return 1; startblk = isonum_733(dirp->extent); filesize = isonum_733(dirp->size); DPRINTF(("startblk = %d, filesize = %d\n", startblk, filesize)); curblk = 0; /* force a re-read, 0 is impossible file start */ seek(0); return 0; }