home *** CD-ROM | disk | FTP | other *** search
- /*
- * dir.c
- *
- * Directory build/scan routines by David Lutz
- * Expanded, debugged, and list_dir added by Jason Hunter
- *
- * This file contains routines for handling directories.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <time.h>
- #include "ext2.h"
- #include "proto.h"
-
- #define DEBUG 0
- #define SOFTLINK 0120000
- #define DIRECTORY 0040000
- #define FILE 0100000
-
- long eatpath( char *path )
- {
- inode *i;
- long inode_num;
- char *buf, *path_seg, *old_path_seg;
- struct dir *dir_head;
-
- if( !strcmp( path, "/" ) ) /* Look for path = root dir */
- {
- return( (long)2 ); /* bail quick and early if so */
- }
-
- /* Load root directory */
- i = load_inode( (long)2 );
-
- if( (buf = (byte *)malloc( i->i_blocks * 512 )) == NULL )
- {
- fprintf( stderr, "Memory problem in eatpath.\n" );
- exit( -1 ); /* Memory Problems */
- }
- if( read_inode( i, buf, i->i_blocks * 512 ) == -1 ) /* Problem encountered */
- exit( -1 );
- dir_head = build_dir( buf, i->i_blocks * 512 );
-
- path_seg = strtok( path, "/" ); /* break out first path element */
-
- while( path_seg != NULL )
- {
- if( DEBUG ) printf( "Looking for %s\n", path_seg );
- inode_num = search_dir( dir_head, path_seg );
- if( inode_num == 0 ) /* Error!!! */
- {
- fprintf( stderr, "Can't find '%s'.\n", path_seg );
- return( 0 );
- }
-
- if( DEBUG ) printf( "Inode for %s = %ld\n", path_seg, inode_num );
-
- /* Release Space */
- free( buf );
- kill_dir( dir_head );
-
- /* Read in the next directory */
- i = load_inode( inode_num );
-
- /* Verify this inode is not a softlink before we proceed */
- if( (i->i_mode & SOFTLINK) == SOFTLINK)
- {
- fprintf( stderr, "Softlink '%s' cannot be processed.\n", path_seg );
- exit( -1 );
- }
-
- /* See if there's more string to parse */
- old_path_seg = path_seg; /* works since it was from strtok() */
- path_seg = strtok( NULL, "/" ); /* Get next section of path */
- if( path_seg == NULL ) break; /* No more path to look for */
-
- /* There appears to be more to go, so see if we can... */
- if( (i->i_mode & FILE) == FILE)
- {
- fprintf( stderr, "File '%s' cannot be processed as a directory.\n",
- old_path_seg );
- exit( -1 );
- }
-
- if( (buf = (byte *)malloc( i->i_blocks * 512 )) == NULL )
- {
- fprintf( stderr, "Memory problem in eatpath.\n" );
- exit( -1 ); /* Memory Problems */
- }
- read_inode( i, buf, i->i_blocks * 512 );
-
- dir_head = build_dir( buf, i->i_blocks * 512 );
- }
-
- return( inode_num );
- }
-
- /* Release some excess space */
- void kill_dir( struct dir *head )
- {
- struct dir *temp, *temp1;
-
- temp = head;
-
- while( temp != NULL )
- {
- temp1 = temp;
- temp = temp->next;
- free( temp1->name );
- free( temp1 );
- }
- }
-
- /* Print out a listing of the directory w/inode numbers */
- void print_dir( struct dir *head )
- {
- struct dir *temp;
-
- temp = head;
-
- while( temp != NULL )
- {
- printf( "%9ld %s\n", temp->inode_num, temp->name );
- temp = temp->next;
- }
- }
-
- /* List a directory (names and inode numbers) with inode struct as input */
- void list_dir( inode *i )
- {
- char *buf;
- struct dir *temp, *temp2;
- inode *in;
-
- if( (buf = (byte *)malloc( i->i_blocks * 512 )) == NULL )
- {
- fprintf( stderr, "Memory problem in list_dir.\n" );
- exit( -1 ); /* Memory Problems */
- }
- if( read_inode( i, buf, i->i_blocks * 512 ) == -1 ) /* Problem encountered */
- exit( -1 );
- temp = build_dir( buf, i->i_blocks * 512 );
-
- free( buf );
- while( temp != NULL )
- {
- in = load_inode( temp->inode_num );
- if( in == NULL ) exit( -1 ); /* We hit a problem */
- printf( "%10s %5d %5d %9ld %s %s\n",
- build_mode( in ), in->i_uid, in->i_gid, in->i_size,
- strtok( ctime( &(in->i_atime) )+4, "\n"), temp->name );
- temp = temp->next;
- }
- }
-
- /* Convert a buf to a linked list directory structure */
- struct dir *build_dir( byte *buf, size_t buf_size )
- {
- struct dir *temp, *head, *dummy;
- int rec_len, name_len, count = 0;
- long inode_num;
-
- temp = dummy = head = NULL;
-
- while( count + 8 < buf_size ) /* Don't run over end */
- {
- inode_num = *( (long *)(buf + count ) );
- rec_len = *( (short *)(buf + count + 4) );
- name_len = *( (short *)(buf + count + 6) );
-
- if( rec_len == 0 ) break; /* I think this means the end ??? */
- if( inode_num == 0 ) /* This means a deleted entry */
- {
- count += rec_len; /* keep reading... */
- continue;
- }
-
- dummy = temp; /* Don't lose list tail */
- if( (temp = (struct dir *)malloc( sizeof( struct dir ) )) == NULL )
- {
- fprintf( stderr, "Directory too big: build_dir ran out of memory.\n" );
- fprintf( stderr, "This is common with large directories (Lousy DOS)\n" );
- exit( -1 );
- }
-
- if( (temp->name = (char *)malloc( name_len+1 ) ) == NULL )
- {
- fprintf( stderr, "Directory too big: build_dir ran out of memory.\n" );
- fprintf( stderr, "This is common with large directories (Shitty DOS)\n" );
- exit( -1 );
- }
-
- temp->inode_num = inode_num;
- strncpy( temp->name, buf + count + 8, name_len );
- temp->name[name_len] = '\0'; /* terminate name string */
- temp->next = NULL;
- if( dummy != NULL ) dummy->next = temp; /* Add to list */
- if( head == NULL ) head = temp; /* Save head of list */
-
- count += rec_len; /* increment counter */
- }
-
- return( head );
- }
-
- /* Search a directory list for an entry: return inode if found, 0 if not */
- long search_dir( struct dir *head, char *str )
- {
- long inode_num = 0;
- struct dir *temp;
-
- temp = head;
- while( temp != NULL )
- {
- if( !strcmp( temp->name, str ) ) /* Do these match? */
- {
- inode_num = temp->inode_num;
- break; /* Don't bother searching the rest */
- }
-
- temp = temp->next;
- }
-
- return( inode_num );
- }
-
- char *build_mode( inode *i )
- {
- static char modestr[11];
- char fullstr[11];
- int x;
-
- strcpy( modestr, "?---------" );
- strcpy( fullstr, "-rwxrwxrwx" );
-
- for( x = 0; x < 9; x++ )
- if( ( i->i_mode >> x ) & 1 )
- modestr[9-x] = fullstr[9-x];
-
- /* here order counts right now */
- if( (i->i_mode & SOFTLINK) == SOFTLINK)
- modestr[0] = 'l';
- else if( (i->i_mode & DIRECTORY) == DIRECTORY)
- modestr[0] = 'd';
- else if( (i->i_mode & FILE) == FILE)
- modestr[0] = '-';
-
- return modestr;
-
- }