Logo Search packages:      
Sourcecode: linux86 version File versions  Download package

fs_tar.c

#include "monitor.h"

#define HEADER_SIZE     512
#define NAME_SIZE 100
#define BLOCK_BOUNDARY   20

typedef union {
  char hdr_block[HEADER_SIZE];
  struct m {
      char m_name[NAME_SIZE];
      char m_mode[8];
      char m_uid[8];
      char m_gid[8];
      char m_size[12];
      char m_time[12];
      char m_checksum[8];
      char m_linked;
      char m_link[NAME_SIZE];
      char m_ustar[8];
      char m_uname[32];
      char m_gname[32];

      char m_major[8];  /* GNU fields */
      char m_minor[8];
      char m_atime[12];
      char m_ctime[12];
      char m_offset[12];
      /* An so forth */
  } member;
} HEADER;

long tar_convert();
int  valid_tar_checksum();
void tar_set_drive();

static int disk_size = 0;

struct tx {
   char name[NAME_SIZE];
   int  first_sectno;
   int  cur_sectno;
   int  sectcount;
   int  diskoffset;
   long file_length;
} tar_status;

tar_open_file(fname)
char * fname;
{
   HEADER * sptr;
#ifndef NOCOMMAND
   int dodir = 0;
#endif
   int sectno;

   sptr = read_sector(0);

   /* Is it a tar disk ? */
   if( !valid_tar_checksum(sptr) ) return -1;

   tar_set_drive();

#ifndef NOCOMMAND
   if( strcmp(fname, ".") == 0 )
      dodir=1;
   else
#endif
   {
      if( tar_status.diskoffset == 0 && strcmp(fname, tar_status.name) == 0 )
         return tar_rewind_file();
   }

   tar_close_file();

   for(sectno=0;;)
   {
      long fl, v;

      if(sectno) sptr = read_sector(sectno);
      if(!sptr || !*sptr->member.m_name) break;

      if( !valid_tar_checksum(sptr) )
      {
         printf("Checksum error on tar header\n");
         return -1;
      }

      fl = tar_convert(sptr->member.m_size, 12);
      v = (fl+511)/512 + 1;

      if( sptr->member.m_linked != 0 && sptr->member.m_linked != '0' )
         ;
#ifndef NOCOMMAND
      else if( dodir )
          printf("%s %d tape blocks\n", sptr->member.m_name, (int)v-1);
#endif
      else if( strcmp(fname, sptr->member.m_name, NAME_SIZE) == 0 )
      {
         strncpy(tar_status.name, sptr->member.m_name, NAME_SIZE);
       tar_status.first_sectno = sectno+1;
       tar_status.cur_sectno = sectno+1;
       tar_status.file_length = fl;
       tar_status.sectcount = v-1;
       tar_status.diskoffset = 0;
       return 0;
      }

      if( v < 1 || (sectno += v) > disk_size ) break;
   }

   return -1;
}

tar_rewind_file()
{
   if( tar_status.name[0] == '\0' || tar_status.diskoffset != 0 )
   {
      tar_close_file();
      return -1;
   }

   tar_status.cur_sectno = tar_status.first_sectno;
   return 0;
}

tar_close_file()
{
   tar_status.name[0] = 0;
   tar_status.first_sectno = -1;
   tar_status.cur_sectno = -1;
   tar_status.file_length = -1;
   tar_status.diskoffset = -1;

   return 0;
}

long
tar_file_length()
{
   if( tar_status.name[0] == '\0' ) return -1;

   return tar_status.file_length;
}

tar_read_block(buffer)
char * buffer;
{
   char * ptr;
   HEADER * sptr;
   int i;
   if( tar_status.name[0] == '\0' ) return -1;

   for(i=0; i<2; i++)
   {
      if( tar_status.cur_sectno - tar_status.first_sectno >= tar_status.sectcount )
      {
         memset(buffer, '\0', 512);
      }
      else
      {
       if( tar_status.cur_sectno >= tar_status.diskoffset+disk_size )
       {
          int k;
          tar_status.diskoffset += disk_size-2;

          for(;;)
          {
             printf("Please insert next disk and press return:");
             fflush(stdout);
             while( (k=(getch() & 0x7F)) != '\r' && k != '\n')
                if( k == 27 || k == 3 )
              {
                 printf("... Aborting\n");
                 return -1;
                }
             printf("\n");

             sptr = read_sector(0);
             if( !valid_tar_checksum(sptr) )
             {
                printf("Checksum failed reading volume label\n");
              continue;
             }
             tar_set_drive();
             sptr = read_sector(1);
             if( !valid_tar_checksum(sptr)
               || sptr->member.m_linked != 'M'
             || 512*(long)(tar_status.cur_sectno-tar_status.first_sectno)
                != tar_convert(sptr->member.m_offset, 12)
               )
             {
                printf("Wrong disk inserted, ");
              continue;
             }
             break;
          }
            ptr = read_sector(tar_status.cur_sectno-tar_status.diskoffset);
       }
       else
            ptr = read_sector(tar_status.cur_sectno-tar_status.diskoffset);
         if( ptr == 0 ) return -1;
   
         memcpy(buffer, ptr, 512);
      }
      buffer+=512;
      tar_status.cur_sectno++;
   }

   return 0;
}

long 
tar_convert(str, type)
char  str[];
int   type;
{
   register long ac = 0L;
   register int i;

   for (i = 0; i < type; i++)
   {
      if (str[i] >= '0' && str[i] <= '7')
      {
       ac <<= 3;
       ac += (long) (str[i] - '0');
      }
   }
   return ac;
}

valid_tar_checksum(sptr)
register HEADER * sptr;
{
   register char *ptr;
   int ac = 0;

   ptr = sptr->hdr_block;
   while (ptr < sptr->hdr_block+sizeof(sptr->hdr_block))
      if( ptr < sptr->member.m_checksum ||
          ptr >= sptr->member.m_checksum+sizeof(sptr->member.m_checksum))
       ac += (*ptr++ & 0xFF);
      else
       ptr++, (ac += ' ');

   ac -= tar_convert(sptr->member.m_checksum, sizeof(sptr->member.m_checksum));
   return ac == 0;
}

void
tar_set_drive()
{
#ifdef __STANDALONE__
   disk_spt = __argr.x.si;

   /* Choose some formats, note Boot block only sees a few SPT.
    *      9x40=360k, 15x80=1200k, 18x80=1440k, 21x82=1722k, 36x80=2880k
    */
   if( disk_spt <= 9 )               disk_cyls = 40;
   if( disk_spt == 21 || disk_spt > 36 ) disk_cyls = 82;
   else if( disk_spt == 32 )             disk_cyls = 1024;
   else                              disk_cyls = 80;
#else
   disk_spt = 18; /* Testing only */
   disk_cyls= 80;
#endif
   disk_heads=2;

   disk_size = disk_spt*disk_cyls*disk_heads;
}

#if 0

#asm
!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
!
! These are the number of sectors per track that will be scanned for.
! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on
! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies.

disksizes: .byte 36,21,18,15,9

! It seems that there is no BIOS call to get the number of sectors.  Guess
! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
! 15 if sector 15 can be read.  Otherwise guess 9.

export _probe_sectors
_probe_sectors:
      mov   si,#disksizes           ! table of sizes to try

probe_loop:
      lodsb
      cbw                     ! extend to word
      mov   _disk_spt, ax
      cmp   al,#9
      je    got_sectors       ! if all else fails, try 9
      xchg  ax, cx                  ! cx = track and sector
      xor   dx, dx                  ! drive 0, head 0
      mov   bx,#probe_buf           ! address after setup (es = cs)
      mov   ax,#0x0201        ! service 2, 1 sector
      int   0x13
      jc    probe_loop        ! try next value
got_sectors:

      ret
#endasm

#endif

Generated by  Doxygen 1.6.0   Back to index