Search code examples
cfiledirectorymknod

Why are directory files not read using fread?


I was going through an example from Maurice Bach's Unix Book. He writes a simple copy program like mentioned below. However it fails when the inputfile is a directory file. I did stumble upon opendir and few other such API's - should I use that?

If a binary file can work with this, why is directory file considered different? In Unix, isn't everything abstracted as a file regardless of the way it is interpreted by the program.

Also how can I extend this program to support directory file and then create a mknod of that? I want to test this, suppose I am in /home/user1 and do a $./copy /home/user user-home-clone and mknod it to see how that directory will be different from home. I guess that the user-home-clone might not have a reference to itself, but all the other files in /home/user [ even though it would a file called user-home-clone would be there in /home/user ] since it was not there when we did the copy command?

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

char buffer[2048];

int copy(FILE *source, FILE *destination)
{
    int count;
    while ((count = fread(buffer, 1, sizeof buffer , source)) > 0)
    {
        fwrite(buffer, 1, count, destination);
    }
    return 0;
}

int main(int argc, char* argv[])
{
    int status;
    FILE *source;
    FILE *destination;

    if (argc != 3)
    {
        printf("%s takes exactly 3 arguments\n", argv[0]);
        exit(1);
    }
    source = fopen(argv[1], "r");
    if (source == NULL)
    {
        printf("%s can't  be opened for reading\n", argv[1]);
        exit(1);
    }
    destination = fopen(argv[2], "wb");
    if (destination == NULL)
    {
        printf("%s can't  be opened for writing\n", argv[2]);
        exit(1);
    }
    if (copy(source, destination) == 0)
    {
        status = 0;
    }
    else
    {
        status = 1;
    }

    fclose(source);
    fclose(destination);
    exit(status);
}

I use Centos 6.5 Linux Ext4 Filesystem


Solution

  • In early versions of Unix, directory files could be read as binary files. However, when network and other types of virtual filesystems were added, this ability was removed, because different filesystems implement directories differently. While it would be technically possible for the driver to emulate a byte stream structure for these directories, it wasn't seen as a useful feature. Directories should be treated as opaque, abstract collections, and accessed using the directory-specific functions.