3

I'm working on a project where I must open a directory and read the files/directories inside at kernel level. I'm basically trying to find out how ls is implemented at kernel level.

Right now I've figured out how to get a file descriptor for a directory using sys_open() and the O_DIRECTORY flag, but I don't know how to read the fd that I receive. If anyone has any tips or other suggestions I'd appreciate it. (Keep in mind this has to be done at kernel level).

Edit:For a long story short, For a school project I am implementing file/directory attributes. Where I'm storring the attributes is a hidden folder at the same level of the file with a given attribute. (So a file in Desktop/MyFolder has an attributes folder called Desktop/MyFolder/.filename_attr). Trust me I don't care to mess around in kernel for funsies. But the reason I need to read a dir at kernel level is because it's apart of project specs.

NuGy
  • 37
  • 1
  • 10

2 Answers2

5

To add to caf's answer mentioning vfs_readdir(), reading and writing to files from within the kernel is is considered unsafe (except for /proc, which acts as an interface to internal data structures in the kernel.)

The reasons are well described in this linuxjournal article, although they also provide a hack to access files. I don't think their method could be easily modified to work for directories. A more correct approach is accessing the kernel's filesystem inode entries, which is what vfs_readdir does.

Inodes are filesystem objects such as regular files, directories, FIFOs and other beasts. They live either on the disc (for block device filesystems) or in the memory (for pseudo filesystems).

Notice that vfs_readdir() expects a file * parameter. To obtain a file structure pointer from a user space file descriptor, you should utilize the kernel's file descriptor table.

The kernel.org files documentation says the following on doing so safely:

To look up the file structure given an fd, a reader must use either fcheck() or fcheck_files() APIs. These take care of barrier requirements due to lock-free lookup. An example :

    rcu_read_lock();
    file = fcheck_files(files, fd);
    if (file) {
        // Handling of the file structures is special. 
        // Since the look-up of the fd (fget() / fget_light()) 
        // are lock-free, it is possible that look-up may race with 
        // the last put() operation on the file structure. 
        // This is avoided using atomic_long_inc_not_zero() on ->f_count
        if (atomic_long_inc_not_zero(&file->f_count))
            *fput_needed = 1;
        else
        /* Didn't get the reference, someone's freed */
            file = NULL;
    }
    rcu_read_unlock();
    ....
    return file;

atomic_long_inc_not_zero() detects if refcounts is already zero or goes to zero during increment. If it does, we fail fget() / fget_light().

Finally, take a look at filldir_t, the second parameter type.

Rob
  • 5,223
  • 5
  • 41
  • 62
4

You probably want vfs_readdir() from fs/readdir.c.

In general though kernel code does not read directories, user code does.

caf
  • 233,326
  • 40
  • 323
  • 462