17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  *  ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
37c478bd9Sstevel@tonic-gate  *  including Rock Ridge Extensions support
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  *  Copyright (C) 1998, 1999  Kousuke Takai  <tak@kmc.kyoto-u.ac.jp>
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  *  This program is free software; you can redistribute it and/or modify
87c478bd9Sstevel@tonic-gate  *  it under the terms of the GNU General Public License as published by
97c478bd9Sstevel@tonic-gate  *  the Free Software Foundation; either version 2 of the License, or
107c478bd9Sstevel@tonic-gate  *  (at your option) any later version.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  *  This program is distributed in the hope that it will be useful,
137c478bd9Sstevel@tonic-gate  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
147c478bd9Sstevel@tonic-gate  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157c478bd9Sstevel@tonic-gate  *  GNU General Public License for more details.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  *  You should have received a copy of the GNU General Public License
187c478bd9Sstevel@tonic-gate  *  along with this program; if not, write to the Free Software
197c478bd9Sstevel@tonic-gate  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  *  References:
237c478bd9Sstevel@tonic-gate  *	linux/fs/isofs/rock.[ch]
247c478bd9Sstevel@tonic-gate  *	mkisofs-1.11.1/diag/isoinfo.c
257c478bd9Sstevel@tonic-gate  *	mkisofs-1.11.1/iso9660.h
267c478bd9Sstevel@tonic-gate  *		(all are written by Eric Youngdale)
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  *  Modifications by:
297c478bd9Sstevel@tonic-gate  *	Leonid Lisovskiy   <lly@pisem.net>	2003
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #ifdef FSYS_ISO9660
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include "shared.h"
357c478bd9Sstevel@tonic-gate #include "filesys.h"
367c478bd9Sstevel@tonic-gate #include "iso9660.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /* iso9660 super-block data in memory */
397c478bd9Sstevel@tonic-gate struct iso_sb_info {
407c478bd9Sstevel@tonic-gate   unsigned long vol_sector;
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate };
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /* iso fs inode data in memory */
457c478bd9Sstevel@tonic-gate struct iso_inode_info {
467c478bd9Sstevel@tonic-gate   unsigned long file_start;
477c478bd9Sstevel@tonic-gate };
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #define ISO_SUPER	\
507c478bd9Sstevel@tonic-gate     ((struct iso_sb_info *)(FSYS_BUF))
517c478bd9Sstevel@tonic-gate #define INODE		\
527c478bd9Sstevel@tonic-gate     ((struct iso_inode_info *)(FSYS_BUF+sizeof(struct iso_sb_info)))
537c478bd9Sstevel@tonic-gate #define PRIMDESC        ((struct iso_primary_descriptor *)(FSYS_BUF + 2048))
547c478bd9Sstevel@tonic-gate #define DIRREC          ((struct iso_directory_record *)(FSYS_BUF + 4096))
557c478bd9Sstevel@tonic-gate #define RRCONT_BUF      ((unsigned char *)(FSYS_BUF + 6144))
567c478bd9Sstevel@tonic-gate #define NAME_BUF        ((unsigned char *)(FSYS_BUF + 8192))
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate static inline unsigned long
grub_log2(unsigned long word)607c478bd9Sstevel@tonic-gate grub_log2 (unsigned long word)
617c478bd9Sstevel@tonic-gate {
627c478bd9Sstevel@tonic-gate   asm volatile ("bsfl %1,%0"
637c478bd9Sstevel@tonic-gate 		:          "=r" (word)
647c478bd9Sstevel@tonic-gate 		:          "r" (word));
657c478bd9Sstevel@tonic-gate   return word;
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate #define log2 grub_log2
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static int
iso9660_devread(int sector,int byte_offset,int byte_len,char * buf)707c478bd9Sstevel@tonic-gate iso9660_devread (int sector, int byte_offset, int byte_len, char *buf)
717c478bd9Sstevel@tonic-gate {
722269adc8Sszhou   static int read_count = 0, threshold = 2;
737c478bd9Sstevel@tonic-gate   unsigned short sector_size_lg2 = log2(buf_geom.sector_size);
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate   /*
767c478bd9Sstevel@tonic-gate    * We have to use own devread() function since BIOS return wrong geometry
777c478bd9Sstevel@tonic-gate    */
787c478bd9Sstevel@tonic-gate   if (sector < 0)
797c478bd9Sstevel@tonic-gate     {
807c478bd9Sstevel@tonic-gate       errnum = ERR_OUTSIDE_PART;
817c478bd9Sstevel@tonic-gate       return 0;
827c478bd9Sstevel@tonic-gate     }
837c478bd9Sstevel@tonic-gate   if (byte_len <= 0)
847c478bd9Sstevel@tonic-gate     return 1;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate   sector += (byte_offset >> sector_size_lg2);
877c478bd9Sstevel@tonic-gate   byte_offset &= (buf_geom.sector_size - 1);
887c478bd9Sstevel@tonic-gate   asm volatile ("shl%L0 %1,%0"
897c478bd9Sstevel@tonic-gate 		: "=r"(sector)
907c478bd9Sstevel@tonic-gate 		: "Ic"((int8_t)(ISO_SECTOR_BITS - sector_size_lg2)),
917c478bd9Sstevel@tonic-gate 		"0"(sector));
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate #if !defined(STAGE1_5)
947c478bd9Sstevel@tonic-gate   if (disk_read_hook && debug)
957c478bd9Sstevel@tonic-gate     printf ("<%d, %d, %d>", sector, byte_offset, byte_len);
967c478bd9Sstevel@tonic-gate #endif /* !STAGE1_5 */
977c478bd9Sstevel@tonic-gate 
982269adc8Sszhou   read_count += (byte_len >> 9);
992269adc8Sszhou   if ((read_count >> 11) > threshold) {
1001fac5a60Ssetje 	noisy_printf(".");
1012269adc8Sszhou 	threshold += 2;	/* one dot every 2 MB */
1022269adc8Sszhou   }
1037c478bd9Sstevel@tonic-gate   return rawread(current_drive, part_start + sector, byte_offset, byte_len, buf);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate int
iso9660_mount(void)1077c478bd9Sstevel@tonic-gate iso9660_mount (void)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate   unsigned int sector;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate   /*
1127c478bd9Sstevel@tonic-gate    *  Because there is no defined slice type ID for ISO-9660 filesystem,
1137c478bd9Sstevel@tonic-gate    *  this test will pass only either (1) if entire disk is used, or
1147c478bd9Sstevel@tonic-gate    *  (2) if current partition is BSD style sub-partition whose ID is
1157c478bd9Sstevel@tonic-gate    *  ISO-9660.
1167c478bd9Sstevel@tonic-gate    */
1177c478bd9Sstevel@tonic-gate   if ((current_partition != 0xFFFFFF)
1187c478bd9Sstevel@tonic-gate       && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660))
1197c478bd9Sstevel@tonic-gate     return 0;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate   /*
1227c478bd9Sstevel@tonic-gate    *  Currently, only FIRST session of MultiSession disks are supported !!!
1237c478bd9Sstevel@tonic-gate    */
1247c478bd9Sstevel@tonic-gate   for (sector = 16 ; sector < 32 ; sector++)
1257c478bd9Sstevel@tonic-gate     {
1267c478bd9Sstevel@tonic-gate       if (!iso9660_devread(sector, 0, sizeof(*PRIMDESC), (char *)PRIMDESC))
1277c478bd9Sstevel@tonic-gate 	break;
1287c478bd9Sstevel@tonic-gate       /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */
1297c478bd9Sstevel@tonic-gate       if (PRIMDESC->type.l == ISO_VD_PRIMARY
1307c478bd9Sstevel@tonic-gate 	  && !memcmp(PRIMDESC->id, ISO_STANDARD_ID, sizeof(PRIMDESC->id)))
1317c478bd9Sstevel@tonic-gate 	{
1327c478bd9Sstevel@tonic-gate 	  ISO_SUPER->vol_sector = sector;
1337c478bd9Sstevel@tonic-gate 	  INODE->file_start = 0;
1347c478bd9Sstevel@tonic-gate 	  fsmax = PRIMDESC->volume_space_size.l;
1357c478bd9Sstevel@tonic-gate 	  return 1;
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate     }
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate   return 0;
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate int
iso9660_dir(char * dirname)1437c478bd9Sstevel@tonic-gate iso9660_dir (char *dirname)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate   struct iso_directory_record *idr;
1467c478bd9Sstevel@tonic-gate   RR_ptr_t rr_ptr;
1477c478bd9Sstevel@tonic-gate   struct rock_ridge *ce_ptr;
1487c478bd9Sstevel@tonic-gate   unsigned int pathlen;
1497c478bd9Sstevel@tonic-gate   int size;
1507c478bd9Sstevel@tonic-gate   unsigned int extent;
1517c478bd9Sstevel@tonic-gate   unsigned char file_type;
1527c478bd9Sstevel@tonic-gate   unsigned int rr_len;
1537c478bd9Sstevel@tonic-gate   unsigned char rr_flag;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate   idr = &PRIMDESC->root_directory_record;
1567c478bd9Sstevel@tonic-gate   INODE->file_start = 0;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate   do
1597c478bd9Sstevel@tonic-gate     {
1607c478bd9Sstevel@tonic-gate       while (*dirname == '/')	/* skip leading slashes */
1617c478bd9Sstevel@tonic-gate 	dirname++;
1627c478bd9Sstevel@tonic-gate       /* pathlen = strcspn(dirname, "/\n\t "); */
1637c478bd9Sstevel@tonic-gate       for (pathlen = 0 ;
1647c478bd9Sstevel@tonic-gate 	   dirname[pathlen]
1657c478bd9Sstevel@tonic-gate 	     && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ;
1667c478bd9Sstevel@tonic-gate 	   pathlen++)
1677c478bd9Sstevel@tonic-gate 	;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate       size = idr->size.l;
1707c478bd9Sstevel@tonic-gate       extent = idr->extent.l;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate       while (size > 0)
1737c478bd9Sstevel@tonic-gate 	{
1747c478bd9Sstevel@tonic-gate 	  if (!iso9660_devread(extent, 0, ISO_SECTOR_SIZE, (char *)DIRREC))
1757c478bd9Sstevel@tonic-gate 	    {
1767c478bd9Sstevel@tonic-gate 	      errnum = ERR_FSYS_CORRUPT;
1777c478bd9Sstevel@tonic-gate 	      return 0;
1787c478bd9Sstevel@tonic-gate 	    }
1797c478bd9Sstevel@tonic-gate 	  extent++;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	  idr = (struct iso_directory_record *)DIRREC;
1827c478bd9Sstevel@tonic-gate 	  for (; idr->length.l > 0;
1837c478bd9Sstevel@tonic-gate 	       idr = (struct iso_directory_record *)((char *)idr + idr->length.l) )
1847c478bd9Sstevel@tonic-gate 	    {
1857c478bd9Sstevel@tonic-gate 	      const char *name = idr->name;
1867c478bd9Sstevel@tonic-gate 	      unsigned int name_len = idr->name_len.l;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	      file_type = (idr->flags.l & 2) ? ISO_DIRECTORY : ISO_REGULAR;
1897c478bd9Sstevel@tonic-gate 	      if (name_len == 1)
1907c478bd9Sstevel@tonic-gate 		{
1917c478bd9Sstevel@tonic-gate 		  if ((name[0] == 0) ||	/* self */
1927c478bd9Sstevel@tonic-gate 		      (name[0] == 1)) 	/* parent */
1937c478bd9Sstevel@tonic-gate 		    continue;
1947c478bd9Sstevel@tonic-gate 		}
1957c478bd9Sstevel@tonic-gate 	      if (name_len > 2 && CHECK2(name + name_len - 2, ';', '1'))
1967c478bd9Sstevel@tonic-gate 		{
1977c478bd9Sstevel@tonic-gate 		  name_len -= 2;	/* truncate trailing file version */
1987c478bd9Sstevel@tonic-gate 		  if (name_len > 1 && name[name_len - 1] == '.')
1997c478bd9Sstevel@tonic-gate 		    name_len--;		/* truncate trailing dot */
2007c478bd9Sstevel@tonic-gate 		}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	      /*
2037c478bd9Sstevel@tonic-gate 	       *  Parse Rock-Ridge extension
2047c478bd9Sstevel@tonic-gate 	       */
2057c478bd9Sstevel@tonic-gate 	      rr_len = (idr->length.l - idr->name_len.l
2067c478bd9Sstevel@tonic-gate 			- sizeof(struct iso_directory_record)
2077c478bd9Sstevel@tonic-gate 			+ sizeof(idr->name));
2087c478bd9Sstevel@tonic-gate 	      rr_ptr.ptr = ((unsigned char *)idr + idr->name_len.l
2097c478bd9Sstevel@tonic-gate 			    + sizeof(struct iso_directory_record)
2107c478bd9Sstevel@tonic-gate 			    - sizeof(idr->name));
2117c478bd9Sstevel@tonic-gate 	      if (rr_ptr.i & 1)
2127c478bd9Sstevel@tonic-gate 		rr_ptr.i++, rr_len--;
2137c478bd9Sstevel@tonic-gate 	      ce_ptr = NULL;
2147c478bd9Sstevel@tonic-gate 	      rr_flag = RR_FLAG_NM | RR_FLAG_PX /*| RR_FLAG_SL*/;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	      while (rr_len >= 4)
2177c478bd9Sstevel@tonic-gate 		{
2187c478bd9Sstevel@tonic-gate 		  if (rr_ptr.rr->version != 1)
2197c478bd9Sstevel@tonic-gate 		    {
2207c478bd9Sstevel@tonic-gate #ifndef STAGE1_5
2217c478bd9Sstevel@tonic-gate 		      if (debug)
2227c478bd9Sstevel@tonic-gate 			printf(
2237c478bd9Sstevel@tonic-gate 			       "Non-supported version (%d) RockRidge chunk "
2247c478bd9Sstevel@tonic-gate 			       "`%c%c'\n", rr_ptr.rr->version,
2257c478bd9Sstevel@tonic-gate 			       rr_ptr.rr->signature & 0xFF,
2267c478bd9Sstevel@tonic-gate 			       rr_ptr.rr->signature >> 8);
2277c478bd9Sstevel@tonic-gate #endif
2287c478bd9Sstevel@tonic-gate 		    }
2297c478bd9Sstevel@tonic-gate 		  else
2307c478bd9Sstevel@tonic-gate 		    {
2317c478bd9Sstevel@tonic-gate 		      switch (rr_ptr.rr->signature)
2327c478bd9Sstevel@tonic-gate 			{
2337c478bd9Sstevel@tonic-gate 			case RRMAGIC('R', 'R'):
2347c478bd9Sstevel@tonic-gate 			  if ( rr_ptr.rr->len >= (4+sizeof(struct RR)))
2357c478bd9Sstevel@tonic-gate 			    rr_flag &= rr_ptr.rr->u.rr.flags.l;
2367c478bd9Sstevel@tonic-gate 			  break;
2377c478bd9Sstevel@tonic-gate 			case RRMAGIC('N', 'M'):
2387c478bd9Sstevel@tonic-gate 			  name = rr_ptr.rr->u.nm.name;
2397c478bd9Sstevel@tonic-gate 			  name_len = rr_ptr.rr->len - (4+sizeof(struct NM));
2407c478bd9Sstevel@tonic-gate 			  rr_flag &= ~RR_FLAG_NM;
2417c478bd9Sstevel@tonic-gate 			  break;
2427c478bd9Sstevel@tonic-gate 			case RRMAGIC('P', 'X'):
2437c478bd9Sstevel@tonic-gate 			  if (rr_ptr.rr->len >= (4+sizeof(struct PX)))
2447c478bd9Sstevel@tonic-gate 			    {
2457c478bd9Sstevel@tonic-gate 			      file_type = ((rr_ptr.rr->u.px.mode.l & POSIX_S_IFMT)
2467c478bd9Sstevel@tonic-gate 					   == POSIX_S_IFREG
2477c478bd9Sstevel@tonic-gate 					   ? ISO_REGULAR
2487c478bd9Sstevel@tonic-gate 					   : ((rr_ptr.rr->u.px.mode.l & POSIX_S_IFMT)
2497c478bd9Sstevel@tonic-gate 					      == POSIX_S_IFDIR
2507c478bd9Sstevel@tonic-gate 					      ? ISO_DIRECTORY : ISO_OTHER));
2517c478bd9Sstevel@tonic-gate 			      rr_flag &= ~RR_FLAG_PX;
2527c478bd9Sstevel@tonic-gate 			    }
2537c478bd9Sstevel@tonic-gate 			  break;
2547c478bd9Sstevel@tonic-gate 			case RRMAGIC('C', 'E'):
2557c478bd9Sstevel@tonic-gate 			  if (rr_ptr.rr->len >= (4+sizeof(struct CE)))
2567c478bd9Sstevel@tonic-gate 			    ce_ptr = rr_ptr.rr;
2577c478bd9Sstevel@tonic-gate 			  break;
2587c478bd9Sstevel@tonic-gate #if 0		// RockRidge symlinks are not supported yet
2597c478bd9Sstevel@tonic-gate 			case RRMAGIC('S', 'L'):
2607c478bd9Sstevel@tonic-gate 			  {
2617c478bd9Sstevel@tonic-gate 			    int slen;
2627c478bd9Sstevel@tonic-gate 			    unsigned char rootflag, prevflag;
2637c478bd9Sstevel@tonic-gate 			    char *rpnt = NAME_BUF+1024;
2647c478bd9Sstevel@tonic-gate 			    struct SL_component *slp;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 			    slen = rr_ptr.rr->len - (4+1);
2677c478bd9Sstevel@tonic-gate 			    slp = &rr_ptr.rr->u.sl.link;
2687c478bd9Sstevel@tonic-gate 			    while (slen > 1)
2697c478bd9Sstevel@tonic-gate 			      {
2707c478bd9Sstevel@tonic-gate 				rootflag = 0;
2717c478bd9Sstevel@tonic-gate 				switch (slp->flags.l)
2727c478bd9Sstevel@tonic-gate 				  {
2737c478bd9Sstevel@tonic-gate 				  case 0:
2747c478bd9Sstevel@tonic-gate 				    memcpy(rpnt, slp->text, slp->len);
2757c478bd9Sstevel@tonic-gate 				    rpnt += slp->len;
2767c478bd9Sstevel@tonic-gate 				    break;
2777c478bd9Sstevel@tonic-gate 				  case 4:
2787c478bd9Sstevel@tonic-gate 				    *rpnt++ = '.';
2797c478bd9Sstevel@tonic-gate 				    /* fallthru */
2807c478bd9Sstevel@tonic-gate 				  case 2:
2817c478bd9Sstevel@tonic-gate 				    *rpnt++ = '.';
2827c478bd9Sstevel@tonic-gate 				    break;
2837c478bd9Sstevel@tonic-gate 				  case 8:
2847c478bd9Sstevel@tonic-gate 				    rootflag = 1;
2857c478bd9Sstevel@tonic-gate 				    *rpnt++ = '/';
2867c478bd9Sstevel@tonic-gate 				    break;
2877c478bd9Sstevel@tonic-gate 				  default:
2887c478bd9Sstevel@tonic-gate 				    printf("Symlink component flag not implemented (%d)\n",
2897c478bd9Sstevel@tonic-gate 					   slp->flags.l);
2907c478bd9Sstevel@tonic-gate 				    slen = 0;
2917c478bd9Sstevel@tonic-gate 				    break;
2927c478bd9Sstevel@tonic-gate 				  }
2937c478bd9Sstevel@tonic-gate 				slen -= slp->len + 2;
2947c478bd9Sstevel@tonic-gate 				prevflag = slp->flags.l;
2957c478bd9Sstevel@tonic-gate 				slp = (struct SL_component *) ((char *) slp + slp->len + 2);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 				if (slen < 2)
2987c478bd9Sstevel@tonic-gate 				  {
2997c478bd9Sstevel@tonic-gate 				    /*
3007c478bd9Sstevel@tonic-gate 				     * If there is another SL record, and this component
3017c478bd9Sstevel@tonic-gate 				     * record isn't continued, then add a slash.
3027c478bd9Sstevel@tonic-gate 				     */
3037c478bd9Sstevel@tonic-gate 				    if ((!rootflag) && (rr_ptr.rr->u.sl.flags.l & 1) && !(prevflag & 1))
3047c478bd9Sstevel@tonic-gate 				      *rpnt++='/';
3057c478bd9Sstevel@tonic-gate 				    break;
3067c478bd9Sstevel@tonic-gate 				  }
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 				/*
3097c478bd9Sstevel@tonic-gate 				 * If this component record isn't continued, then append a '/'.
3107c478bd9Sstevel@tonic-gate 				 */
3117c478bd9Sstevel@tonic-gate 				if (!rootflag && !(prevflag & 1))
3127c478bd9Sstevel@tonic-gate 				  *rpnt++ = '/';
3137c478bd9Sstevel@tonic-gate 			      }
3147c478bd9Sstevel@tonic-gate 			    *rpnt++ = '\0';
3157c478bd9Sstevel@tonic-gate 			    grub_putstr(NAME_BUF+1024);// debug print!
3167c478bd9Sstevel@tonic-gate 			  }
3177c478bd9Sstevel@tonic-gate 			  rr_flag &= ~RR_FLAG_SL;
3187c478bd9Sstevel@tonic-gate 			  break;
3197c478bd9Sstevel@tonic-gate #endif
3207c478bd9Sstevel@tonic-gate 			default:
3217c478bd9Sstevel@tonic-gate 			  break;
3227c478bd9Sstevel@tonic-gate 			}
3237c478bd9Sstevel@tonic-gate 		    }
3247c478bd9Sstevel@tonic-gate 		  if (!rr_flag)
3257c478bd9Sstevel@tonic-gate 		    /*
3267c478bd9Sstevel@tonic-gate 		     * There is no more extension we expects...
3277c478bd9Sstevel@tonic-gate 		     */
3287c478bd9Sstevel@tonic-gate 		    break;
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 		  rr_len -= rr_ptr.rr->len;
3317c478bd9Sstevel@tonic-gate 		  rr_ptr.ptr += rr_ptr.rr->len;
3327c478bd9Sstevel@tonic-gate 		  if (rr_len < 4 && ce_ptr != NULL)
3337c478bd9Sstevel@tonic-gate 		    {
3347c478bd9Sstevel@tonic-gate 		      /* preserve name before loading new extent. */
3357c478bd9Sstevel@tonic-gate 		      if( RRCONT_BUF <= (unsigned char *)name
3367c478bd9Sstevel@tonic-gate 			  && (unsigned char *)name < RRCONT_BUF + ISO_SECTOR_SIZE )
3377c478bd9Sstevel@tonic-gate 			{
3387c478bd9Sstevel@tonic-gate 			  memcpy(NAME_BUF, name, name_len);
3397c478bd9Sstevel@tonic-gate 			  name = NAME_BUF;
3407c478bd9Sstevel@tonic-gate 			}
3417c478bd9Sstevel@tonic-gate 		      rr_ptr.ptr = RRCONT_BUF + ce_ptr->u.ce.offset.l;
3427c478bd9Sstevel@tonic-gate 		      rr_len = ce_ptr->u.ce.size.l;
3437c478bd9Sstevel@tonic-gate 		      if (!iso9660_devread(ce_ptr->u.ce.extent.l, 0, ISO_SECTOR_SIZE, RRCONT_BUF))
3447c478bd9Sstevel@tonic-gate 			{
3457c478bd9Sstevel@tonic-gate 			  errnum = 0;	/* this is not fatal. */
3467c478bd9Sstevel@tonic-gate 			  break;
3477c478bd9Sstevel@tonic-gate 			}
3487c478bd9Sstevel@tonic-gate 		      ce_ptr = NULL;
3497c478bd9Sstevel@tonic-gate 		    }
3507c478bd9Sstevel@tonic-gate 		} /* rr_len >= 4 */
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	      filemax = MAXINT;
3537c478bd9Sstevel@tonic-gate 	      if (name_len >= pathlen
3547c478bd9Sstevel@tonic-gate 		  && !memcmp(name, dirname, pathlen))
3557c478bd9Sstevel@tonic-gate 		{
3567c478bd9Sstevel@tonic-gate 		  if (dirname[pathlen] == '/' || !print_possibilities)
3577c478bd9Sstevel@tonic-gate 		    {
3587c478bd9Sstevel@tonic-gate 		      /*
3597c478bd9Sstevel@tonic-gate 		       *  DIRNAME is directory component of pathname,
3607c478bd9Sstevel@tonic-gate 		       *  or we are to open a file.
3617c478bd9Sstevel@tonic-gate 		       */
3627c478bd9Sstevel@tonic-gate 		      if (pathlen == name_len)
3637c478bd9Sstevel@tonic-gate 			{
3647c478bd9Sstevel@tonic-gate 			  if (dirname[pathlen] == '/')
3657c478bd9Sstevel@tonic-gate 			    {
3667c478bd9Sstevel@tonic-gate 			      if (file_type != ISO_DIRECTORY)
3677c478bd9Sstevel@tonic-gate 				{
3687c478bd9Sstevel@tonic-gate 				  errnum = ERR_BAD_FILETYPE;
3697c478bd9Sstevel@tonic-gate 				  return 0;
3707c478bd9Sstevel@tonic-gate 				}
3717c478bd9Sstevel@tonic-gate 			      goto next_dir_level;
3727c478bd9Sstevel@tonic-gate 			    }
3737c478bd9Sstevel@tonic-gate 			  if (file_type != ISO_REGULAR)
3747c478bd9Sstevel@tonic-gate 			    {
3757c478bd9Sstevel@tonic-gate 			      errnum = ERR_BAD_FILETYPE;
3767c478bd9Sstevel@tonic-gate 			      return 0;
3777c478bd9Sstevel@tonic-gate 			    }
3787c478bd9Sstevel@tonic-gate 			  INODE->file_start = idr->extent.l;
3797c478bd9Sstevel@tonic-gate 			  filepos = 0;
3807c478bd9Sstevel@tonic-gate 			  filemax = idr->size.l;
3817c478bd9Sstevel@tonic-gate 			  return 1;
3827c478bd9Sstevel@tonic-gate 			}
3837c478bd9Sstevel@tonic-gate 		    }
3847c478bd9Sstevel@tonic-gate 		  else	/* Completion */
3857c478bd9Sstevel@tonic-gate 		    {
3867c478bd9Sstevel@tonic-gate #ifndef STAGE1_5
3877c478bd9Sstevel@tonic-gate 		      if (print_possibilities > 0)
3887c478bd9Sstevel@tonic-gate 			print_possibilities = -print_possibilities;
3897c478bd9Sstevel@tonic-gate 		      memcpy(NAME_BUF, name, name_len);
3907c478bd9Sstevel@tonic-gate 		      NAME_BUF[name_len] = '\0';
3917c478bd9Sstevel@tonic-gate 		      print_a_completion (NAME_BUF);
3927c478bd9Sstevel@tonic-gate #endif
3937c478bd9Sstevel@tonic-gate 		    }
3947c478bd9Sstevel@tonic-gate 		}
3957c478bd9Sstevel@tonic-gate 	    } /* for */
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	  size -= ISO_SECTOR_SIZE;
3987c478bd9Sstevel@tonic-gate 	} /* size>0 */
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate       if (dirname[pathlen] == '/' || print_possibilities >= 0)
4017c478bd9Sstevel@tonic-gate 	{
4027c478bd9Sstevel@tonic-gate 	  errnum = ERR_FILE_NOT_FOUND;
4037c478bd9Sstevel@tonic-gate 	  return 0;
4047c478bd9Sstevel@tonic-gate 	}
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate     next_dir_level:
4077c478bd9Sstevel@tonic-gate       dirname += pathlen;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate     } while (*dirname == '/');
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate   return 1;
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate int
iso9660_read(char * buf,int len)4157c478bd9Sstevel@tonic-gate iso9660_read (char *buf, int len)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate   int sector, blkoffset, size, ret;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate   if (INODE->file_start == 0)
4207c478bd9Sstevel@tonic-gate     return 0;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate   ret = 0;
4237c478bd9Sstevel@tonic-gate   blkoffset = filepos & (ISO_SECTOR_SIZE - 1);
4247c478bd9Sstevel@tonic-gate   sector = filepos >> ISO_SECTOR_BITS;
4257c478bd9Sstevel@tonic-gate   while (len > 0)
4267c478bd9Sstevel@tonic-gate     {
4277c478bd9Sstevel@tonic-gate       size = ISO_SECTOR_SIZE - blkoffset;
4287c478bd9Sstevel@tonic-gate       if (size > len)
4297c478bd9Sstevel@tonic-gate         size = len;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate       disk_read_func = disk_read_hook;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate       if (!iso9660_devread(INODE->file_start + sector, blkoffset, size, buf))
4347c478bd9Sstevel@tonic-gate 	return 0;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate       disk_read_func = NULL;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate       len -= size;
4397c478bd9Sstevel@tonic-gate       buf += size;
4407c478bd9Sstevel@tonic-gate       ret += size;
4417c478bd9Sstevel@tonic-gate       filepos += size;
4427c478bd9Sstevel@tonic-gate       sector++;
4437c478bd9Sstevel@tonic-gate       blkoffset = 0;
4447c478bd9Sstevel@tonic-gate     }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate   return ret;
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate #endif /* FSYS_ISO9660 */
450