in fs/extfs/extfs.cpp [582:666]
static int do_ext2fs_mknod(ext2_filsys fs, const char *path, unsigned int st_mode, unsigned int st_rdev) {
ext2_ino_t parent, ino;
errcode_t ret = 0;
unsigned long devmajor, devminor;
int filetype;
DEFER(LOG_DEBUG("mknod ", VALUE(path), VALUE(parent), VALUE(ino), VALUE(ret)));
ino = string_to_inode(fs, path, 0);
if (ino) {
return -(ret = EEXIST);
}
parent = get_parent_dir_ino(fs, path);
if (parent == 0) {
return -(ret = ENOTDIR);
}
char *filename = get_filename(path);
if (filename == nullptr) {
return -(ret = EISDIR);
}
switch (st_mode & S_IFMT) {
case S_IFCHR:
filetype = EXT2_FT_CHRDEV;
break;
case S_IFBLK:
filetype = EXT2_FT_BLKDEV;
break;
case S_IFIFO:
filetype = EXT2_FT_FIFO;
break;
#ifndef _WIN32
case S_IFSOCK:
filetype = EXT2_FT_SOCK;
break;
#endif
default:
return EXT2_ET_INVALID_ARGUMENT;
}
ret = ext2fs_new_inode(fs, parent, 010755, 0, &ino);
if (ret) return parse_extfs_error(fs, 0, ret);
ret = ext2fs_link(fs, parent, filename, ino, filetype);
if (ret == EXT2_ET_DIR_NO_SPACE) {
ret = ext2fs_expand_dir(fs, parent);
if (ret) return parse_extfs_error(fs, parent, ret);
ret = ext2fs_link(fs, parent, filename, ino, filetype);
}
if (ret) return parse_extfs_error(fs, parent, ret);
if (ext2fs_test_inode_bitmap2(fs->inode_map, ino))
LOG_WARN("Warning: inode already set");
ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
struct ext2_inode inode;
memset(&inode, 0, sizeof(inode));
inode.i_mode = st_mode;
#ifndef NO_TIMESTAMP
inode.i_atime = inode.i_ctime = inode.i_mtime =
fs->now ? fs->now : time(0);
#endif
if (filetype != S_IFIFO) {
devmajor = major(st_rdev);
devminor = minor(st_rdev);
if ((devmajor < 256) && (devminor < 256)) {
inode.i_block[0] = devmajor * 256 + devminor;
inode.i_block[1] = 0;
} else {
inode.i_block[0] = 0;
inode.i_block[1] = (devminor & 0xff) | (devmajor << 8) |
((devminor & ~0xff) << 12);
}
}
inode.i_links_count = 1;
ret = ext2fs_write_new_inode(fs, ino, &inode);
if (ret) return parse_extfs_error(fs, ino, ret);
return 0;
}