Example #1
0
File: cdfs.c Project: HarryR/sanos
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;
}
Example #2
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;
   }
}
Example #3
0
/*
 * 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;
}
Example #4
0
File: cdfs.c Project: HarryR/sanos
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;
}
Example #5
0
/*
 * 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;
}
Example #6
0
/*
 * 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;
}
Example #7
0
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;
}
Example #8
0
/*
 * 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;
}
Example #9
0
/*
 * 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;
}
Example #10
0
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);
	}
}
Example #11
0
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;
}
Example #13
0
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);
}
Example #14
0
File: cdfs.c Project: HarryR/sanos
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;
}
Example #15
0
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);
}
Example #16
0
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;
}
Example #17
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);
}
Example #18
0
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);
}
Example #19
0
/*
 * 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);
}
Example #20
0
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;
}
Example #21
0
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);
}
Example #22
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;
}
Example #23
0
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;
}
Example #24
0
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;
      }
    }
Example #25
0
/*
 * 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;
}
Example #26
0
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;
}
Example #27
0
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;
}
Example #28
0
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;
      }
    };
Example #29
0
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;
		}
Example #30
0
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;
}