lkml.org 
[lkml]   [1998]   [Jan]   [4]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
/
From"Dave Cinege" <>
DateFri, 02 Jan 98 14:57:08 -0500
SubjectNeed some help hacking kernel.... (libc->kernel file operations)
Myself and a friend (Dima) are adding untar support to the initrd code so special 
archives can be used instead of those nasty raw images for boot disk's.
(It's a little more complex then that, but to save space....)
I have manged to finish up the new loading, uncompressing, etc functions in 
linux/drivers/block/rd.c. I'm now left with an uncompressed tar archive in 
/dev/ram1, that I can yank out from user space after boot.

We must now convert some libc untar code to work from the kernel.
The problem is neither Dima nor I know how to properly handle some of the file 
operations from within the kernel. 
IE the creation of files under the filesystem on the mounted root:
mkdir();
symlink();
chmod();
mknod();
etc

Below is the jist of our untar code. It's pretty much a mess right now but you can 
see what is going on. crd_infp (static struct file) is set all up in rd.c (just like before 
the gunzip part) and is pointing to the beginning of /dev/ram1. /dev/ram0 is already 
mounted as root and has a filesystem in it. (All of this done by the rd.c code)

If you want to run through the code and put some comments, or just point us to a 
good reference on how to convert this it would be most helpful. The /* FIXME: */ 
parts are where we are really lost.

/* 
 * untar() -- see comments for return codes
 *	outfd may be left open on error return !!
 */
//Dunno if  any of this is right.
/* not sure if it matters as we include this file into rd.c
 * which already has all these #include's anyway
 * move the #include "untar.c" directive few lines lower
 * in rd.c, tho' -- below the definition of fill_inbuf(),
 * otherwise gcc will barf (I think)
 */
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/kernel.h>  /* for simple_strtoul() & printk() */
#include <linux/stddef.h>  /* NULL, size_t */
#include <linux/fs.h>

#ifndef STATIC

#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
#  include <sys/types.h>
#  include <stdlib.h>
//stdlib conlides with the *malloc def
#endif
#define STATIC
#endif /* !STATIC */

STATIC int untar(void);


STATIC int untar(void)
{
#include "untar.h"

  char c;
  int err;
  struct file *outfd;
  int isreg, isdir, islnk, ischr, isblk, isfifo;
  unsigned long i, fsize, fmode, fuid, fgid;
  union TarInfo *tarInfo;	/* 512 bytes */
  int len = 512;		/* sizeof(union TarInfo); */
  tarInfo = kmalloc(len,GFP_KERNEL);
  if(tarInfo == 0) {
    printk(KERN_ERR "RAMDISK: can't allocate tar buffer\n");
    return(-1);
  }
  memset(tarInfo,0,len);
/* cd to target dir or return 1 */
/*  if((err=chdir(path)) == -1) return(1); */
//Im lost how we do this from the kernel...
/* we probably don't -- just make sure all tarballs are done in '/' 
 * otherwise we could probably use sys_chdir() in ../../fs/open.c
 * what do you think?
 */
 //I think we just don't  : >

/* main loop */  
  while(1) {
    isreg=FALSE; isdir=FALSE; islnk=FALSE; ischr=FALSE; isblk=FALSE; 
isfifo=FALSE;
/* read header or return short read */
    err=crd_infp->f_op->read(crd_infp->f_inode,crd_infp,tarInfo,len);
    if(err < len) 
      if(err == 0) return(0);
      else {
        printk(KERN_ERR "RAMDISK: corrupt tar archive\n");
	kfree(tarInfo);
        return(-1);
      }
/*    
 * thing is, tar pads the archive with a few blocks of 0's in the end, so
 * when we read the next block and its 1st byte is 0 it is most probably
 * padding -- really means EOF -- unless the tarball is stuffed :(
 * I could check if all 512 bytes are 0's and then it's definitely an EOF.
 * For now let's just return 0
 */
    if(tarInfo->header.name[0] == '\0') {
      kfree(tarInfo);
      return(0);
    }
    fmode=simple_strtoul(tarInfo->header.mode,(char **)NULL,8);
    fuid=simple_strtoul(tarInfo->header.uid,(char **)NULL,8);
    fgid=simple_strtoul(tarInfo->header.gid,(char **)NULL,8);
    fsize=simple_strtoul(tarInfo->header.size,(char **)NULL,8);
/* check the type */
    switch(tarInfo->header.typeflag) {
      case AREGTYPE :
      case REGTYPE  :
        isreg=TRUE;
/* FIXME : create() */
	outfd=crd_infp->f_inode->i_op->create(tarInfo->header.name); 
	if(outfd== -1) {
/* yell */
          kfree(tarInfo);
          return(-1);
        }
/* dump the file */
// hmm fsize crd_infp->f_size? Im not sure if we have a size here
//If not, I can figure it out buy looking at outfile.f_pos before 
//I reset it to 0.
        for(i=0;i<fsize;i++) {
          err=crd_infp->f_op->read(crd_infp->f_inode,crd_infp,&c,1);
          if(err < 1) {
            kfree(tarInfo);
            return(-1);
	  }
/* FIXME: write */
          err=crd_infp->f_op->write(outfd->f_inode,crd_infp,&c,1);
	  if(err < 1) {
            kfree(tarInfo);
            return(-1);
	  }
        }
/* ?? */
        if(outfd->f_op->release)
          outfd->f_op->release(outfd->f_inode,outfd);
        break;
      case LNKTYPE  :	/* hardlinks are restored as symlinks? */
      case SYMTYPE  :	/* do we really have to use hardlinks? */
/* at the moment ctar converts hardlinks to files 'cos otherwise 
 * it'd have to open a whole new can of worms --  keeping track of 
 * all the links to a give file etc... something else to fix later
 */
        islnk=TRUE;
/* FIXME: symlink() */
	err=symlink(tarInfo->header.linkname,tarInfo->header.name); 
	break;
      case CHRTYPE  :	/* char device */
      case BLKTYPE  :	/* block device */
      case FIFOTYPE :	/* named pipe */
/* FIXME: makedev, mknod() */
        fdev=MKDEV(simple_strtoul(tarInfo->header.devmajor,(char **)NULL,8),
	           simple_strtoul(tarInfo->header.devminor,(char **)NULL,8));
	err=mknod(tarInfo->header.name,fmode,fdev);
	break;
      case DIRTYPE  :	/* directory */
/*
 * ctar always(?) stores directory before its contents so we shouldn't
 * run into problem where file creation fails because some upper dir in  
 * the path doesn't exist.  is it really so, I wonder
 */
/* FIXME: mkdir() */
        err=mkdir(tarInfo->header.name,fmode);
	break;
      default:
        printk(KERN_ERR "RAMDISK: corrupt tar archive\n");
        kfree(tarInfo);
        return(-1);
    }
/* chmod and chown the file */
/* FIXME: chmod(), chown() */
    if(!islnk) {
      err=chown(tarInfo->header.name,fuid,fgid);
      err=chmod(tarInfo->header.name,fmode);
    }
/* skip to the next header */
  if(isreg)
    if(fsize%TARBLOCKSIZE != 0) 
lseek(infd,(off_t)(TARBLOCKSIZE*(fsize/TARBLOCKSIZE+1)-fsize),CURRENT);
//SEEK_CUR failed was not found. From what I can see in the rest of the rd.c
//code it should be CURRENT (but dont take my word for this)

  } /* end main loop */
}
-------------------------------------------------------------------------
http://www.psychosis.com/emc/		Elite MicroComputers   908-541-4214
http://www.psychosis.com/linux-router/	Linux Router Project

\
 
 \ /
  Last update: 2005-03-22 12:41    [W:0.053 / U:8.160 seconds]
©2003-2008 Jasper Spaans