Search code examples
ckernelsystem-callsmkdirminix

Modyifing existing do_mkdir() system call to print created folder that doesn't already exist


I'm trying to familiarize myself with modifying Minix system calls and rebuilding the kernel.

I modified mkdir to print New dir -> <directory-name> <permissions> every time it was called, unless the directory already existed.

I edited /usr/src/servers/vfs/open.c, which contains the code for mkdir. I added this line of code to line 610:

    printf("New dir -> %s %o",fullpath,dirmode);

With this edit, mkdir printed correctly, except that if the folder already existed, I was getting the following message:

New Dir -> test 755 mkdir: test: file exists

I expected to see:

mkdir: test: file exists

I thought that by adding the printf to the last if-else body near line 610, it would not execute in this case, since this if-else structure checks if the new directory is valid (inode, permissions, etc), and the call should return if the directory already exists. I was mistaken.

What system function or variable should I check to see if the file already exists?

My edited version of open.c.

I'm using Minix version 3.2.1.

To test this, I rebuilt just the kernel, like this:

cd /usr/src/releasetools
make hdboot

Solution

  • As suggested by the commenters, you need to check one more thing.

    The code near the section that you modified says:

    /* Make sure that the object is a directory */
    if (!S_ISDIR(vp->v_mode)) {
        r = ENOTDIR;
    } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
        r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
                      fp->fp_effgid, bits);
        printf("New dir -> %s %o",fullpath,dirmode);
    }
    

    The key here is that the branches check that the parent directory exists, and then check that the program has permission to create a new directory - but nothing about whether or not a directory already existed.

    That check is done as part of req_mkdir, which returns an error code for whether or not it succeeded. You would want to check this error code:

    /* Make sure that the object is a directory */
    if (!S_ISDIR(vp->v_mode)) {
        r = ENOTDIR;
    } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
        r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
                      fp->fp_effgid, bits);
        if (r == OK) {
            printf("New dir -> %s %o\n", fullpath, dirmode);
        }
    }
    

    While I was at it, I also added the missing newline to the end of the printf format string so that it doesn't get strung together with the next line.

    Disclaimer: I haven't actually tested this, and might have made a mistake.