home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / dos / lread10.exe / DIR.C next >
Encoding:
C/C++ Source or Header  |  1995-05-23  |  6.7 KB  |  253 lines

  1. /*
  2.  * dir.c
  3.  *
  4.  * Directory build/scan routines by David Lutz
  5.  * Expanded, debugged, and list_dir added by Jason Hunter
  6.  *
  7.  * This file contains routines for handling directories.
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <fcntl.h>
  14. #include <time.h>
  15. #include "ext2.h"
  16. #include "proto.h"
  17.  
  18. #define DEBUG 0
  19. #define SOFTLINK  0120000
  20. #define DIRECTORY 0040000
  21. #define FILE      0100000
  22.  
  23. long eatpath( char *path )
  24. {
  25.   inode *i;
  26.   long inode_num;
  27.   char *buf, *path_seg, *old_path_seg;
  28.   struct dir *dir_head;
  29.  
  30.   if( !strcmp( path, "/" ) )    /* Look for path = root dir */
  31.     {
  32.       return( (long)2 );    /* bail quick and early if so */
  33.     }
  34.  
  35.   /* Load root directory */
  36.   i = load_inode( (long)2 );
  37.  
  38.   if( (buf = (byte *)malloc( i->i_blocks * 512 )) == NULL )
  39.   {
  40.     fprintf( stderr, "Memory problem in eatpath.\n" );
  41.     exit( -1 );        /* Memory Problems */
  42.   }
  43.   if( read_inode( i, buf, i->i_blocks * 512 ) == -1 ) /* Problem encountered */
  44.     exit( -1 );
  45.   dir_head = build_dir( buf, i->i_blocks * 512 );
  46.  
  47.   path_seg = strtok( path, "/" ); /* break out first path element */
  48.  
  49.   while( path_seg != NULL )
  50.     {
  51.       if( DEBUG ) printf( "Looking for %s\n", path_seg );
  52.       inode_num = search_dir( dir_head, path_seg );
  53.       if( inode_num == 0 )    /* Error!!! */
  54.     {
  55.       fprintf( stderr, "Can't find '%s'.\n", path_seg );
  56.       return( 0 );
  57.     }
  58.  
  59.       if( DEBUG ) printf( "Inode for %s = %ld\n", path_seg, inode_num );
  60.  
  61.       /* Release Space */
  62.       free( buf );
  63.       kill_dir( dir_head );
  64.  
  65.       /* Read in the next directory */
  66.       i = load_inode( inode_num );
  67.  
  68.       /* Verify this inode is not a softlink before we proceed */
  69.       if( (i->i_mode & SOFTLINK) == SOFTLINK)
  70.       {
  71.         fprintf( stderr, "Softlink '%s' cannot be processed.\n", path_seg );
  72.         exit( -1 );
  73.       }
  74.  
  75.       /* See if there's more string to parse */
  76.       old_path_seg = path_seg;     /* works since it was from strtok() */
  77.       path_seg = strtok( NULL, "/" ); /* Get next section of path */
  78.       if( path_seg == NULL ) break; /* No more path to look for */
  79.  
  80.       /* There appears to be more to go, so see if we can... */
  81.       if( (i->i_mode & FILE) == FILE)
  82.       {
  83.         fprintf( stderr, "File '%s' cannot be processed as a directory.\n",
  84.                    old_path_seg );
  85.         exit( -1 );
  86.       }
  87.  
  88.       if( (buf = (byte *)malloc( i->i_blocks * 512 )) == NULL )
  89.       {
  90.         fprintf( stderr, "Memory problem in eatpath.\n" );
  91.         exit( -1 );        /* Memory Problems */
  92.       }
  93.       read_inode( i, buf, i->i_blocks * 512 );
  94.  
  95.       dir_head = build_dir( buf, i->i_blocks * 512 );
  96.     }
  97.  
  98.   return( inode_num );
  99. }
  100.  
  101. /* Release some excess space */
  102. void kill_dir( struct dir *head )
  103. {
  104.   struct dir *temp, *temp1;
  105.  
  106.   temp = head;
  107.  
  108.   while( temp != NULL )
  109.     {
  110.       temp1 = temp;
  111.       temp = temp->next;
  112.       free( temp1->name );
  113.       free( temp1 );
  114.     }
  115. }
  116.  
  117. /* Print out a listing of the directory w/inode numbers */
  118. void print_dir( struct dir *head )
  119. {
  120.   struct dir *temp;
  121.  
  122.   temp = head;
  123.  
  124.   while( temp != NULL )
  125.     {
  126.       printf( "%9ld %s\n", temp->inode_num, temp->name );
  127.       temp = temp->next;
  128.     }
  129. }
  130.  
  131. /* List a directory (names and inode numbers) with inode struct as input */
  132. void list_dir( inode *i )
  133. {
  134.   char *buf;
  135.   struct dir *temp, *temp2;
  136.   inode *in;
  137.  
  138.   if( (buf = (byte *)malloc( i->i_blocks * 512 )) == NULL )
  139.   {
  140.     fprintf( stderr, "Memory problem in list_dir.\n" );
  141.     exit( -1 );        /* Memory Problems */
  142.   }
  143.   if( read_inode( i, buf, i->i_blocks * 512 ) == -1 ) /* Problem encountered */
  144.     exit( -1 );
  145.   temp = build_dir( buf, i->i_blocks * 512 );
  146.  
  147.   free( buf );
  148.   while( temp != NULL )
  149.     {
  150.       in = load_inode( temp->inode_num );
  151.       if( in == NULL ) exit( -1 );         /* We hit a problem */
  152.       printf( "%10s %5d %5d %9ld  %s  %s\n",
  153.                build_mode( in ), in->i_uid, in->i_gid, in->i_size,
  154.                strtok( ctime( &(in->i_atime) )+4, "\n"), temp->name );
  155.       temp = temp->next;
  156.     }
  157. }
  158.  
  159. /* Convert a buf to a linked list directory structure */
  160. struct dir *build_dir( byte *buf, size_t buf_size )
  161. {
  162.   struct dir *temp, *head, *dummy;
  163.   int rec_len, name_len, count = 0;
  164.   long inode_num;
  165.  
  166.   temp = dummy = head = NULL;
  167.  
  168.   while( count + 8 < buf_size )    /* Don't run over end */
  169.     {
  170.       inode_num = *( (long *)(buf + count ) );
  171.       rec_len = *( (short *)(buf + count + 4) );
  172.       name_len = *( (short *)(buf + count + 6) );
  173.  
  174.       if( rec_len == 0 ) break;    /* I think this means the end ??? */
  175.       if( inode_num == 0 )      /* This means a deleted entry */
  176.       {
  177.         count += rec_len;       /* keep reading... */
  178.         continue;
  179.       }
  180.  
  181.       dummy = temp;        /* Don't lose list tail */
  182.       if( (temp = (struct dir *)malloc( sizeof( struct dir ) )) == NULL )
  183.         {
  184.           fprintf( stderr, "Directory too big: build_dir ran out of memory.\n" );
  185.           fprintf( stderr, "This is common with large directories  (Lousy DOS)\n" );
  186.           exit( -1 );
  187.         }
  188.  
  189.       if( (temp->name = (char *)malloc( name_len+1 ) ) == NULL )
  190.         {
  191.           fprintf( stderr, "Directory too big: build_dir ran out of memory.\n" );
  192.           fprintf( stderr, "This is common with large directories  (Shitty DOS)\n" );
  193.           exit( -1 );
  194.         }
  195.  
  196.       temp->inode_num = inode_num;
  197.       strncpy( temp->name, buf + count + 8, name_len );
  198.       temp->name[name_len] = '\0'; /* terminate name string */
  199.       temp->next = NULL;
  200.       if( dummy != NULL ) dummy->next = temp; /* Add to list */
  201.       if( head == NULL ) head = temp; /* Save head of list */
  202.  
  203.       count += rec_len;        /* increment counter */
  204.     }
  205.  
  206.   return( head );
  207. }
  208.  
  209. /* Search a directory list for an entry: return inode if found, 0 if not */
  210. long search_dir( struct dir *head, char *str )
  211. {
  212.   long inode_num = 0;
  213.   struct dir *temp;
  214.  
  215.   temp = head;
  216.   while( temp != NULL )
  217.     {
  218.       if( !strcmp( temp->name, str ) ) /* Do these match? */
  219.     {
  220.       inode_num = temp->inode_num;
  221.       break;        /* Don't bother searching the rest */
  222.     }
  223.  
  224.       temp = temp->next;
  225.     }
  226.  
  227.   return( inode_num );
  228. }
  229.  
  230. char *build_mode( inode *i )
  231. {
  232.   static char modestr[11];
  233.   char fullstr[11];
  234.   int x;
  235.  
  236.   strcpy( modestr, "?---------" );
  237.   strcpy( fullstr, "-rwxrwxrwx" );
  238.  
  239.   for( x = 0; x < 9; x++ )
  240.     if( ( i->i_mode >> x ) & 1 )
  241.       modestr[9-x] = fullstr[9-x];
  242.  
  243.   /* here order counts right now */
  244.   if( (i->i_mode & SOFTLINK) == SOFTLINK)
  245.     modestr[0] = 'l';
  246.   else if( (i->i_mode & DIRECTORY) == DIRECTORY)
  247.     modestr[0] = 'd';
  248.   else if( (i->i_mode & FILE) == FILE)
  249.     modestr[0] = '-';
  250.  
  251.   return modestr;
  252.  
  253. }