doc: document file system
This commit is contained in:
parent
4b8036b192
commit
f2fdc0aada
|
@ -13,6 +13,7 @@ SRCS = kernel.asm \
|
||||||
isr.inc \
|
isr.inc \
|
||||||
pic.inc \
|
pic.inc \
|
||||||
idt.inc \
|
idt.inc \
|
||||||
|
heap.inc \
|
||||||
dev/console.inc \
|
dev/console.inc \
|
||||||
dev/at/pit.inc \
|
dev/at/pit.inc \
|
||||||
dev/at/cga.inc \
|
dev/at/cga.inc \
|
||||||
|
|
3
kernel/conf/devices
Normal file
3
kernel/conf/devices
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
console c 0 0
|
||||||
|
fd0 b 0 0
|
||||||
|
fd1 b 0 1
|
|
@ -49,25 +49,50 @@ floppy_strategy:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
floppy_open:
|
floppy_open:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
|
||||||
|
mov eax, [ebp+4]
|
||||||
|
cmp al, FLOPPY_MAX
|
||||||
|
jb @f
|
||||||
|
mov eax, ENXIO
|
||||||
|
jmp .end
|
||||||
|
@@:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
.end:
|
||||||
|
pop ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
floppy_close:
|
floppy_close:
|
||||||
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
floppy_ioctl:
|
floppy_ioctl:
|
||||||
mov eax, ENODEV
|
mov eax, ENODEV
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
floppy_dump:
|
||||||
|
ret
|
||||||
|
|
||||||
|
floppy_psize:
|
||||||
|
ret
|
||||||
|
|
||||||
floppy_irq:
|
floppy_irq:
|
||||||
iret
|
iret
|
||||||
|
|
||||||
floppy_device:
|
floppy_device:
|
||||||
db 'floppy', 0, 0
|
db 'floppy', 0, 0
|
||||||
dd floppy_init
|
dd floppy_init
|
||||||
db 0
|
db FLOPPY_BDEV_MAJOR
|
||||||
db 0
|
db FLOPPY_CDEV_MAJOR
|
||||||
|
|
||||||
szMsgFloppy0Found db "floppy0: Found", 0
|
floppy_blockdev:
|
||||||
szMsgFloppy1Found db "floppy1: Found", 0
|
dd floppy_open
|
||||||
|
dd floppy_strategy
|
||||||
|
dd floppy_ioctl
|
||||||
|
dd floppy_close
|
||||||
|
dd floppy_dump
|
||||||
|
dd floppy_psize
|
||||||
|
|
||||||
|
szMsgFloppy0Found db "floppy: fd0 found", 0
|
||||||
|
szMsgFloppy1Found db "floppy: fd1 found", 0
|
||||||
|
|
|
@ -28,6 +28,12 @@ kbd_init:
|
||||||
@@:
|
@@:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
kbd_open:
|
||||||
|
ret
|
||||||
|
|
||||||
|
kbd_close:
|
||||||
|
ret
|
||||||
|
|
||||||
kbd_getc:
|
kbd_getc:
|
||||||
in al, KBD_STATP
|
in al, KBD_STATP
|
||||||
and al, KBS_DIB
|
and al, KBS_DIB
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
;; File: console.inc
|
;; File: console.inc
|
||||||
console_probe:
|
|
||||||
ret
|
|
||||||
|
|
||||||
console_write:
|
console_write:
|
||||||
mov eax, uConsoleLock
|
mov eax, uConsoleLock
|
||||||
|
|
|
@ -7,7 +7,6 @@ DEFN Device
|
||||||
|
|
||||||
struc BlkDev {
|
struc BlkDev {
|
||||||
.open dd ?
|
.open dd ?
|
||||||
.close dd ?
|
|
||||||
.strategy dd ?
|
.strategy dd ?
|
||||||
.ioctl dd ?
|
.ioctl dd ?
|
||||||
.close dd ?
|
.close dd ?
|
||||||
|
|
2
kernel/fork.inc
Normal file
2
kernel/fork.inc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
fork:
|
||||||
|
ret
|
|
@ -1,7 +1,8 @@
|
||||||
;; File: fat.inc
|
;; File: fat.inc
|
||||||
;;
|
;;
|
||||||
|
;;
|
||||||
;; Usefull links:
|
;; Usefull links:
|
||||||
;; - <Spec at https://academy.cba.mit.edu/classes/networking_communications/SD/FAT.pdf>
|
;; - <Microsoft FAT Specification at https://academy.cba.mit.edu/classes/networking_communications/SD/FAT.pdf>
|
||||||
|
|
||||||
FAT_SECTOR_SIZE = 512
|
FAT_SECTOR_SIZE = 512
|
||||||
FAT_MDIR_SIZE = 32
|
FAT_MDIR_SIZE = 32
|
||||||
|
@ -59,6 +60,27 @@ struc FATFS_BootSector32 {
|
||||||
}
|
}
|
||||||
DEFN FATFS_BootSector32
|
DEFN FATFS_BootSector32
|
||||||
|
|
||||||
|
struc FATFS_Dirent {
|
||||||
|
.name db 8 dup(?)
|
||||||
|
.ext db 3 dup(?)
|
||||||
|
.attr db ?
|
||||||
|
.reserved db 0
|
||||||
|
.crt_time_tenth db ?
|
||||||
|
.crt_time dw ?
|
||||||
|
.crt_date dw ?
|
||||||
|
.lst_acc_date dw ?
|
||||||
|
.fst_clus_hi dw ?
|
||||||
|
.wrt_time dw ?
|
||||||
|
.wrt_date dw ?
|
||||||
|
.fst_clus_lo dw ?
|
||||||
|
.file_size dd ?
|
||||||
|
}
|
||||||
|
DEFN FATFS_Dirent
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
;; Section: Implementation
|
||||||
|
|
||||||
szVfsFatName db 'FATFS', 0
|
szVfsFatName db 'FATFS', 0
|
||||||
|
|
||||||
vfs_fatfs:
|
vfs_fatfs:
|
||||||
|
|
|
@ -1,27 +1,86 @@
|
||||||
;; File: stpdfs.inc
|
;; File: stpdfs.inc
|
||||||
|
;;
|
||||||
|
;; > ┌──────────┬───────────┬──────┬───┬──────┬────┬───┬────┐
|
||||||
|
;; > │Boot block│Super block│Inodes│...│Inodes│Data│...│Data│
|
||||||
|
;; > └──────────┴───────────┴──────┴───┴──────┴────┴───┴────┘
|
||||||
|
|
||||||
|
;; Constant: STPDFS_SB_MAGIC
|
||||||
|
;; Superblock magic number, MUST BE `0x44505453` (STPD)
|
||||||
STPDFS_SB_MAGIC = 0x44505453
|
STPDFS_SB_MAGIC = 0x44505453
|
||||||
|
;; Constant: STPDFS_SB_REV
|
||||||
|
;; StupidFS revision, currently `0x1`
|
||||||
STPDFS_SB_REV = 1
|
STPDFS_SB_REV = 1
|
||||||
|
;; Constant: STPDFS_BSIZE
|
||||||
|
;; StupidFS block size (512)
|
||||||
STPDFS_BSIZE = 512
|
STPDFS_BSIZE = 512
|
||||||
|
;; Constant: STPDFS_BADINO
|
||||||
|
;; StupidFS bad inode
|
||||||
|
STPDBOOT_BADINO = 0
|
||||||
|
;; Constant: STPDFS_ROOTINO
|
||||||
|
;; StupidFS root inode
|
||||||
STPDFS_ROOTINO = 1
|
STPDFS_ROOTINO = 1
|
||||||
|
;; Constant: STPDFS_NDIRECT
|
||||||
STPDFS_NDIRECT = 7
|
STPDFS_NDIRECT = 7
|
||||||
|
;; Constant: STPDFS_NAME_MAX
|
||||||
|
STPDFS_NAME_MAX = 28
|
||||||
|
|
||||||
|
;; Enum: StupidFS State
|
||||||
|
;; STPDFS_CLEANLY_UNMOUNTED - 0
|
||||||
|
;; STPDFS_ERROR - 1
|
||||||
|
;; STPDFS_DIRTY - 1
|
||||||
STPDFS_CLEANLY_UNMOUNTED = 0
|
STPDFS_CLEANLY_UNMOUNTED = 0
|
||||||
STPDFS_ERROR = 1
|
STPDFS_ERROR = 1
|
||||||
STPDFS_DIRTY = 1
|
STPDFS_DIRTY = 1
|
||||||
|
|
||||||
|
;; Struc: StpdFS_FreeList
|
||||||
|
;;
|
||||||
|
;; > ┌──────────┐
|
||||||
|
;; > │ block 99 │
|
||||||
|
;; > ├──────────┤
|
||||||
|
;; > │ block 98 │
|
||||||
|
;; > ├──────────┤
|
||||||
|
;; > │ ... │
|
||||||
|
;; > ├──────────┤
|
||||||
|
;; > │ block 2 │
|
||||||
|
;; > ├──────────┤
|
||||||
|
;; > │ block 1 │
|
||||||
|
;; > ├──────────┤ ┌──────────┐
|
||||||
|
;; > │ block 0 ├───►│ block 99 │
|
||||||
|
;; > └──────────┘ ├──────────┤
|
||||||
|
;; > │ ... │
|
||||||
|
;; > ├──────────┤ ┌──────────┐
|
||||||
|
;; > │ block 0 ├───►│ block 99 │
|
||||||
|
;; > └──────────┘ ├──────────┤
|
||||||
|
;; > │ ... │
|
||||||
|
;; > ├──────────┤
|
||||||
|
;; > │ block 0 │
|
||||||
|
;; > └──────────┘
|
||||||
|
;;
|
||||||
|
struc StpdFS_FreeList {
|
||||||
|
.free dd 100 dup(?)
|
||||||
|
.nfree db ?
|
||||||
|
}
|
||||||
|
|
||||||
|
;; Struc: StpdFS_Sb
|
||||||
|
;; .magic - See <STPDFS_SB_MAGIC>
|
||||||
|
;; .isize - Size in block of the i-node list
|
||||||
|
;; .fsize - Size in block of the entire volume
|
||||||
|
;; .freelist - See <StpdFS_FreeList>
|
||||||
|
;; .rev - See <STPDFS_SB_REV>
|
||||||
|
;; .state - See <StupidFS State>
|
||||||
|
;; .time - Last access time (64bit UNIX timestamp)
|
||||||
struc StpdFS_Sb {
|
struc StpdFS_Sb {
|
||||||
.magic dd ?
|
.magic dd ?
|
||||||
.isize dd ?
|
.isize dd ?
|
||||||
.fsize dd ?
|
.fsize dd ?
|
||||||
.free dd 100 dup(?)
|
.freelist StpdFS_FreeList
|
||||||
.nfree db ?
|
|
||||||
.rev db ?
|
.rev db ?
|
||||||
.state dw ?
|
.state dw ?
|
||||||
.time dq ?
|
.time dq ?
|
||||||
}
|
}
|
||||||
DEFN StpdFS_Sb
|
DEFN StpdFS_Sb
|
||||||
|
|
||||||
|
;; Struc: StpdFS_Inode
|
||||||
struc StpdFS_Inode {
|
struc StpdFS_Inode {
|
||||||
.mode dw ?
|
.mode dw ?
|
||||||
.nlink dw ?
|
.nlink dw ?
|
||||||
|
@ -35,6 +94,22 @@ struc StpdFS_Inode {
|
||||||
}
|
}
|
||||||
DEFN StpdFS_Inode
|
DEFN StpdFS_Inode
|
||||||
|
|
||||||
|
;; Struc: StpdFS_Dirent
|
||||||
|
;; StupidFS dir entry
|
||||||
|
;;
|
||||||
|
;; .inode - address of i-node
|
||||||
|
;; .name - null terminated file name (see <STPDFS_NAME_MAX>)
|
||||||
|
struc StpdFS_Dirent {
|
||||||
|
.inode dd ?
|
||||||
|
.name db STPDFS_NAME_MAX dup(?)
|
||||||
|
}
|
||||||
|
DEFN StpdFS_Dirent
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
;; Section: Implementation
|
||||||
|
|
||||||
|
|
||||||
szVfsStpdFSName db 'StupidFS', 0
|
szVfsStpdFSName db 'StupidFS', 0
|
||||||
|
|
||||||
vops_stpdfs:
|
vops_stpdfs:
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
;; File: xv6fs.inc
|
;; File: xv6fs.inc
|
||||||
;;
|
;;
|
||||||
|
;; > ┌──────────┬───────────┬───┬───┬───┬──────┬───┬──────┬──────┬───┬──────┬────┬───┬────┐
|
||||||
|
;; > │Boot block│Super block│Log│...│Log│Inodes│...│Inodes│Bitmap│...│Bitmap│Data│...│Data│
|
||||||
|
;; > └──────────┴───────────┴───┴───┴───┴──────┴───┴──────┴──────┴───┴──────┴────┴───┴────┘
|
||||||
|
;;
|
||||||
;; Usefull links:
|
;; Usefull links:
|
||||||
;; - <https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/fs.h>
|
;; - <https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/fs.h>
|
||||||
;; - <xv6 book at https://pdos.csail.mit.edu/6.1810/2023/xv6/book-riscv-rev3.pdf>
|
;; - <xv6 book at https://pdos.csail.mit.edu/6.1810/2023/xv6/book-riscv-rev3.pdf>
|
||||||
|
|
||||||
|
;; Constant: XV6FS_BSIZE
|
||||||
|
;; xv6 Filesystem block size (1024)
|
||||||
XV6FS_BSIZE = 1024
|
XV6FS_BSIZE = 1024
|
||||||
XV6FS_ROOTINO = 1
|
XV6FS_ROOTINO = 1
|
||||||
XV6FS_MAGIC = 0x10203040
|
XV6FS_MAGIC = 0x10203040
|
||||||
|
@ -13,6 +19,7 @@ XV6FS_MAXFILE = (XV6FS_NDIRECT + XV6FS_NINDIRECT)
|
||||||
XV6FS_IPB = (XV6FS_BSIZE / 64)
|
XV6FS_IPB = (XV6FS_BSIZE / 64)
|
||||||
XV6FS_DIRSIZE = 14
|
XV6FS_DIRSIZE = 14
|
||||||
|
|
||||||
|
;; Struc: Xv6FS_Sb
|
||||||
struc Xv6FS_Sb {
|
struc Xv6FS_Sb {
|
||||||
.magic dd ?
|
.magic dd ?
|
||||||
.size dd ?
|
.size dd ?
|
||||||
|
@ -25,6 +32,7 @@ struc Xv6FS_Sb {
|
||||||
}
|
}
|
||||||
DEFN Xv6FS_Sb
|
DEFN Xv6FS_Sb
|
||||||
|
|
||||||
|
;; Struc: Xv6FS_Inode
|
||||||
struc Xv6FS_Inode {
|
struc Xv6FS_Inode {
|
||||||
.type dw ?
|
.type dw ?
|
||||||
.major dw ?
|
.major dw ?
|
||||||
|
@ -35,11 +43,17 @@ struc Xv6FS_Inode {
|
||||||
}
|
}
|
||||||
DEFN Xv6FS_Inode
|
DEFN Xv6FS_Inode
|
||||||
|
|
||||||
|
;; Struc: Xv6FS_Dirent
|
||||||
struc Xv6FS_Dirent {
|
struc Xv6FS_Dirent {
|
||||||
.inum dw ?
|
.inum dw ?
|
||||||
.name db XV6FS_DIRSIZE dup(?)
|
.name db XV6FS_DIRSIZE dup(?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
;; Section: Implementation
|
||||||
|
|
||||||
|
|
||||||
szVfsXv6FSName db 'xv6FS', 0
|
szVfsXv6FSName db 'xv6FS', 0
|
||||||
|
|
||||||
vops_xv6fs:
|
vops_xv6fs:
|
||||||
|
|
27
kernel/heap.inc
Normal file
27
kernel/heap.inc
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
;; File: heap.inc
|
||||||
|
|
||||||
|
;; Function: heap_init
|
||||||
|
heap_init:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
sub esp, 4
|
||||||
|
mov [ebp-4], eax
|
||||||
|
mov ecx, KERNEL_VIRT_BASE
|
||||||
|
add eax, ecx
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
mov esi, szMsgHeapInit
|
||||||
|
call klog
|
||||||
|
|
||||||
|
; TODO
|
||||||
|
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
|
||||||
|
heap_alloc:
|
||||||
|
ret
|
||||||
|
|
||||||
|
heap_free:
|
||||||
|
ret
|
||||||
|
|
||||||
|
szMsgHeapInit db "HEAP: initialize %x - %x", 0
|
|
@ -6,15 +6,13 @@
|
||||||
include 'sys/bootinfo.inc'
|
include 'sys/bootinfo.inc'
|
||||||
include 'sys/cpu.inc'
|
include 'sys/cpu.inc'
|
||||||
include 'sys/errno.inc'
|
include 'sys/errno.inc'
|
||||||
|
include 'sys/process.inc'
|
||||||
|
|
||||||
org KBASE
|
org KBASE
|
||||||
use32
|
use32
|
||||||
|
|
||||||
jmp short kmain
|
jmp short kmain
|
||||||
|
|
||||||
db 'STPDKRNL'
|
|
||||||
db 32 dup(0)
|
|
||||||
|
|
||||||
;; Function: kmain
|
;; Function: kmain
|
||||||
;;
|
;;
|
||||||
;; Parameters:
|
;; Parameters:
|
||||||
|
@ -56,6 +54,9 @@ kmain:
|
||||||
add ebx, KERNEL_VIRT_BASE
|
add ebx, KERNEL_VIRT_BASE
|
||||||
call pmm_free_range
|
call pmm_free_range
|
||||||
|
|
||||||
|
mov eax, [boot_structure.low_mem]
|
||||||
|
call heap_init
|
||||||
|
|
||||||
call pic_init
|
call pic_init
|
||||||
|
|
||||||
; clear tss
|
; clear tss
|
||||||
|
@ -109,6 +110,7 @@ kmain:
|
||||||
include 'isr.inc'
|
include 'isr.inc'
|
||||||
include 'idt.inc'
|
include 'idt.inc'
|
||||||
include 'pic.inc'
|
include 'pic.inc'
|
||||||
|
include 'heap.inc'
|
||||||
include 'vfs.inc'
|
include 'vfs.inc'
|
||||||
include 'fs/fat.inc'
|
include 'fs/fat.inc'
|
||||||
include 'fs/stpdfs.inc'
|
include 'fs/stpdfs.inc'
|
||||||
|
|
|
@ -14,6 +14,7 @@ struc BootInfo {
|
||||||
.kernel_start dd ?
|
.kernel_start dd ?
|
||||||
.kernel_size dd ?
|
.kernel_size dd ?
|
||||||
.high_mem dd ?
|
.high_mem dd ?
|
||||||
|
.low_mem dd ?
|
||||||
}
|
}
|
||||||
virtual at 0
|
virtual at 0
|
||||||
BootInfo BootInfo
|
BootInfo BootInfo
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
|
ENXIO = 6
|
||||||
ENODEV = 19
|
ENODEV = 19
|
||||||
|
|
27
kernel/sys/process.inc
Normal file
27
kernel/sys/process.inc
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
struc ProcessGroup {
|
||||||
|
}
|
||||||
|
|
||||||
|
struc Context {
|
||||||
|
.flags dd ?
|
||||||
|
.regs dd ?
|
||||||
|
}
|
||||||
|
|
||||||
|
struc Process {
|
||||||
|
.pagedir dd ?
|
||||||
|
.parent dd ?
|
||||||
|
.context Context
|
||||||
|
.next dd ?
|
||||||
|
}
|
||||||
|
|
||||||
|
PROCESS_STATE_IDL = 0
|
||||||
|
PROCESS_STATE_RUN = 1
|
||||||
|
PROCESS_STATE_SLEEP = 2
|
||||||
|
PROCESS_STATE_STOP = 3
|
||||||
|
PROCESS_STATE_ZOMBIE = 4
|
||||||
|
|
||||||
|
PZERO = 22
|
||||||
|
PWAIT = 24
|
||||||
|
PLOCK = 36
|
||||||
|
PPAUSE = 40
|
||||||
|
PUSER = 50
|
|
@ -1,71 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
static char *prg_name;
|
|
||||||
|
|
||||||
struct kernel_header {
|
|
||||||
uint8_t jump[3];
|
|
||||||
uint8_t magic[8];
|
|
||||||
uint8_t signature[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_keygen()
|
|
||||||
{
|
|
||||||
uint8_t pk[crypto_sign_ed25519_PUBLICKEYBYTES];
|
|
||||||
uint8_t sk[crypto_sign_ed25519_SECRETKEYBYTES];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(int retcode)
|
|
||||||
{
|
|
||||||
if (retcode == EXIT_FAILURE)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Try '%s -h' form more information.\n", prg_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Usage: %s [-hV] [sign|verify|keygen]\n", prg_name);
|
|
||||||
printf("\t-h\tdisplay this help and exit\n");
|
|
||||||
printf("\t-V\toutput version information\n");
|
|
||||||
|
|
||||||
printf("\nReport bugs to <%s>\n", MK_BUGREPORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(retcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
version(void)
|
|
||||||
{
|
|
||||||
printf("%s commit %s\n", prg_name, MK_COMMIT);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
prg_name = argv[0];
|
|
||||||
|
|
||||||
if (sodium_init() < 0) abort();
|
|
||||||
|
|
||||||
while ((argc > 1) && (argv[1][0] == '-'))
|
|
||||||
{
|
|
||||||
switch (argv[1][1])
|
|
||||||
{
|
|
||||||
case 'h':
|
|
||||||
usage(EXIT_SUCCESS);
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
version();
|
|
||||||
}
|
|
||||||
|
|
||||||
argv++;
|
|
||||||
argc--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc <= 1) usage(EXIT_FAILURE);
|
|
||||||
|
|
||||||
return (EXIT_SUCCESS);
|
|
||||||
}
|
|
|
@ -107,7 +107,7 @@ main(int argc, char **argv)
|
||||||
c = argv[1][2] - '0';
|
c = argv[1][2] - '0';
|
||||||
argv++;
|
argv++;
|
||||||
argc--;
|
argc--;
|
||||||
if (c != 0 && c != 1 && c != 2 && c != 3)
|
if (c < 0 && c > 3)
|
||||||
{
|
{
|
||||||
usage(EXIT_FAILURE);
|
usage(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue