#include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #ifdef HAVE_LIBGEN_H # include #endif /* HAVE_LIBGEN_H */ #ifdef HAVE_GETOPT_H # include #endif /* HAVE_GETOPT_H */ static const char *prg_name; static int inodes = -1; static const char *device; static int blocks = -1; static int bootable = 0; static struct stpdfs_sb super; extern const char _binary_mkfs_boot_o_start[]; extern const char _binary_mkfs_boot_o_end[]; #ifdef HAVE_STRUCT_OPTION static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"boot", no_argument, 0, 'b'}, {"inodes", required_argument, 0, 'i'}, {0, 0, 0, 0} }; #endif /* HAVE_STRUCT_OPTION */ static void usage(int retval) { if (retval == EXIT_FAILURE) { fprintf(stderr, "Try '%s -h' for more information.\n", prg_name); } else { printf("Usage: %s [options] /dev/name [blocks]\n\n", prg_name); printf("Options:\n"); printf(" -b, --boot make filesystem bootable\n"); printf(" -i, --inode number of inodes for the filesystem\n"); printf(" -h, --help display this help\n"); printf(" -V, --version display version\n\n"); printf("For more details see mkfs.stpd(8).\n"); } exit(retval); } static void version(void) { printf("%s (%s) %s\n", prg_name, PACKAGE_NAME, PACKAGE_VERSION); exit(EXIT_SUCCESS); } static int write_block(int fd, void *data, size_t size) { uint8_t buffer[STPDFS_BLOCK_SIZE]; memset(buffer, 0, STPDFS_BLOCK_SIZE); if (data) { memcpy(buffer, data, size); } return (write(fd, buffer, STPDFS_BLOCK_SIZE) == STPDFS_BLOCK_SIZE); } static int mkfs() { struct stat statbuf; struct stpdfs_dirent rootdirent[2]; int fd; int dev_block; int idx; struct stpdfs_inode inds[STPDFS_INODES_PER_BLOCK]; struct stpdfs_free freebuff; int freeblock; int nextfree; if (stat(device, &statbuf) < 0) { perror(device); return (EXIT_FAILURE); } fd = open(device, O_RDWR); if (fd < 0) { perror(device); return (EXIT_FAILURE); } dev_block = statbuf.st_size / STPDFS_BLOCK_SIZE; printf("device blocks: %d\n", dev_block); if (blocks < 0) { blocks = dev_block; } if (inodes <= 0) { if (512 * 1024 < blocks) { inodes = blocks / 8; } else { inodes = blocks / 3; } } super.magic = STPDFS_SB_MAGIC; super.revision = STPDFS_SB_REV; super.isize = inodes / STPDFS_INODES_PER_BLOCK; super.fsize = blocks; super.freelist.nfree = 0; /* write inodes */ lseek(fd, 2 * STPDFS_BLOCK_SIZE, SEEK_SET); memset(&inds, 0, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK); for (idx = 0; idx < super.isize; idx++) { if (write_block(fd, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK)); } /* set free blocks */ freeblock = blocks - (inodes + 2); for (nextfree = super.isize + 3; nextfree < freeblock; nextfree++) { if (stpdfs_free_block(fd, &super, nextfree) != 0) { fprintf(stderr, "error: %u\n", nextfree); } } /* create root dir */ stpdfs_read(fd, 2, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK); inds[STPDFS_ROOTINO].modtime = time(NULL); inds[STPDFS_ROOTINO].actime = time(NULL); inds[STPDFS_ROOTINO].size = sizeof(struct stpdfs_dirent) * 2; inds[STPDFS_ROOTINO].flags = STPDFS_INO_FLAG_ALOC; inds[STPDFS_ROOTINO].mode = STPDFS_S_IFDIR | STPDFS_S_IRUSR | STPDFS_S_IWUSR | STPDFS_S_IXUSR | STPDFS_S_IRGRP | STPDFS_S_IXGRP | STPDFS_S_IXOTH; inds[STPDFS_ROOTINO].zones[0] = stpdfs_alloc_block(fd, &super); inds[STPDFS_ROOTINO].size = sizeof(struct stpdfs_dirent) * 2; stpdfs_read(fd, inds[STPDFS_ROOTINO].zones[0], rootdirent, sizeof(struct stpdfs_dirent) * 2); strcpy(rootdirent[0].filename, "."); rootdirent[1].inode = 1; strcpy(rootdirent[1].filename, ".."); rootdirent[1].inode = 1; inds[STPDFS_ROOTINO].nlink += 2; stpdfs_write(fd, inds[STPDFS_ROOTINO].zones[0], rootdirent, sizeof(struct stpdfs_dirent) * 2); stpdfs_write(fd, 2, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK); /* write super block */ super.time = time(NULL); super.state = STPDFS_CLEANLY_UNMOUNTED; stpdfs_write(fd, 1, &super, sizeof(struct stpdfs_sb)); if (bootable) { stpdfs_write(fd, 0, (void *)_binary_mkfs_boot_o_start, STPDFS_BLOCK_SIZE); } /* we finished \o/ */ printf("StupidFS: %u blocks (%u Inodes)\n", super.fsize, super.isize); close(fd); return (EXIT_SUCCESS); } int main(int argc, char **argv) { int idx; int c; #ifdef HAVE_LIBGEN_H prg_name = basename(argv[0]); #else prg_name = argv[0]; #endif /* HAVE_LIBGEN_H */ #if defined(HAVE_GETOPT_LONG) && defined(HAVE_STRUCT_OPTION) while ((c = getopt_long(argc, argv, "hVbi:", long_options, &idx)) != EOF) #else while ((c = getopt(argc, argv, "hVbi:")) != EOF) #endif /* HAVE_GETOPT_LONG && HAVE_STRUCT_OPTION */ { switch (c) { case 'h': usage(EXIT_SUCCESS); break; case 'V': version(); break; case 'b': bootable = 1; break; case 'i': inodes = atoi(optarg); break; default: usage(EXIT_FAILURE); break; } } if (optind >= argc) { usage(EXIT_FAILURE); } device = argv[optind++]; if (optind < argc) { blocks = atoi(argv[optind]); } return (mkfs()); }