0

So what I am trying to do is do the same thing that "ls" command in unix though. So here is code the code that does it. But what I want to do is add a global variable that will count the number of hidden files and the number of user executable files.

#include    <stdio.h>
#include    <sys/types.h>
#include    <dirent.h>
#include    <sys/stat.h>

void do_ls(char[]);
void dostat(char *);
void show_file_info( char *, struct stat *);
void mode_to_letters( int , char [] );
char *uid_to_name( uid_t );
char *gid_to_name( gid_t );

main(int ac, char *av[])
{
    if ( ac == 1 )
        do_ls( "." );
    else
        while ( --ac ){
            printf("%s:\n", *++av );
            do_ls( *av );
        }
}

void do_ls( char dirname[] )
/*
 *  list files in directory called dirname
 */
{
    DIR     *dir_ptr;       /* the directory */
    struct dirent   *direntp;       /* each entry    */

    if ( ( dir_ptr = opendir( dirname ) ) == NULL )
        fprintf(stderr,"ls1: cannot open %s\n", dirname);
    else
    {
        while ( ( direntp = readdir( dir_ptr ) ) != NULL )
            dostat( direntp->d_name );
        closedir(dir_ptr);
    }
}

void dostat( char *filename )
{
    struct stat info;

    if ( stat(filename, &info) == -1 )      /* cannot stat   */
        perror( filename );         /* say why   */
    else                    /* else show info    */
        show_file_info( filename, &info );
}

void show_file_info( char *filename, struct stat *info_p )
/*
 * display the info about 'filename'.  The info is stored in struct at *info_p
 */
{
    char    *uid_to_name(), *ctime(), *gid_to_name(), *filemode();
    void    mode_to_letters();
        char    modestr[11];

    mode_to_letters( info_p->st_mode, modestr );

    printf( "%s"    , modestr );
    printf( "%4d "  , (int) info_p->st_nlink);  
    printf( "%-8s " , uid_to_name(info_p->st_uid) );
    printf( "%-8s " , gid_to_name(info_p->st_gid) );
    printf( "%8ld " , (long)info_p->st_size);
    printf( "%.12s ", 4+ctime(&info_p->st_mtime));
    printf( "%s\n"  , filename );

}

/*
 * utility functions
 */

/*
 * This function takes a mode value and a char array
 * and puts into the char array the file type and the 
 * nine letters that correspond to the bits in mode.
 * NOTE: It does not code setuid, setgid, and sticky
 * codes
 */
void mode_to_letters( int mode, char str[] )
{
    strcpy( str, "----------" );           /* default=no perms */

    if ( S_ISDIR(mode) )  str[0] = 'd';    /* directory?       */
    if ( S_ISCHR(mode) )  str[0] = 'c';    /* char devices     */
    if ( S_ISBLK(mode) )  str[0] = 'b';    /* block device     */

    if ( mode & S_IRUSR ) str[1] = 'r';    /* 3 bits for user  */
    if ( mode & S_IWUSR ) str[2] = 'w';
    if ( mode & S_IXUSR ) str[3] = 'x';

    if ( mode & S_IRGRP ) str[4] = 'r';    /* 3 bits for group */
    if ( mode & S_IWGRP ) str[5] = 'w';
    if ( mode & S_IXGRP ) str[6] = 'x';

    if ( mode & S_IROTH ) str[7] = 'r';    /* 3 bits for other */
    if ( mode & S_IWOTH ) str[8] = 'w';
    if ( mode & S_IXOTH ) str[9] = 'x';
}

#include    <pwd.h>

char *uid_to_name( uid_t uid )
/* 
 *  returns pointer to username associated with uid, uses getpw()
 */ 
{
    struct  passwd *getpwuid(), *pw_ptr;
    static  char numstr[10];

    if ( ( pw_ptr = getpwuid( uid ) ) == NULL ){
        sprintf(numstr,"%d", uid);
        return numstr;
    }
    else
        return pw_ptr->pw_name ;
}

#include    <grp.h>

char *gid_to_name( gid_t gid )
/*
 *  returns pointer to group number gid. used getgrgid(3)
 */
{
    struct group *getgrgid(), *grp_ptr;
    static  char numstr[10];

    if ( ( grp_ptr = getgrgid(gid) ) == NULL ){
        sprintf(numstr,"%d", gid);
        return numstr;
    }
    else
        return grp_ptr->gr_name;
}

I want to show an output the same as what it shows, but also say "The number of hidden values are: " and "The number of user executable files are: _"

I know for the hidden values; I need to check the first character of the file name.. But I am struggling with that.

I also know for the user exectuable files I need to use bit masking. But I have never done that before.

Any help?

hiquetj
  • 410
  • 1
  • 8
  • 23
  • If `filename` is the file name and it's an array, use the syntax for accessing the first element of the array. As for bitmask, look up `&`, `|`, and `~` in any C book. – Paul J. Lucas Feb 02 '16 at 00:15
  • Do you classify the file as executable event hough it isn't executable by the user running your code? If this is the case then `mode & (S_IXUSR | S_IXGRP | S_IXOTH)` will be the condition to use. If the file is not considered executable then the condition will be a little more complex `mode & ((S_IXUSR & info_p->st_uid == getuid()) | (S_IXGRP & info_p->st_gid == getgid()) | (S_IXOTH))`. Note: this is a suggestion. You have to optimize the code. – alvits Feb 02 '16 at 00:20
  • @alvits When I meant user I meant owner. So just the owner being able to execute – hiquetj Feb 03 '16 at 15:27
  • Let's say you have `executables` and `hiddenfiles` variables, you can increment `executables` when `S_ISREG(mode) & mode & S_IXUSR` is true and increment `hiddenfiles` when `filename[0] == '.' && S_ISREG(mode)`. – alvits Feb 03 '16 at 22:10
  • the `ls` command has the ability to handle options (there are a bunch, as listed in the man page) the posted code does not handle any options. – user3629249 Feb 04 '16 at 23:20

0 Answers0