9. Directories

Introduction

//------------------------------------------------------------------
#include <stdio.h> // perror(), fprintf()
#include <unistd.h> // stat(), fstat(), lstat()
#include <sys/stat.h> // struct stat

...

struct stat entry;
if( stat("/usr/bin/vi", &entry) < 0 )
  perror("");
if( S_ISREG(entry.st_mode) )
  fprintf( stderr, "file\n" );

...

//------------------------------------------------------------------
#include <stdio.h> // perror(), fprintf()
#include <unistd.h> // stat(), fstat(), lstat()
#include <sys/stat.h> // struct stat

...

struct stat entry;
if( stat("/usr/bin", &entry) < 0 )
  perror("");
if( S_ISDIR( entry.st_mode) )
  fprintf( stderr, "directory\n" );

...

//------------------------------------------------------------------
// we can't access the inode of a file with a stream as parameter
// we need to pass a file descriptor parameter to fstat
#include <stdio.h> // perror(), fprintf()
#include <unistd.h> // stat(), fstat(), lstat()
#include <sys/stat.h> // struct stat
#include <fcntl.h> //open()

...

struct stat entry;
int fd; // file descriptor
FILE * fp;  // stream

if((fd = open("/etc/group", O_RDONLY)) < 0)
  perror("");

if( fstat(fd, &entry) < 0 )
  perror("");
  
if((fp = fdopen(fd, "r" )) == NULL ) // we attach the file descriptor to a stream
  perror("");

...

//------------------------------------------------------------------
#include <stdio.h> // perror()
#include <unistd.h> // stat(), fstat(), lstat()
#include <sys/stat.h> // struct stat
#include <sys/types.h> // off_t

...
  
struct stat entry;

time_t ctime;
off_t size;

if( stat("/usr/bin/vi", &entry) < 0 )
  perror("");

ctime = entry.st_ctime;
size = entry.st_size;
//fprintf( stdout, "ctime: %ld\nsize: %ld\n", ctime, size );
  
...  

//------------------------------------------------------------------
// No equivalent in C ANSI/POSIX/GNU for -T (file is a text file)?
/*
# -s for filesize (test if nonzero)
unless (-s F && -T _) {
  die "$filename doesn't have text in it.\n";
}
*/

//------------------------------------------------------------------
#include <stdio.h>
#include <dirent.h> // struct dirent, opendir(), readdir(), closedir()
#include <sys/types.h> // DIR type

...

DIR * dir;
struct dirent * entry;

dir = opendir("/usr/bin");
if( dir == NULL )
  perror("");
while((entry = readdir(dir)) != NULL)
  fprintf(stdout, "Inside /usr/bin is something called %s\n", entry->d_name);
fprintf(stdout, "\n");
closedir(dir);

...

Getting and Setting Timestamps

Deleting a File

Copying or Moving a File

Recognizing Two Names for the Same File

Processing All Files in a Directory

Globbing, or Getting a List of Filenames Matching a Pattern

Processing All Files in a Directory Recursively

Removing a Directory and Its Contents

Renaming Files

Splitting a Filename into Its Component Parts

//------------------------------------------------------------------

//  we use the XPG version of basename which overrides
//  the GNU version (not portable) if libgen.h is included
//  /!\ do not call basename or dirname with a static string (bugs in glibc)

#include <stdio.h> // fprintf()
#include <stdlib.h> // free()
#include <string.h>  // strdup(), strrchr()
#include <libgen.h>  // basename(), dirname()

...
 char * dir, * file, * ext;
char * tmp_dirname, * tmp_file;
char * path = "/usr/lib/libc.a";

tmp_dirname = strdup(path);
tmp_file = strdup(path);
   dir = dirname(tmp_dirname);
file = basename(tmp_file);
ext = strrchr(path, '.'); // extension as everything after the last '.'

fprintf(stdout, "dir is %s, file is %s, ext is %s\n", dir, file, ext);
// dir is /usr/lib, file is libc.a, ext is .a
 free(tmp_file);
free(tmp_dirname);

...

//------------------------------------------------------------------
#include <stdio.h> // fprintf()
#include <stdlib.h> // free()
#include <string.h>  // strdup()
#include <libgen.h>  // basename(), dirname()

...

char * file, * dir, * tmp_file, * tmp_dirname;
char * path = "/usr/lib/libc.a";

tmp_file = strdup( path );
tmp_dirname = strdup( path );
dir = dirname( tmp_dirname );
file = basename( tmp_file );

fprintf( stdout, "dir is %s, file is %s\n", dir, file );
// dir is /usr/lib, file is libc.a
free(tmp_dirname);
free(tmp_file);
 ...

//------------------------------------------------------------------
// no equivalent in C for fileparse() but we can
//  implement a (very basic) similar function

#include <stdio.h> // fprintf()
#include <stdlib.h> // free()
#include <string.h>  // strdup(), strrchr(), strlen()

typedef struct Pathname_ {
  char * dirname;
  char * filename;
  char * extension;
}Pathname;

void fileparse( const char * path, Pathname * split_path) {
  char * tmp_path, * ptr, * extension;

  tmp_path = strdup(path);
 ptr= strrchr( tmp_path, '/');
  *ptr = '\0';
  ptr++;

  // dirname
  split_path->dirname = strdup(tmp_path);
  // filename
  split_path->filename = malloc(strlen(ptr) + 1);
  strcpy(split_path->filename, ptr);

  // extension
  extension = strrchr(path, '.'); // extension as everything
after the last '.'
  split_path->extension = strdup(extension);

  free(tmp_path);
 return;
}

int main( int argc, char * argv[] ) {

  Pathname fparsed;
  char * path = "/usr/lib/libc.a";
 fileparse(path, &fparsed);
 fprintf(stdout, "dir is %s, file is %s, ext is %s\n",
      fparsed.dirname,
      fparsed.filename,
      fparsed.extension);
  // dir is /usr/lib, file is libc.a, ext is .a
 free(fparsed.dirname);
  free(fparsed.filename);
  free(fparsed.extension);

  return 0;
}

//------------------------------------------------------------------
//  we are Unix centric so no equivalent for fileparse_set_fstype("MacOS");

//------------------------------------------------------------------
char * extension(const char * path){
  char * ext;
  ext = strrchr(path, '.');
  if(ext == NULL)
    return NULL;

  return ext;
}

// fprintf(stdout, "ext is %s\n", extension(path));
// ext is .a

Program: symirror

Program: lst