Subject: kern/689: netbsd's /boot won't recognise symbolic links when booting.
To: None <gnats-admin@NetBSD.ORG>
From: Darren Reed <darrenr@vitruvius.arbld.unimelb.EDU.AU>
List: netbsd-bugs
Date: 01/03/1995 06:35:04
>Number:         689
>Category:       kern
>Synopsis:       netbsd's /boot won't recognise symbolic links when booting.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jan  3 06:35:01 1995
>Originator:     Darren Reed
>Organization:
University of Melbourne
>Release:        NetBSD-current
>Environment:
Sun sparc IPC, NetBSD-current
System: NetBSD candella.arbld.unimelb.edu.au 1.0A NetBSD 1.0A (1.0A) #15: Sat Dec 31 16:35:44 EST 1994 darrenr@candella.arbld.unimelb.edu.au:/usr/src/sys/arch/sparc/compile/1.0A sparc


>Description:
	NetBSD's /boot program doesn't follow symbolic links when it
tries to load the kernel.

>How-To-Repeat:
	make a symbolic link to a kernel in the root directory and try
to boot using the symbolic link name.

>Fix:
	Using the patch below, which I have tested and observed working,
I was able to boot kernels where the boot-file parameter was a symbolic
link.  To aid in the boot procedure problem solving, it prints out each
step of the symbolic link as it walks it.  Unfortunately, it has to
compete with twiddle() and gets a messed up display.

*** sys/lib/libsa/ufs.c.orig	Tue Jan  3 23:12:28 1995
--- sys/lib/libsa/ufs.c	Tue Jan  3 22:59:57 1995
***************
*** 379,390 ****
  	ino_t inumber, parent_inumber;
  	struct file *fp;
  	struct fs *fs;
! 	int rc;
  	u_int buf_size;
- #if 0
- 	int nlinks = 0;
  	char namebuf[MAXPATHLEN+1];
! #endif
  
  	/* allocate file system specific data structure */
  	fp = alloc(sizeof(struct file));
--- 379,388 ----
  	ino_t inumber, parent_inumber;
  	struct file *fp;
  	struct fs *fs;
! 	int rc, nlinks = 0;
  	u_int buf_size;
  	char namebuf[MAXPATHLEN+1];
! 	char *buf = NULL;
  
  	/* allocate file system specific data structure */
  	fp = alloc(sizeof(struct file));
***************
*** 479,523 ****
  		if ((rc = read_inode(inumber, f)) != 0)
  			goto out;
  
- #if 0
  		/*
  		 * Check for symbolic link.
  		 */
! 		if ((fp->i_mode & IFMT) == IFLNK) {
! 			int link_len = fp->f_di.di_size;
! 			int len;
  
! 			len = strlen(cp) + 1;
  
  			if (fp->f_di.di_size >= MAXPATHLEN - 1 ||
! 			    ++nlinks > MAXSYMLINKS) {
  				rc = ENOENT;
  				goto out;
  			}
  
! 			strcpy(&namebuf[link_len], cp);
! 
! 			if ((fp->i_flags & IC_FASTLINK) != 0) {
! 				bcopy(fp->i_symlink, namebuf, (unsigned) link_len);
  			} else {
  				/*
  				 * Read file for symbolic link
  				 */
! 				char *buf;
! 				u_int buf_size;
! 				daddr_t	disk_block;
! 				register struct fs *fs = fp->f_fs;
! 
! 				(void) block_map(f, (daddr_t)0, &disk_block);
! 				rc = device_read(&fp->f_dev,
! 						 fsbtodb(fs, disk_block),
! 						 blksize(fs, fp, 0),
! 						 &buf, &buf_size);
  				if (rc)
  					goto out;
  
  				bcopy((char *)buf, namebuf, (unsigned)link_len);
- 				free(buf, buf_size);
  			}
  
  			/*
--- 477,523 ----
  		if ((rc = read_inode(inumber, f)) != 0)
  			goto out;
  
  		/*
  		 * Check for symbolic link.
  		 */
! 		strcpy(namebuf, ncp);
! 		namebuf[strlen(namebuf)] = '\0';
! 		printf(" %s  ", namebuf);
  
! 		if ((fp->f_di.di_mode & IFMT) == IFLNK) {
! 			int link_len = fp->f_di.di_size;
  
  			if (fp->f_di.di_size >= MAXPATHLEN - 1 ||
! 			     nlinks >= MAXSYMLINKS) {
  				rc = ENOENT;
  				goto out;
  			}
  
! 			if (link_len < fs->fs_maxsymlinklen) {
! 				/*
! 				 * Symbolic link data is in the inode.
! 				 */
! 				bcopy(fp->f_di.di_shortlink, namebuf, (unsigned) link_len);
  			} else {
  				/*
  				 * Read file for symbolic link
  				 */
! 				u_int buf_size = fs->fs_bsize;
! 				daddr_t diskblock;
! 
! 				if (!buf)
! 					buf = alloc(buf_size);
! 				rc = block_map(f, 0, &diskblock);
! 				if (rc)
! 					goto out;
! 
! 				rc = (f->f_dev->dv_strategy)(f->f_devdata,
! 					F_READ, fsbtodb(fs, diskblock),
! 					fs->fs_bsize, buf, &buf_size);
  				if (rc)
  					goto out;
  
  				bcopy((char *)buf, namebuf, (unsigned)link_len);
  			}
  
  			/*
***************
*** 530,539 ****
  			else
  				inumber = (ino_t)ROOTINO;
  
! 			if ((rc = read_inode(inumber, fp)) != 0)
  				goto out;
  		}
- #endif
  	}
  
  	/*
--- 530,540 ----
  			else
  				inumber = (ino_t)ROOTINO;
  
! 			if ((rc = read_inode(inumber, f)) != 0)
  				goto out;
+ 			namebuf[link_len] = '\0';
+ 			printf(" -> ");
  		}
  	}
  
  	/*
***************
*** 541,546 ****
--- 542,550 ----
  	 */
  	rc = 0;
  out:
+ 	printf("\n");
+ 	if (buf)
+ 		free(buf, fs->fs_bsize);
  	if (rc)
  		free(fp, sizeof(struct file));
  	return (rc);
>Audit-Trail:
>Unformatted: