C File System Exploration: Data Structures and Directory Listing

C File System Exploration

This document details the implementation of a file system exploration tool in C. It includes data structures, permission handling, and directory listing functionalities.

Data Structures

The following constants and structures are defined:

  • MAX_PATH: Maximum path length (150).
  • MAX_NOMBRE: Maximum file name length (32).
  • MAX_FICHEROS: Maximum number of files (500).

The datosF structure stores file information:


struct datosF {
  char name[MAX_NOMBRE];
  long size;
  long inode;
  char *user;
  char *group;
  char permission[10];
};

Permission Handling

The damePermisos function converts file mode permissions to a string:


char *damePermisos(mode_t st_mode) {
  char *permission = malloc(10);
  strcpy(permission, "----------");
  if ((st_mode & S_IFDIR) == S_IFDIR) permission[0] = 'd';
  if ((S_IRUSR & st_mode) == S_IRUSR) permission[1] = 'r';
  if ((S_IWUSR & st_mode) == S_IWUSR) permission[2] = 'w';
  if ((S_IXUSR & st_mode) == S_IXUSR) permission[3] = 'x';
  if ((S_IRGRP & st_mode) == S_IRGRP) permission[4] = 'r';
  if ((S_IWGRP & st_mode) == S_IWGRP) permission[5] = 'w';
  if ((S_IXGRP & st_mode) == S_IXGRP) permission[6] = 'x';
  if ((S_IROTH & st_mode) == S_IROTH) permission[7] = 'r';
  if ((S_IWOTH & st_mode) == S_IWOTH) permission[8] = 'w';
  if ((S_IXOTH & st_mode) == S_IXOTH) permission[9] = 'x';
  return permission;
}

Sorting Functions

The following functions are used for sorting file data:

  • ordenaTamano_maM: Sorts by size (ascending).
  • ordenaTamano_Mam: Sorts by size (descending).
  • ordenaNombre: Sorts by name (ascending).
  • ordenaNombre_Inv: Sorts by name (descending).

int ordenaTamano_maM(const void * _a, const void * _b) {
  struct datosF a = * ((struct datosF *) _a);
  struct datosF b = * ((struct datosF *) _b);
  return (a.size - b.size);
}

int ordenaTamano_Mam(const void * _a, const void * _b) {
  struct datosF a = * ((struct datosF *) _a);
  struct datosF b = * ((struct datosF *) _b);
  return (b.size - a.size);
}

int ordenaNombre(const void * _a, const void * _b) {
  struct datosF a = * ((struct datosF *) _a);
  struct datosF b = * ((struct datosF *) _b);
  return strcmp(a.name, b.name);
}

int ordenaNombre_Inv(const void * _a, const void * _b) {
  struct datosF a = * ((struct datosF *) _a);
  struct datosF b = * ((struct datosF *) _b);
  return strcmp(b.name, a.name);
}

Directory Listing Function

The do_ls function lists directory contents with various options:


void do_ls(char *name, int opt_long, int opt_size, int opt_recursive, int opt_hidden, int opt_inode, int opt_sort_size, int opt_reverse) {
  DIR *dir;
  char path[MAX_PATH] = "";
  char trayec_var[MAX_PATH] = "";
  struct dirent *infodir;
  struct datosF datosFichero[MAX_FICHEROS];
  struct stat infoBuffer;
  static int recursive = 0;

  dir = opendir(name);
  if (dir == NULL) {
    perror("opendir error");
    exit(1);
  } else {
    strcat(path, name);
    if (recursive == 0) {
      printf("\nlist %s with long format = %d, size = %d, recursive = %d, hidden = %d inode = %d sort_size = %d reverse = %d\n",
             name, opt_long, opt_size, opt_recursive, opt_hidden, opt_inode, opt_sort_size, opt_reverse);
      strcat(path, "/");
      printf("\n----> We started by listing the elements of: %s", path);
    }
    infodir = readdir(dir);
    int cont = 0;
    while (infodir != NULL && cont < MAX_FICHEROS) {
      strcpy(trayec_var, path);
      strcat(trayec_var, infodir->d_name);
      stat(trayec_var, &infoBuffer);
      strcpy(datosFichero[cont].name, infodir->d_name);
      datosFichero[cont].size = infoBuffer.st_size;
      datosFichero[cont].inode = infoBuffer.st_ino;
      datosFichero[cont].user = getpwuid(infoBuffer.st_uid)->pw_name;
      datosFichero[cont].group = getgrgid(infoBuffer.st_gid)->gr_name;
      strcpy(datosFichero[cont].permission, damePermisos(infoBuffer.st_mode));
      infodir = readdir(dir);
      cont++;
    }
    closedir(dir);

    if (opt_sort_size == 1) {
      if (opt_reverse == 1)
        qsort(datosFichero, cont, sizeof(struct datosF), ordenaTamano_maM);
      else
        qsort(datosFichero, cont, sizeof(struct datosF), ordenaTamano_Mam);
    } else {
      if (opt_reverse == 1)
        qsort(datosFichero, cont, sizeof(struct datosF), ordenaNombre_Inv);
      else
        qsort(datosFichero, cont, sizeof(struct datosF), ordenaNombre);
    }

    printf("\n");
    for (int i = 0; i < cont; i++) {
      if ((opt_hidden == 1) || (strcmp(datosFichero[i].name, ".") != 0 && strcmp(datosFichero[i].name, "..") != 0)) {
        if (opt_inode == 1) {
          printf("\t%ld\t", datosFichero[i].inode);
        }
        if (opt_long == 1) {
          printf("\t%s", datosFichero[i].user);
          printf("\t%s", datosFichero[i].group);
          printf("\t%s", datosFichero[i].permission);
        }
        if (opt_size == 1) {
          printf("\t%ld\t", datosFichero[i].size);
        }
        printf("%s\n", datosFichero[i].name);
        if ((opt_recursive == 1) && (datosFichero[i].permission[0] == 'd')) {
          recursive = 1;
          strcpy(trayec_var, path);
          strcat(trayec_var, datosFichero[i].name);
          strcat(trayec_var, "/");
          do_ls(trayec_var, opt_long, opt_size, opt_recursive, opt_hidden, opt_inode, opt_sort_size, opt_reverse);
          int j = i + 1;
          if (j < cont)
            printf("<---- continue listing the elements of: %s\n", path);
        }
      }
    }
  }
}