blob: 3a3c7441cc123d7f1dadc27ad3a405a1f9b3719c [file] [log] [blame] [raw]
/* mknod - toolbox
Copyright 2015-2021 Rivoreo
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include "str2mode.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef makedev
#ifdef __GLIBC__
#include <sys/sysmacros.h>
#else
#include <sys/mkdev.h>
#endif
#ifndef makedev
#define makedev mkdev
#endif
#endif
static void print_usage(const char *name) {
fprintf(stderr, "Usage: %s [{-m|--mode} <mode>] <name> <type> [<major> <minor>]\n", name);
}
int mknod_main(int argc, char **argv) {
int i = 1;
mode_t mode = 0777;
int set_mode(const char *option) {
const char *m = argv[i + 1];
if(!m) {
fprintf(stderr, "%s: Option '%s' requires an argument\n", argv[0], option);
return -1;
}
mode = STR2MODE(m);
if(mode == (mode_t)-1) {
fprintf(stderr, "%s: Bad mode\n", argv[0]);
return -1;
}
umask(0);
int j;
argc -= 2;
for(j=i; j<argc+1; j++) argv[j] = argv[j + 2];
return 0;
}
first_loop:
while(i < argc) {
if(argv[i][0] == '-') {
const char *o = argv[i] + 1;
while(*o) switch(*o++) {
case 'm':
if(set_mode("-m") < 0) return -2;
goto first_loop;
case 'h':
print_usage(argv[0]);
return 0;
case '-':
if(*o) {
if(strcmp(o, "mode") == 0) {
if(set_mode("--mode") < 0) return -2;
goto first_loop;
} else if(strcmp(o, "help") == 0) {
print_usage(argv[0]);
return 0;
} else {
fprintf(stderr, "%s: Invalid option '--%s'\n", argv[0], o);
return -1;
}
} else goto options_parse_end;
break;
default:
fprintf(stderr, "%s: Invalid option '-%c'\n", argv[0], o[-1]);
return -1;
}
}
i++;
}
options_parse_end:
if(argc < 3) {
print_usage(argv[0]);
return -1;
}
if(!argv[2][0] || argv[2][1]) {
fprintf(stderr, "%s: The type takes only one character\n", argv[0]);
return 1;
}
switch(*(argv[2])) {
case 'b':
mode |= S_IFBLK;
break;
case 'c':
mode |= S_IFCHR;
break;
case 'p':
mode |= S_IFIFO;
break;
default:
fprintf(stderr, "%s: Invalid type '%c'\n", argv[0], *(argv[2]));
return 1;
}
dev_t dev = 0;
if(S_ISBLK(mode) || S_ISCHR(mode)) {
if(argc < 5) {
fprintf(stderr, "%s: Missing major and minor for type '%c'\n", argv[0], *(argv[2]));
return 2;
} else if(argc > 5) {
fprintf(stderr, "%s: Too many operand for type '%c'\n", argv[0], *(argv[2]));
return 2;
}
dev = makedev(strtoul(argv[3], NULL, 0), strtoul(argv[4], NULL, 0));
} else if(argc > 3) {
fprintf(stderr, "%s: Too many operand for type 'p'\n", argv[0]);
return 2;
}
if(mknod(argv[1], mode, dev) < 0) {
perror(argv[1]);
return 3;
}
return 0;
}