CSC 357 Lecture Notes Week 5
More on Files and Directories Function Pointers in C Standard I/O Library
System Data Files and Information
DIR* opendir(const char *filename); struct dirent *readdir(DIR* dirp); int closedir(DIR* dirp);
typedef struct dirent {
   ino_t d_ino;     /* inode numberof entry */
   off_t d_off;     /* offset of disk directory entry*/
   short d_reclen;  /* len of this record */
   char d_name[];   /* name of file */
} dirent_t;
int chdir(const char *pathname); int fchdir(int fildes); char* getcwd(char* buf, size_t size);
int ftw(const char *path,
        int (*fn) (const char*, const struct stat*, int),
        int depth);
int nftw(const char *path,
         int (*fn) (const char*, const struct stat*, int, struct FTW*),
         int depth,
         int flags);
#include <stdio.h>
#include <ftw.h>
/****
 *
 * Example use of nftw.
 *
 */
/**
 * The visit function is called by nftw for each element of a traversed
 * directory hierarchy.  It prints out the path of the element being visited,
 * and its mode as an octal value.  The first three octits of the mode are the
 * file type, with 040 indicating a directory, and 100 a plain file.  The last
 * three octits are the file permissions, e.g., 644 = "rw-r--r--".
 */
int visit(const char* path, const struct stat* stat, int flags, struct FTW* ftw) {
    printf("path=%s, mode=%o\n", path, stat->st_mode);
    return 0;
}
/**
 * The main function just calls nftw, catching any error it might return.
 */
main() {
    if (nftw(".", visit, 10, 0) != 0) {
        perror("nftw");
    }
}
#include <stdio.h>
#include <unistd.h>
#include "std-macros.h"
/**
 *
 * This program exercises the system qsort function.  The focus is on the
 * comparator functions that qsort calls, as an illustration of using function
 * pointers in C.
 *
 */
/**
 * Compare two void* values as ints, by casting them and using normal numeric
 * comparison.
 */
int intcmp(const void* a1, const void* a2) {
    int v1 = *((int*) a1);
    int v2 = *((int*) a2);
    if (v1 < v2) return -1;
    if (v1 > v2) return 1;
    return 0;
}
/**
 * Like intcmp, but reverses the sense of the comparison.  This allows the
 * sorting order to defined as descending, without changing the implementation
 * of the sort function.
 */
int intcmp_reverse(const void* a1, const void* a2) {
    int v1 = *((int*) a1);
    int v2 = *((int*) a2);
    if (v1 > v2) return -1;
    if (v1 < v2) return 1;
    return 0;
}
/**
 * Compare two void* values as numeric strings, by casting them to char*, then
 * converting them using atoi, then using normal numeric comparison.
 *
 * Note here the intermediate use of char** as a cast, then the deference down
 * to char*.  I.e,. the following code is used to cast the incoming void*
 * argument a1 into the char* variable s1:
 *
 *     char* s1 = *((char**) a1);
 *
 * The deal is that qsort works with pointers to the array values it's sorting,
 * not the values themselves.  In this case, the array being sorted contains
 * char* values.  This means that qsort is working with element pointers of
 * type char**, since it's pointing to each char* element of the arrays.
 * Hence, this function receives values of type char**, carried in the generic
 * pointers of type void*.
 */
int str_intcmp(const void* a1, const void* a2) {
    char* s1 = *((char**) a1);
    char* s2 = *((char**) a2);
    int v1 = atoi(s1);
    int v2 = atoi(s2);
    if (v1 < v2) return -1;
    if (v1 > v2) return 1;
    return 0;
}
/**
 * The main function defines unsorted int and string arrays.  It then calls the
 * system qsort function to sort the int array in ascending and descending
 * orders, using the preceding two int comparison functions.  It also calls
 * qsort to sort the string array in ascending order, using str_intcmp.
 */
main() {
    int i;
    int int_data[6] = {1, 8, 3, 4, 2, 1};
    char* str_data[6] = {"1", "8", "3", "4", "2", "1"};
    size_t int_nelems = sizeof(int_data) / sizeof(int);
    size_t str_nelems = sizeof(str_data) / sizeof(int);
    /*
     * Print the int array before sorting.
     */
    for (i = 0; i < int_nelems; i++) printf("%d ", int_data[i]);
    printf("\n");
    /*
     * Sort the int array using intcmp comparator and print results.
     */
    qsort((void*) int_data, int_nelems, sizeof(int), intcmp);
    for (i = 0; i < int_nelems; i++) printf("%d ", int_data[i]);
    printf("\n");
    /*
     * Sort the int array using intcmp_reverse comparator and print results.
     */
    qsort((void*) int_data, int_nelems, sizeof(int), intcmp_reverse);
    for (i = 0; i < int_nelems; i++) printf("%d ", int_data[i]);
    printf("\n");
    /*
     * Print the string array before sorting.
     */
    for (i = 0; i < str_nelems; i++) printf("%s ", str_data[i]);
    printf("\n");
    /*
     * Sort the string array using str_intcmp comparator and print results.
     */
    qsort((void*) str_data, str_nelems, sizeof(char*), str_intcmp);
    for (i = 0; i < str_nelems; i++) printf("%s ", str_data[i]);
    printf("\n");
}
void qsort(void* base, size_t nel, size_t width,
           int (*compar)(const void*, const void*));
which declares that compar is a function returning a pointer to an int, which is a different thing.int *compar(const void*, const void*));
int (*fn) (const char*, const struct stat*, int, struct FTW*)
int visit(const char* path, const struct stat* stat, int flags, struct FTW* ftw)
typedef int (* CompareFunc)(const void*, const void*); void qsort(void* base, size_t nel, size_t width, CompareFunc compar);
typedef int CompareFunc(const void*, const void*); void qsort(void* base, size_t nel, size_t width, CompareFunc* compar);
void qsort(void* base, size_t nel, size_t width, CompareFunc compar);
struct passwd {
        char    *pw_name;
        char    *pw_passwd;
        uid_t   pw_uid;
        gid_t   pw_gid;
        char    *pw_age;
        char    *pw_comment;
        char    *pw_gecos;
        char    *pw_dir;
        char    *pw_shell;
};
struct passwd *getpwnam(
    const char *name);
struct passwd *getpwuid(
    uid_t uid);
int uname(struct utsname *name);
struct utsname {
        char    sysname[_SYS_NMLN];
        char    nodename[_SYS_NMLN];
        char    release[_SYS_NMLN];
        char    version[_SYS_NMLN];
        char    machine[_SYS_NMLN];
};