Insight into something.
//////////////////////////////////////////////////////////////////////////////// /** * @file ls_01.c * @brief Write a program in C that is similar to the ls command. * * @title ls 01 * @author Nicholas Guthrie * @web http//nickguthrie.com * @created February 4, 2013 * * Compile with: gcc -g -Wall -o ./ls_01 ls_01.c */ //////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------ :Libraries: // _ _ _ _ // | | (_) |__ _ _ __ _ _ _(_)___ ___ // | |__| | '_ \ '_/ _` | '_| / -_|_-< // |____|_|_.__/_| \__,_|_| |_\___/__/ // // ----------------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <limits.h> /* limits.h defines "PATH_MAX". */ #include <sys/stat.h> //----------------------------------------------------------------- :Prototypes: // ___ _ _ // | _ \_ _ ___| |_ ___| |_ _ _ _ __ ___ ___ // | _/ '_/ _ \ _/ _ \ _| || | '_ \/ -_|_-< // |_| |_| \___/\__\___/\__|\_, | .__/\___/__/ // |__/|_| // //----------------------------------------------------------------------------- int o_dir(char * dir, int level, char * f_name); void get_permissions (char *mode, unsigned int imode); /**----------------------------------------------------------------------- :Main: // __ __ _ // | \/ |__ _(_)_ _ // | |\/| / _` | | ' \ // |_| |_\__,_|_|_||_| // -----------------------------------------------------------------------------*/ int main( int argc, char *argv[] ) { char d_name[3] = "."; /* initial directory */ //Debug - cleaner way of formatting pointers? char * p_name = d_name; char * pf_name = NULL; //Obtain Argument if ( argc == 2 ) /* argc should be 2 for correct execution */ { //printf( "Argument is %s\n", argv[1] ); pf_name = argv[1]; //strcpy(f_name, argv[1]); } // Error Checking for > 1 Argument if ( argc > 2 ) { printf( "Usage: %s (optional)filename\nExiting.\n", argv[0] ); return -1; } o_dir(p_name, 0, pf_name); return EXIT_SUCCESS; } //------------------------------------------------------------------ :Functions: // ___ _ _ // | __| _ _ _ __| |_(_)___ _ _ ___ // | _| || | ' \/ _| _| / _ \ ' \(_-< // |_| \_,_|_||_\__|\__|_\___/_||_/__/ // // //----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /** * @brief Recursively search for directories. * @param[in] c_dir The name of the directory to search. * @param[in] level Used to keep track of spacing for sub-directories. * @return EXIT_SUCCESS if successful */ //////////////////////////////////////////////////////////////////////////////// int o_dir( char * c_dir, int level, char * f_name ) { DIR * dir = opendir(c_dir); struct dirent * file; while ( ( file = readdir( dir ) ) != NULL ) { // check for dir open failure if ( dir == NULL ) { perror( "opendir() failed\n" ); return EXIT_FAILURE; } // Read File Info struct stat buf; int rc = lstat( file->d_name, &buf ); // check for . or .. as first char in name if ( (strcmp (file->d_name, "..") != 0 && strcmp (file->d_name, ".") != 0) && ( S_ISDIR(buf.st_mode) || ( S_ISREG( buf.st_mode ) && (f_name == NULL || strcmp(f_name, file->d_name) == 0)))) { //Print Directory Level Spacing int i; for(i=0; i<level*4;i++) printf(" "); //@DEBUG - What is this used for? if ( rc < 0 ) { /* perror( "lstat() failed\n" ); */ /* return EXIT_FAILURE; */ } else { printf( "%s ", file->d_name); if ( S_ISDIR( buf.st_mode ) ) { char rwx_perms[12]; get_permissions (rwx_perms, buf.st_mode); printf( "(subdirectory) [%s]\n", rwx_perms); // Recursive Section int path_length; char path[PATH_MAX]; path_length = snprintf (path, PATH_MAX, "%s/%s", c_dir, file->d_name); //Check Path Length if (path_length >= PATH_MAX) { fprintf (stderr, "Path length has got too long.\n"); exit (EXIT_FAILURE); } //Recursively call with the new path. chdir(file->d_name); o_dir (".", level + 1, f_name); chdir(".."); } // Regular File else if ( S_ISREG(buf.st_mode) ) { //Determine rwx_perms char rwx_perms[12]; get_permissions (rwx_perms, buf.st_mode); printf( "(%d bytes) [%s]\n", (int) buf.st_size, rwx_perms); } // Sub-Directory // System Link /*else if ( S_ISLNK( buf.st_mode ) ) { printf( "[symbolic link]\n" ); }*/ // Unknown File /* else */ /* { */ /* //Do Nothing */ /* } */ } } } closedir( dir ); return EXIT_SUCCESS; } //////////////////////////////////////////////////////////////////////////////// /** * @brief Given the octal permission of a file, determine rwx human readable * @param[out] mode Stores the string of rwx permissions. * @param[in] imode * @return void. Results stored in *mode. */ //////////////////////////////////////////////////////////////////////////////// void get_permissions (char *mode, unsigned int imode ) { int i[16]; int count=0; int rem; memset( i,0,16 ); memset( mode,'\0',11 ); /*Convert to binary*/ while ( imode>0 ) { rem=imode%2; imode/=2; i[count]=rem; count++; } /*End Binary Coversion*/ count=0; /*Start Processing bits*/ int j; for ( j=15;j>=0;j-- ) { switch ( j ) { case 15 : if ( i[j]==1 ) { mode[count]='-'; count++; } else { mode[count]='d'; count++; } break; case 8 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='r'; count++; } break; case 7 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='w'; count++; } break; case 6 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='x'; count++; } break; case 5 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='r'; count++; } break; case 4 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='w'; count++; } break; case 3 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='x'; count++; } break; case 2 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='r'; count++; } break; case 1 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='w'; count++; } break; case 0 : if ( i[j]==0 ) { mode[count]='-'; count++; } else { mode[count]='x'; count++; } break; } } }