Low level Linux Directory command

Low level Linux Directory command 

Low Level I/O 

You will use the C low level I/O functions to create our own xdir command in C. This program must not use bash, ls, sed, awk, and/or Perl.  It must not use any of the exec functions.

Syntax of xdir:

xdirdirectory

xdirdirectory switches

Your source code must be namedxdir.c 

In each of the cases, we show the directory.  The directory entries are then indented four spaces. 

Without any switches

  • xdir will first print the directory name followed by a colon.
  • xdir will not print any files that begin with “.”
  • xdir will print the filenames (unqualified) in the order they are provided by the readdir function.

>xdir Data

Data :

file5

file6

Program4

Program5

Program2

Program3

file4

With just the -l switch

  • xdir will first print the directory name followed by a colon.
  • xdir will not print any files that begin with “.”
  • For each file, xdir will print (on one line):
    • file name (unqualified)
    • file type (F – regular file, D – directory, L – link, P – Pipe)
    • number of 512 byte blocks
    • size in bytes
  • xdir will print the files in the order they are provided by the readdir function.

>xdir Data -l

Data :

file5 F 8 blks 167 bytes

file6 F 8 blks 121 bytes

Program4 D 8 blks 4096 bytes

Program5 D 8 blks 4096 bytes

Program2 D 8 blks 4096 bytes

Program3 D 8 blks 4096 bytes

file4 F 8 blks 87 bytes

With just the -a switch

  • xdir will first print the directory name followed by a colon.
  • xdir will print any files in the directory including ones that begin with a “.”
  • xdir will print the filenames (unqualified) in the order they are provided by the readdir function.

>xdir Data -a

Data :

.

..

file5

file6

.mydot

Program4

Program5

Program2

Program3

file4

With both the -l and -a switches

  • xdir will first print the directory name followed by a colon.
  • xdir will print any files in the directory including ones that begin with a “.”
  • For each file, xdir will print (on one line):
    • file name (unqualified)
    • file type (F – regular file, D – directory, L – link, P – Pipe)
    • number of 512 byte blocks
    • size in bytes
  • xdir will print the files in the order they are provided by the readdir function.

>xdir Data -l -a

Data :

. D 8 blks 4096 bytes

.. D 8 blks 4096 bytes

file5 F 8 blks 167 bytes

file6 F 8 blks 121 bytes

.mydot F 8 blks 25 bytes

Program4 D 8 blks 4096 bytes

Program5 D 8 blks 4096 bytes

Program2 D 8 blks 4096 bytes

Program3 D 8 blks 4096 bytes

file4 F 8 blks 87 bytes

Solution

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <dirent.h>

#include <sys/types.h>

#include <sys/stat.h>

#define OFFSET 4

charfile_type(struct stat path_stat)

{

if ( S_ISDIR(path_stat.st_mode) )

return ‘D’;

else if ( S_ISFIFO(path_stat.st_mode) )

return ‘P’;

else if ( S_ISLNK(path_stat.st_mode) )

return ‘L’;

else

return ‘F’;

}

intprocess_dir(char *dirname, intaflag, intlflag, intrflag, int level) {

DIR *dir;

structdirent *dp;

struct stat path_stat;

char path[1024];

charftype;

dir = opendir(dirname);

while( (dp = readdir(dir)) != NULL ) {

/* skip hidden files */

if (dp->d_name[0] == ‘.’ &&aflag == 0)

continue;

/* complete path to the file */

snprintf(path, 1024, “%s/%s”, dirname, dp->d_name);

stat(path, &path_stat);

ftype = file_type(path_stat);

printf(“%*c”, (level + 1) * OFFSET, ‘ ‘);

printf(“%s”, dp->d_name);

if (ftype == ‘D’ &&rflag&&strcmp(dp->d_name, “.”) != 0 &&strcmp(dp->d_name, “..”) != 0 )

{

printf(“:\n”);

/* recursive call */

process_dir(path, aflag, lflag, rflag, level + 1);

}

else

{

if (lflag) /* print file stats */

printf(” %c %d blks %d bytes”, ftype, path_stat.st_blocks, path_stat.st_size);

printf(“\n”);

}

}

closedir(dir);

}

int main(intargc, char **argv) {

char *dirname;

intaflag = 0, lflag = 0, rflag = 0;

int index, c;

/* parse command-line arguments */

while ((c = getopt (argc, argv, “alr”)) != -1) {

switch (c) {

case ‘a’:

aflag = 1;

break;

case ‘l’:

lflag = 1;

break;

case ‘r’:

rflag = 1;

break;

case ‘?’:

return 1;

default:

break;

}

}

if (optind<argc) {  /* get the remaining argument: directory name */

dirname = argv[optind];

}

else {

printf(“usage: directory [-alr]\n”, argv[0]);

return 1;

}

printf(“%s:\n”, dirname);

process_dir(dirname, aflag, lflag, rflag, 0);

return 0;

}