Beispiel #1
0
static int
rrip_check(struct open_file *f, struct iso_directory_record *dp, int *lenskip)
{
	ISO_SUSP_PRESENT *sp;
	ISO_RRIP_EXTREF *er;
	char *p;

	/* First, see if we can find a SP field. */
	p = dp->name + isonum_711(dp->name_len);
	if (p > (char *)dp + isonum_711(dp->length))
		return (0);
	sp = (ISO_SUSP_PRESENT *)p;
	if (bcmp(sp->h.type, SUSP_PRESENT, 2) != 0)
		return (0);
	if (isonum_711(sp->h.length) != sizeof(ISO_SUSP_PRESENT))
		return (0);
	if (sp->signature[0] != 0xbe || sp->signature[1] != 0xef)
		return (0);
	*lenskip = isonum_711(sp->len_skp);

	/*
	 * Now look for an ER field.  If RRIP is present, then there must
	 * be at least one of these.  It would be more pedantic to walk
	 * through the list of fields looking for a Rock Ridge ER field.
	 */
	er = (ISO_RRIP_EXTREF *)susp_lookup_record(f, SUSP_EXTREF, dp, 0);
	if (er == NULL)
		return (0);
	return (1);
}
Beispiel #2
0
static struct dentry *isofs_export_get_parent(struct dentry *child)
{
	unsigned long parent_block = 0;
	unsigned long parent_offset = 0;
	struct inode *child_inode = child->d_inode;
	struct iso_inode_info *e_child_inode = ISOFS_I(child_inode);
	struct iso_directory_record *de = NULL;
	struct buffer_head * bh = NULL;
	struct dentry *rv = NULL;

	
	if (!S_ISDIR(child_inode->i_mode)) {
		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
		       "child is not a directory!\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	if (e_child_inode->i_iget5_offset != 0) {
		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
		       "child directory not normalized!\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	parent_block = e_child_inode->i_iget5_block;

	
	bh = sb_bread(child_inode->i_sb, parent_block);
	if (bh == NULL) {
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	
	de = (struct iso_directory_record*)bh->b_data;

	
	parent_offset = (unsigned long)isonum_711(de->length);
	de = (struct iso_directory_record*)(bh->b_data + parent_offset);

	
	if ((isonum_711(de->name_len) != 1) || (de->name[0] != 1)) {
		printk(KERN_ERR "isofs: Unable to find the \"..\" "
		       "directory for NFS.\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	
	isofs_normalize_block_and_offset(de, &parent_block, &parent_offset);

	rv = d_obtain_alias(isofs_iget(child_inode->i_sb, parent_block,
				     parent_offset));
 out:
	if (bh)
		brelse(bh);
	return rv;
}
Beispiel #3
0
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;
}
Beispiel #4
0
/*
 * Extension reference
 */
static int
cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana)
{
	if (isonum_711(p->len_id) != 10
	    || bcmp((char *)p + 8,"RRIP_1991A",10)
	    || isonum_711(p->version) != 1)
		return 0;
	ana->fields &= ~ISO_SUSP_EXTREF;
	return ISO_SUSP_EXTREF;
}
Beispiel #5
0
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;
}
Beispiel #6
0
/*
 * Alternate name
 */
static int
cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana)
{
	char *inbuf;
	int wlen;
	int cont;

	inbuf = "..";
	wlen = 0;
	cont = 0;

	switch (*p->flags) {
	case ISO_SUSP_CFLAG_CURRENT:
		/* Inserting Current */
		wlen = 1;
		break;

	case ISO_SUSP_CFLAG_PARENT:
		/* Inserting Parent */
		wlen = 2;
		break;

	case ISO_SUSP_CFLAG_HOST:
		/* Inserting hostname i.e. "kurt.tools.de" */
		inbuf = hostname;
		wlen = strlen(hostname);
		break;

	case ISO_SUSP_CFLAG_CONTINUE:
		cont = 1;
		/* fall thru */
	case 0:
		/* Inserting component */
		wlen = isonum_711(p->h.length) - 5;
		inbuf = (char *)p + 5;
		break;

	default:
		kprintf("RRIP with incorrect NM flags?\n");
		wlen = ana->maxlen + 1;
		break;
	}

	if ((*ana->outlen += wlen) > ana->maxlen) {
		/* treat as no name field */
		ana->fields &= ~ISO_SUSP_ALTNAME;
		ana->outbuf -= *ana->outlen - wlen;
		*ana->outlen = 0;
		return 0;
	}

	bcopy(inbuf,ana->outbuf,wlen);
	ana->outbuf += wlen;

	if (!cont) {
		ana->fields &= ~ISO_SUSP_ALTNAME;
		return ISO_SUSP_ALTNAME;
	}
	return 0;
}
Beispiel #7
0
static char *
rrip_lookup_name(struct open_file *f, struct iso_directory_record *dp,
    int lenskip, size_t *len)
{
	ISO_RRIP_ALTNAME *p;

	if (len == NULL)
		return (NULL);

	p = (ISO_RRIP_ALTNAME *)susp_lookup_record(f, RRIP_NAME, dp, lenskip);
	if (p == NULL)
		return (NULL);
	switch (*p->flags) {
	case ISO_SUSP_CFLAG_CURRENT:
		*len = 1;
		return (".");
	case ISO_SUSP_CFLAG_PARENT:
		*len = 2;
		return ("..");
	case 0:
		*len = isonum_711(p->h.length) - 5;
		return ((char *)p + 5);
	default:
		/*
		 * We don't handle hostnames or continued names as they are
		 * too hard, so just bail and use the default name.
		 */
		return (NULL);
	}
}
Beispiel #8
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;
}
Beispiel #9
0
int
cd9660_rrip_getname(struct iso_directory_record *isodir, char *outbuf,
		    u_short *outlen, ino_t *inump, struct iso_mnt *imp)
{
	ISO_RRIP_ANALYZE analyze;
	RRIP_TABLE *tab;
	u_short c;

	analyze.outbuf = outbuf;
	analyze.outlen = outlen;
	analyze.maxlen = NAME_MAX;
	analyze.inump = inump;
	analyze.imp = imp;
	analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
	*outlen = 0;

        isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
                imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l);
	tab = rrip_table_getname;
	if (c == 0 || c == 1) {
		cd9660_rrip_defname(isodir,&analyze);

		analyze.fields &= ~ISO_SUSP_ALTNAME;
		tab++;
	}

	return cd9660_rrip_loop(isodir,&analyze,tab);
}
Beispiel #10
0
static int
dirmatch(const char *path, struct iso_directory_record *dp)
{
	char *cp;
	int i;

	/* This needs to be a regular file */
	if (dp->flags[0] & 6)
		return 0;

	cp = dp->name;
	for (i = isonum_711(dp->name_len); --i >= 0; path++, cp++) {
		if (!*path)
			break;
		if (toupper(*path) == *cp)
			continue;
		return 0;
	}
	if (*path)
		return 0;
	/*
	 * Allow stripping of trailing dots and the version number.
	 * Note that this will find the first instead of the last version
	 * of a file.
	 */
	if (i >= 0 && (*cp == ';' || *cp == '.')) {
		/* This is to prevent matching of numeric extensions */
		if (*cp == '.' && cp[1] != ';')
			return 0;
		while (--i >= 0)
			if (*++cp != ';' && (*cp < '0' || *cp > '9'))
				return 0;
	}
	return 1;
}
Beispiel #11
0
/*
 * cdfs_get_extnd_attrs - read the input file's extended attribute data.
 */
long	cdfs_get_extnd_attrs(struct cdfs_file *file,
	                     struct iso_extended_attributes *attrs)
{
	void	*bp, *data;
	long	status = CDFS_SUCCESS;
	int	lbn, length;
	static	char *myname = "cdfs_read_attrs";

	CDFS_DEBUG_FCN_ENTRY(myname);

	if((length = isonum_711(file->node.ext_attr_length)) == 0)
		status = CDFS_ENOENT;
	else {
		if(length > 1)
			cdfs_error(0, myname,
			           "multi-block extents not supported");
/*
 * Get the next block from the directory.
 */
		lbn = cdfs_bmap(file, -(length * file->cdfs->lbsize));

		if((bp = cdfs_getblk(file->cdfs, lbn, 1, &data)) == NULL) {
			status = CDFS_EIO;
		} else {
			bcopy(data, attrs, sizeof(*attrs));
		}
		cdfs_relblk(file->cdfs, bp);
	}

	CDFS_DEBUG_FCN_EXIT(myname, status);

	return(status);
}
Beispiel #12
0
/*
 * cdfs_get_dirname - extract a file name from a directory entry.
 */
static	int cdfs_get_fname(struct cdfs_file *file,
	                   struct iso_directory_record *dp,
	                   char *buffer, int buflen)
{
	char	*rripname;
	int	name_len;

	name_len = isonum_711(dp->name_len);
/*
 * Try for a RRIP alternate name.
 */
	rripname = NULL;
	if(file->cdfs->flags & CDFS_RRIP)
		cdfs_get_altname(dp, &rripname, &name_len);
/*
 * Room left in the current buffer?
 */
	if((name_len + 2) > buflen)
		return(FALSE);
/*
 * Copy the current entry's name.
 */
	if(rripname != NULL)
		strncat(buffer, rripname, name_len);
	else
		cdfs_fncvt(dp->name, buffer, name_len);

	buffer[name_len] = '\0';
	strcat(buffer, "\n");

	return(TRUE);
}
Beispiel #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);
}
Beispiel #14
0
/*
 * Flag indicating
 */
static int
cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana)
{
	ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */
	/* special handling of RE field */
	if (ana->fields&ISO_SUSP_RELDIR)
		return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana);

	return ISO_SUSP_IDFLAG;
}
Beispiel #15
0
static void
cd9660_rrip_defname(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana)
{
        isofntrans(isodir->name,isonum_711(isodir->name_len),
                   ana->outbuf,ana->outlen,
                   1,isonum_711(isodir->flags)&4, ana->imp->joliet_level,
                   ana->imp->im_flags, ana->imp->im_d2l);
	switch (*ana->outbuf) {
	default:
		break;
	case 1:
		*ana->outlen = 2;
		/* FALL THROUGH */
	case 0:
		/* outlen is 1 already */
		strcpy(ana->outbuf,"..");
		break;
	}
}
Beispiel #16
0
/*
 * Extension reference
 */
static int
cd9660_rrip_extref(void *v, ISO_RRIP_ANALYZE *ana)
{
	ISO_RRIP_EXTREF *p = v;

	if (isonum_711(p->version) != 1)
		return 0;
	if (isonum_711(p->len_id) != 9
	    && isonum_711(p->len_id) != 10)
		return 0;
	if (isonum_711(p->len_id) == 9
	    && memcmp((char *)p + 8, "IEEE_1282", 9))
		return 0;
	if (isonum_711(p->len_id) == 10
	    && memcmp((char *)p + 8, "IEEE_P1282", 10)
	    && memcmp((char *)p + 8, "RRIP_1991A", 10))
		return 0;
	ana->fields &= ~ISO_SUSP_EXTREF;
	return ISO_SUSP_EXTREF;
}
Beispiel #17
0
static void
cd9660_rrip_defname(void *v, ISO_RRIP_ANALYZE *ana)
{
	struct iso_directory_record *isodir = v;

	isofntrans(isodir->name, isonum_711(isodir->name_len),
		   ana->outbuf, ana->outlen,
		   1, 0, isonum_711(isodir->flags) & 4,
		   ana->imp->im_joliet_level);
	switch (ana->outbuf[0]) {
	default:
		break;
	case 0:
		ana->outbuf[0] = '.';
		*ana->outlen = 1;
		break;
	case 1:
		strlcpy(ana->outbuf, "..", ana->maxlen - *ana->outlen);
		*ana->outlen = 2;
		break;
	}
}
Beispiel #18
0
static int
pnmatch(const char *path, struct ptable_ent *pp)
{
	char *cp;
	int i;

	cp = pp->name;
	for (i = isonum_711(pp->namlen); --i >= 0; path++, cp++) {
		if (toupper(*path) == *cp)
			continue;
		return 0;
	}
	if (*path != '/')
		return 0;
	return 1;
}
Beispiel #19
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");
}
Beispiel #20
0
static int
dirmatch(struct open_file *f, const char *path, struct iso_directory_record *dp,
    int use_rrip, int lenskip)
{
	size_t len;
	char *cp;
	int i, icase;

	if (use_rrip)
		cp = rrip_lookup_name(f, dp, lenskip, &len);
	else
		cp = NULL;
	if (cp == NULL) {
		len = isonum_711(dp->name_len);
		cp = dp->name;
		icase = 1;
	} else
		icase = 0;
	for (i = len; --i >= 0; path++, cp++) {
		if (!*path || *path == '/')
			break;
		if (*path == *cp)
			continue;
		if (!icase && toupper(*path) == *cp)
			continue;
		return 0;
	}
	if (*path && *path != '/')
		return 0;
	/*
	 * Allow stripping of trailing dots and the version number.
	 * Note that this will find the first instead of the last version
	 * of a file.
	 */
	if (i >= 0 && (*cp == ';' || *cp == '.')) {
		/* This is to prevent matching of numeric extensions */
		if (*cp == '.' && cp[1] != ';')
			return 0;
		while (--i >= 0)
			if (*++cp != ';' && (*cp < '0' || *cp > '9'))
				return 0;
	}
	return 1;
}
Beispiel #21
0
/*
 * Check for Rock Ridge Extension and return offset of its fields.
 * Note: We insist on the ER field.
 */
int
cd9660_rrip_offset(struct iso_directory_record *isodir, struct iso_mnt *imp)
{
	ISO_RRIP_OFFSET *p;
	ISO_RRIP_ANALYZE analyze;

	imp->rr_skip0 = 0;
	p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
	if (bcmp(p,"SP\7\1\276\357",6)) {
		/* Maybe, it's a CDROM XA disc? */
		imp->rr_skip0 = 15;
		p = (ISO_RRIP_OFFSET *)((char *)p + 15);
		if (bcmp(p,"SP\7\1\276\357",6))
			return -1;
	}

	analyze.imp = imp;
	analyze.fields = ISO_SUSP_EXTREF;
	if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
		return -1;

	return isonum_711(p->skip);
}
Beispiel #22
0
/*
 * cdfs_get_other_attrs - try to get extended and/or POSIX file
 * attributes.
 */
static	void cdfs_get_other_attrs(struct cdfs_file *file,
	                          struct iso_directory_record *dp)
{
	long	status;

	file->flags &= ~CDFS_ALL_ATTRS;
/*
 * Try to get extended attributes.
 */
	if(isonum_711(file->node.ext_attr_length) > 0) {
		status = cdfs_get_extnd_attrs(file, &file->extnd_attrs);
		if(status == CDFS_SUCCESS)
			file->flags |= CDFS_EXTND_ATTRS;
	}
/*
 * Try to get POSIX attributes.
 */
	if(file->cdfs->flags & CDFS_RRIP) {
		status = cdfs_get_posix_attrs(dp, &file->posix_attrs);
		if(status == CDFS_SUCCESS)
			file->flags |= CDFS_POSIX_ATTRS;
	}
}
Beispiel #23
0
void KIso::addBoot(struct el_torito_boot_descriptor* bootdesc)
{
    KISOFUNC;

    int i;
    long long size;
    boot_head boot;
    boot_entry *be;
    QString path;
    KIsoFile *entry;

    path = "Catalog";
    entry = new KIsoFile(this, path, dirent->permissions() & ~S_IFDIR,
                         dirent->date(), dirent->adate(), dirent->cdate(),
                         dirent->user(), dirent->group(), QString(),
                         (long long)isonum_731(bootdesc->boot_catalog) << (long long)11, (long long)2048);
    dirent->addEntry(entry);
    if (!ReadBootTable(&readf, isonum_731(bootdesc->boot_catalog), &boot, this)) {
        i = 1;
        be = boot.defentry;
        while (be) {
            size = BootImageSize(isonum_711(be->data.d_e.media),
                                 isonum_721(be->data.d_e.seccount));
            path = "Default Image";
            if (i > 1) path += " (" + QString::number(i) + ')';
            entry = new KIsoFile(this, path, dirent->permissions() & ~S_IFDIR,
                                 dirent->date(), dirent->adate(), dirent->cdate(),
                                 dirent->user(), dirent->group(), QString(),
                                 (long long)isonum_731(be->data.d_e.start) << (long long)11, size << (long long)9);
            dirent->addEntry(entry);
            be = be->next;
            i++;
        }

        FreeBootTable(&boot);
    }
}
Beispiel #24
0
void K3b::Iso9660::addBoot(struct el_torito_boot_descriptor* bootdesc)
{
    int i,size;
    boot_head boot;
    boot_entry *be;
    QString path;
    K3b::Iso9660File *entry;

    entry=new K3b::Iso9660File( this, "Catalog", "Catalog", dirent->permissions() & ~S_IFDIR,
                              dirent->date(), dirent->adate(), dirent->cdate(),
                              dirent->user(), dirent->group(), QString(),
                              isonum_731(bootdesc->boot_catalog), 2048 );
    dirent->addEntry(entry);
    if (!ReadBootTable(&K3b::Iso9660::read_callback,isonum_731(bootdesc->boot_catalog),&boot,this)) {
        i=1;
        be=boot.defentry;
        while (be) {
            size=BootImageSize(&K3b::Iso9660::read_callback,
                               isonum_711(((struct default_entry*) be->data)->media),
                               isonum_731(((struct default_entry*) be->data)->start),
                               isonum_721(((struct default_entry*) be->data)->seccount),
                               this);
            path="Default Image";
            if (i>1) path += " (" + QString::number(i) + ')';
            entry=new K3b::Iso9660File( this, path, path, dirent->permissions() & ~S_IFDIR,
                                      dirent->date(), dirent->adate(), dirent->cdate(),
                                      dirent->user(), dirent->group(), QString(),
                                      isonum_731(((struct default_entry*) be->data)->start), size<<9 );
            dirent->addEntry(entry);
            be=be->next;
            i++;
        }

        FreeBootTable(&boot);
    }
}
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;
		}
/* This function is surprisingly simple.  The trick is understanding
 * that "child" is always a directory. So, to find its parent, you
 * simply need to find its ".." entry, normalize its block and offset,
 * and return the underlying inode.  See the comments for
 * isofs_normalize_block_and_offset(). */
static struct dentry *isofs_export_get_parent(struct dentry *child)
{
	unsigned long parent_block = 0;
	unsigned long parent_offset = 0;
	struct inode *child_inode = child->d_inode;
	struct iso_inode_info *e_child_inode = ISOFS_I(child_inode);
	struct iso_directory_record *de = NULL;
	struct buffer_head * bh = NULL;
	struct dentry *rv = NULL;

	/* "child" must always be a directory. */
	if (!S_ISDIR(child_inode->i_mode)) {
		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
		       "child is not a directory!\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* It is an invariant that the directory offset is zero.  If
	 * it is not zero, it means the directory failed to be
	 * normalized for some reason. */
	if (e_child_inode->i_iget5_offset != 0) {
		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
		       "child directory not normalized!\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* The child inode has been normalized such that its
	 * i_iget5_block value points to the "." entry.  Fortunately,
	 * the ".." entry is located in the same block. */
	parent_block = e_child_inode->i_iget5_block;

	/* Get the block in question. */
	bh = sb_bread(child_inode->i_sb, parent_block);
	if (bh == NULL) {
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* This is the "." entry. */
	de = (struct iso_directory_record*)bh->b_data;

	/* The ".." entry is always the second entry. */
	parent_offset = (unsigned long)isonum_711(de->length);
	de = (struct iso_directory_record*)(bh->b_data + parent_offset);

	/* Verify it is in fact the ".." entry. */
	if ((isonum_711(de->name_len) != 1) || (de->name[0] != 1)) {
		printk(KERN_ERR "isofs: Unable to find the \"..\" "
		       "directory for NFS.\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* Normalize */
	isofs_normalize_block_and_offset(de, &parent_block, &parent_offset);

	rv = d_obtain_alias(isofs_iget(child_inode->i_sb, parent_block,
				     parent_offset));
 out:
	if (bh)
		brelse(bh);
	return rv;
}
Beispiel #27
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;
}
Beispiel #28
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;
}
Beispiel #29
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);
}
Beispiel #30
0
/*
 * Symbolic Links
 */
static int
cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana)
{
	ISO_RRIP_SLINK_COMPONENT *pcomp;
	ISO_RRIP_SLINK_COMPONENT *pcompe;
	int error, len, wlen, cont;
	char *outbuf, *inbuf, *freebuf;

	pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
	pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
	len = *ana->outlen;
	outbuf = ana->outbuf;
	cont = ana->cont;
	freebuf = NULL;

	/*
	 * Gathering a Symbolic name from each component with path
	 */
	for (;
	     pcomp < pcompe;
	     pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
						  + isonum_711(pcomp->clen))) {

		if (!cont) {
			if (len < ana->maxlen) {
				len++;
				*outbuf++ = '/';
			}
		}
		cont = 0;

		inbuf = "..";
		wlen = 0;

		switch (*pcomp->cflag) {

		case ISO_SUSP_CFLAG_CURRENT:
			/* Inserting Current */
			wlen = 1;
			break;

		case ISO_SUSP_CFLAG_PARENT:
			/* Inserting Parent */
			wlen = 2;
			break;

		case ISO_SUSP_CFLAG_ROOT:
			/* Inserting slash for ROOT */
			/* start over from beginning(?) */
			outbuf -= len;
			len = 0;
			break;

		case ISO_SUSP_CFLAG_VOLROOT:
			/* Inserting a mount point i.e. "/cdrom" */
			/* same as above */
			outbuf -= len;
			len = 0;
			error = cache_fullpath(NULL, &ana->imp->im_mountp->mnt_ncmountpt,
					       &inbuf, &freebuf, 0);
			if (error)
				goto bad;
			wlen = strlen(inbuf);
			break;

		case ISO_SUSP_CFLAG_HOST:
			/* Inserting hostname i.e. "kurt.tools.de" */
			inbuf = hostname;
			wlen = strlen(hostname);
			break;

		case ISO_SUSP_CFLAG_CONTINUE:
			cont = 1;
			/* fall thru */
		case 0:
			/* Inserting component */
			wlen = isonum_711(pcomp->clen);
			inbuf = pcomp->name;
			break;
		default:
			kprintf("RRIP with incorrect flags?");
			wlen = ana->maxlen + 1;
			break;
		}

		if (len + wlen > ana->maxlen)
			goto bad;

		bcopy(inbuf,outbuf,wlen);
		outbuf += wlen;
		len += wlen;

		if (freebuf != NULL) {
			kfree(freebuf, M_TEMP);
			freebuf = NULL;
		}
	}
	ana->outbuf = outbuf;
	*ana->outlen = len;
	ana->cont = cont;

	if (!isonum_711(p->flags)) {
		ana->fields &= ~ISO_SUSP_SLINK;
		return ISO_SUSP_SLINK;
	}
	return 0;

bad:
	if (freebuf != NULL)
		kfree(freebuf, M_TEMP);
	ana->cont = 1;
	ana->fields = 0;
	ana->outbuf -= *ana->outlen;
	*ana->outlen = 0;
	return 0;
}