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?
I'm using Minix version 3.2.1.
To test this, I rebuilt just the kernel, like this:
cd /usr/src/releasetools
make hdboot
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.