Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 21728285a6 | |||
| 636f8c68c5 | |||
| 50569ed1c8 | |||
| 81ca704adb | |||
| a4091ca57b | |||
| 57bd59bb43 | |||
| f687b89c74 | |||
| 0347054fae | |||
| 2df2f34f22 | |||
| 9bb19e22be | |||
| 2644a07f66 | |||
| c8db92b7b7 | |||
| 082ea79648 | |||
| 272a246e29 | |||
| 67223d0edf | |||
| e4e740c1c5 | |||
| d213be2bcf | |||
| 2ab2dd8a11 | |||
| f4f57e0750 | |||
| 548feeaf7d | |||
| 761abc0172 | |||
| 61024ac3f3 | |||
| 9ee6421e1b | |||
| 79a9897a61 | |||
| 0b1bc2844b | |||
| f538920b24 | |||
| 152f141d5a | |||
| 61824151fb | |||
| 9950584c12 | |||
| 113e902a62 | |||
| 91e1a116c7 | |||
| e67aced2c0 | |||
| 179a301c40 | |||
| fb1a6fcf15 | |||
| 9bb52a8494 | |||
| bd864fe384 | |||
| 3bf6119030 | |||
| dba41a3719 | |||
| b149807ccc | |||
| 43c5bbaaff | |||
| 9f0d8eca0d | |||
| 9de28df51a | |||
| 58ceead501 | |||
| 1a6a590eee | |||
| cf8781398d | |||
| 2d8350f732 | |||
| b79f768a0f | |||
| 45229810be | |||
| 670320df13 | |||
| f088eb4058 | |||
| 7b6076b612 | |||
| d213276817 | |||
| ed7454f1e0 | |||
| 806664f61c | |||
| 8852d09693 | |||
| 8262982e87 | |||
| fbff702922 | |||
| cd60f1602e | |||
| 354470b85b | |||
| 43054529d5 | |||
| fe4c4e337e | |||
| 63b8d9420a | |||
| 7b54ff8d2a | |||
| 65393843a5 | |||
| afa3d4fb66 | |||
| f124be1cf7 | |||
| 88b1846a43 | |||
| 8e1696d701 | |||
| ebd07576fa | |||
| ce99aff26b | |||
| 5b4c3bb0f4 | |||
| 53d1e8ad68 | |||
| ed50926b46 | |||
| bc0c921316 | |||
| 189f2ceb77 | |||
| e31e40ba2e | |||
| ce9d95e4e8 |
+164
-165
@@ -16,184 +16,183 @@ If the column is empty it means that it's not implemented yet.
|
||||
```
|
||||
S | EAX | Name | Source | EBX | ECX | EDX | ESX | EDI |
|
||||
---+-----+----------------------------+-----------------------------+--------------------------+------------------------------+-------------------------+-----------------+------------------|
|
||||
2 | 1 | sys_exit | kernel/exit.c | int | - | - | - | - |
|
||||
2 | 2 | sys_fork | arch/i386/kernel/process.c | struct pt_regs | - | - | - | - |
|
||||
2 | 1 | sys_exit | process/scheduler.c | int | - | - | - | - |
|
||||
2 | 2 | sys_fork | process/process.c | struct pt_regs | - | - | - | - |
|
||||
2 | 3 | sys_read | fs/read_write.c | unsigned int | char * | size_t | - | - |
|
||||
2 | 4 | sys_write | fs/read_write.c | unsigned int | const char * | size_t | - | - |
|
||||
2 | 5 | sys_open | fs/open.c | const char * | int | int | - | - |
|
||||
2 | 6 | sys_close | fs/open.c | int | - | - | - | - |
|
||||
2 | 7 | sys_waitpid | kernel/exit.c | pid_t | unsigned int * | int | - | - |
|
||||
2 | 8 | sys_creat | fs/open.c | const char * | int | - | - | - |
|
||||
| 9 | sys_link | fs/namei.c | const char * | const char * | - | - | - |
|
||||
2 | 7 | sys_waitpid | process/scheduler.c | pid_t | unsigned int * | int | - | - |
|
||||
2 | 8 | sys_creat | fs/namei.c | const char * | int | - | - | - |
|
||||
| 9 | sys_link | | const char * | const char * | - | - | - |
|
||||
2 | 10 | sys_unlink | fs/namei.c | const char * | - | - | - | - |
|
||||
2 | 11 | sys_execve | arch/i386/kernel/process.c | struct pt_regs | - | - | - | - |
|
||||
2 | 12 | sys_chdir | fs/open.c | const char * | - | - | - | - |
|
||||
2 | 13 | sys_time | kernel/time.c | int * | - | - | - | - |
|
||||
| 14 | sys_mknod | fs/namei.c | const char * | int | dev_t | - | - |
|
||||
| 15 | sys_chmod | fs/open.c | const char * | mode_t | - | - | - |
|
||||
| 16 | sys_lchown | fs/open.c | const char * | uid_t | gid_t | - | - |
|
||||
2 | 11 | sys_execve | process/process.c | struct pt_regs | - | - | - | - |
|
||||
2 | 12 | sys_chdir | process/process.c | const char * | - | - | - | - |
|
||||
2 | 13 | sys_time | klib/time.c | int * | - | - | - | - |
|
||||
| 14 | sys_mknod | | const char * | int | dev_t | - | - |
|
||||
1 | 15 | sys_chmod | fs/attr.c | const char * | mode_t | - | - | - |
|
||||
| 16 | sys_lchown | fs/attr.c | const char * | uid_t | gid_t | - | - |
|
||||
2 | 18 | sys_stat | fs/stat.c | char * | struct __old_kernel_stat * | - | - | - |
|
||||
2 | 19 | sys_lseek | fs/read_write.c | unsigned int | off_t | unsigned int | - | - |
|
||||
2 | 20 | sys_getpid | kernel/sched.c | - | - | - | - | - |
|
||||
| 21 | sys_mount | fs/super.c | char * | char * | char * | - | - |
|
||||
| 22 | sys_oldumount | fs/super.c | char * | - | - | - | - |
|
||||
2 | 23 | sys_setuid | kernel/sys.c | uid_t | - | - | - | - |
|
||||
2 | 24 | sys_getuid | kernel/sched.c | - | - | - | - | - |
|
||||
| 25 | sys_stime | kernel/time.c | int * | - | - | - | - |
|
||||
| 26 | sys_ptrace | arch/i386/kernel/ptrace.c | long | long | long | long | - |
|
||||
2 | 27 | sys_alarm | kernel/sched.c | unsigned int | - | - | - | - |
|
||||
2 | 20 | sys_getpid | process/scheduler.c | - | - | - | - | - |
|
||||
| 21 | sys_mount | | char * | char * | char * | - | - |
|
||||
| 22 | sys_oldumount | | char * | - | - | - | - |
|
||||
2 | 23 | sys_setuid | process/scheduler.c | uid_t | - | - | - | - |
|
||||
2 | 24 | sys_getuid | process/scheduler.c | - | - | - | - | - |
|
||||
| 25 | sys_stime | | int * | - | - | - | - |
|
||||
| 26 | sys_ptrace | | long | long | long | long | - |
|
||||
2 | 27 | sys_alarm | hardware/timer.c | unsigned int | - | - | - | - |
|
||||
2 | 28 | sys_fstat | fs/stat.c | unsigned int | struct __old_kernel_stat * | - | - | - |
|
||||
| 29 | sys_pause | arch/i386/kernel/sys_i386.c | - | - | - | - | - |
|
||||
| 30 | sys_utime | fs/open.c | char * | struct utimbuf * | - | - | - |
|
||||
| 33 | sys_access | fs/open.c | const char * | int | - | - | - |
|
||||
1 | 34 | sys_nice | kernel/sched.c | int | - | - | - | - |
|
||||
| 36 | sys_sync | fs/buffer.c | - | - | - | - | - |
|
||||
1 | 37 | sys_kill | kernel/signal.c | int | int | - | - | - |
|
||||
| 38 | sys_rename | fs/namei.c | const char * | const char * | - | - | - |
|
||||
| 29 | sys_pause | | - | - | - | - | - |
|
||||
| 30 | sys_utime | | char * | struct utimbuf * | - | - | - |
|
||||
| 33 | sys_access | | const char * | int | - | - | - |
|
||||
1 | 34 | sys_nice | process/scheduler.c | int | - | - | - | - |
|
||||
| 36 | sys_sync | | - | - | - | - | - |
|
||||
1 | 37 | sys_kill | system/signal.c | int | int | - | - | - |
|
||||
| 38 | sys_rename | | const char * | const char * | - | - | - |
|
||||
2 | 39 | sys_mkdir | fs/namei.c | const char * | int | - | - | - |
|
||||
2 | 40 | sys_rmdir | fs/namei.c | const char * | - | - | - | - |
|
||||
| 41 | sys_dup | fs/fcntl.c | unsigned int | - | - | - | - |
|
||||
| 42 | sys_pipe | arch/i386/kernel/sys_i386.c | unsigned long * | - | - | - | - |
|
||||
| 43 | sys_times | kernel/sys.c | struct tms * | - | - | - | - |
|
||||
2 | 45 | sys_brk | mm/mmap.c | unsigned long | - | - | - | - |
|
||||
2 | 46 | sys_setgid | kernel/sys.c | gid_t | - | - | - | - |
|
||||
2 | 47 | sys_getgid | kernel/sched.c | - | - | - | - | - |
|
||||
1 | 48 | sys_signal | kernel/signal.c | int | __sighandler_t | - | - | - |
|
||||
| 49 | sys_geteuid | kernel/sched.c | - | - | - | - | - |
|
||||
| 50 | sys_getegid | kernel/sched.c | - | - | - | - | - |
|
||||
| 51 | sys_acct | kernel/acct.c | const char * | - | - | - | - |
|
||||
| 52 | sys_umount | fs/super.c | char * | int | - | - | - |
|
||||
1 | 41 | sys_dup | fs/vfs.c | unsigned int | - | - | - | - |
|
||||
| 42 | sys_pipe | | unsigned long * | - | - | - | - |
|
||||
| 43 | sys_times | | struct tms * | - | - | - | - |
|
||||
2 | 45 | sys_brk | mem/kheap.c | unsigned long | - | - | - | - |
|
||||
2 | 46 | sys_setgid | process/scheduler.c | gid_t | - | - | - | - |
|
||||
2 | 47 | sys_getgid | process/scheduler.c | - | - | - | - | - |
|
||||
1 | 48 | sys_signal | system/signal.c | int | __sighandler_t | - | - | - |
|
||||
1 | 49 | sys_geteuid | process/scheduler.c | - | - | - | - | - |
|
||||
1 | 50 | sys_getegid | process/scheduler.c | - | - | - | - | - |
|
||||
| 51 | sys_acct | | const char * | - | - | - | - |
|
||||
| 52 | sys_umount | | char * | int | - | - | - |
|
||||
1 | 54 | sys_ioctl | fs/ioctl.c | unsigned int | unsigned int | unsigned long | - | - |
|
||||
| 55 | sys_fcntl | fs/fcntl.c | unsigned int | unsigned int | unsigned long | - | - |
|
||||
2 | 57 | sys_setpgid | kernel/sys.c | pid_t | pid_t | - | - | - |
|
||||
| 59 | sys_olduname | arch/i386/kernel/sys_i386.c | struct oldold_utsname * | - | - | - | - |
|
||||
| 60 | sys_umask | kernel/sys.c | int | - | - | - | - |
|
||||
| 61 | sys_chroot | fs/open.c | const char * | - | - | - | - |
|
||||
| 62 | sys_ustat | fs/super.c | dev_t | struct ustat * | - | - | - |
|
||||
| 63 | sys_dup2 | fs/fcntl.c | unsigned int | unsigned int | - | - | - |
|
||||
2 | 64 | sys_getppid | kernel/sched.c | - | - | - | - | - |
|
||||
| 65 | sys_getpgrp | kernel/sys.c | - | - | - | - | - |
|
||||
2 | 66 | sys_setsid | kernel/sys.c | - | - | - | - | - |
|
||||
1 | 67 | sys_sigaction | arch/i386/kernel/signal.c | int | const struct old_sigaction * | struct old_sigaction * | - | - |
|
||||
X | 68 | sys_sgetmask | kernel/signal.c | - | - | - | - | - |
|
||||
X | 69 | sys_ssetmask | kernel/signal.c | int | - | - | - | - |
|
||||
| 70 | sys_setreuid | kernel/sys.c | uid_t | uid_t | - | - | - |
|
||||
| 71 | sys_setregid | kernel/sys.c | gid_t | gid_t | - | - | - |
|
||||
| 72 | sys_sigsuspend | arch/i386/kernel/signal.c | int | int | old_sigset_t | - | - |
|
||||
| 73 | sys_sigpending | kernel/signal.c | old_sigset_t * | - | - | - | - |
|
||||
| 74 | sys_sethostname | kernel/sys.c | char * | int | - | - | - |
|
||||
| 75 | sys_setrlimit | kernel/sys.c | unsigned int | struct rlimit * | - | - | - |
|
||||
| 76 | sys_getrlimit | kernel/sys.c | unsigned int | struct rlimit * | - | - | - |
|
||||
| 77 | sys_getrusage | kernel/sys.c | int | struct rusage * | - | - | - |
|
||||
| 78 | sys_gettimeofday | kernel/time.c | struct timeval * | struct timezone * | - | - | - |
|
||||
| 79 | sys_settimeofday | kernel/time.c | struct timeval * | struct timezone * | - | - | - |
|
||||
| 80 | sys_getgroups | kernel/sys.c | int | gid_t * | - | - | - |
|
||||
| 81 | sys_setgroups | kernel/sys.c | int | gid_t * | - | - | - |
|
||||
| 83 | sys_symlink | fs/namei.c | const char * | const char * | - | - | - |
|
||||
| 84 | sys_lstat | fs/stat.c | char * | struct __old_kernel_stat * | - | - | - |
|
||||
| 85 | sys_readlink | fs/stat.c | const char * | char * | int | - | - |
|
||||
| 86 | sys_uselib | fs/exec.c | const char * | - | - | - | - |
|
||||
| 87 | sys_swapon | mm/swapfile.c | const char * | int | - | - | - |
|
||||
| 55 | sys_fcntl | | unsigned int | unsigned int | unsigned long | - | - |
|
||||
2 | 57 | sys_setpgid | process/scheduler.c | pid_t | pid_t | - | - | - |
|
||||
| 59 | sys_olduname | | struct oldold_utsname * | - | - | - | - |
|
||||
| 60 | sys_umask | | int | - | - | - | - |
|
||||
| 61 | sys_chroot | | const char * | - | - | - | - |
|
||||
| 62 | sys_ustat | | dev_t | struct ustat * | - | - | - |
|
||||
| 63 | sys_dup2 | | unsigned int | unsigned int | - | - | - |
|
||||
2 | 64 | sys_getppid | process/scheduler.c | - | - | - | - | - |
|
||||
| 65 | sys_getpgrp | | - | - | - | - | - |
|
||||
2 | 66 | sys_setsid | process/scheduler.c | - | - | - | - | - |
|
||||
1 | 67 | sys_sigaction | system/signal.c | int | const struct old_sigaction * | struct old_sigaction * | - | - |
|
||||
X | 68 | sys_sgetmask | | - | - | - | - | - |
|
||||
X | 69 | sys_ssetmask | | int | - | - | - | - |
|
||||
1 | 70 | sys_setreuid | process/scheduler.c | uid_t | uid_t | - | - | - |
|
||||
1 | 71 | sys_setregid | process/scheduler.c | gid_t | gid_t | - | - | - |
|
||||
| 72 | sys_sigsuspend | | int | int | old_sigset_t | - | - |
|
||||
| 73 | sys_sigpending | | old_sigset_t * | - | - | - | - |
|
||||
| 74 | sys_sethostname | | char * | int | - | - | - |
|
||||
| 75 | sys_setrlimit | | unsigned int | struct rlimit * | - | - | - |
|
||||
| 76 | sys_getrlimit | | unsigned int | struct rlimit * | - | - | - |
|
||||
| 77 | sys_getrusage | | int | struct rusage * | - | - | - |
|
||||
| 78 | sys_gettimeofday | | struct timeval * | struct timezone * | - | - | - |
|
||||
| 79 | sys_settimeofday | | struct timeval * | struct timezone * | - | - | - |
|
||||
| 80 | sys_getgroups | | int | gid_t * | - | - | - |
|
||||
| 81 | sys_setgroups | | int | gid_t * | - | - | - |
|
||||
| 83 | sys_symlink | | const char * | const char * | - | - | - |
|
||||
| 84 | sys_lstat | | char * | struct __old_kernel_stat * | - | - | - |
|
||||
| 85 | sys_readlink | | const char * | char * | int | - | - |
|
||||
| 86 | sys_uselib | | const char * | - | - | - | - |
|
||||
| 87 | sys_swapon | | const char * | int | - | - | - |
|
||||
1 | 88 | sys_reboot | kernel/sys.c | int | int | int | void * | - |
|
||||
1 | 89 | old_readdir | fs/readdir.c | unsigned int | void * | unsigned int | - | - |
|
||||
| 90 | old_mmap | arch/i386/kernel/sys_i386.c | struct mmap_arg_struct * | - | - | - | - |
|
||||
| 91 | sys_munmap | mm/mmap.c | unsigned long | size_t | - | - | - |
|
||||
| 92 | sys_truncate | fs/open.c | const char * | unsigned long | - | - | - |
|
||||
| 93 | sys_ftruncate | fs/open.c | unsigned int | unsigned long | - | - | - |
|
||||
| 94 | sys_fchmod | fs/open.c | unsigned int | mode_t | - | - | - |
|
||||
| 95 | sys_fchown | fs/open.c | unsigned int | uid_t | gid_t | - | - |
|
||||
| 96 | sys_getpriority | kernel/sys.c | int | int | - | - | - |
|
||||
| 97 | sys_setpriority | kernel/sys.c | int | int | int | - | - |
|
||||
| 99 | sys_statfs | fs/open.c | const char * | struct statfs * | - | - | - |
|
||||
| 100 | sys_fstatfs | fs/open.c | unsigned int | struct statfs * | - | - | - |
|
||||
| 101 | sys_ioperm | arch/i386/kernel/ioport.c | unsigned long | unsigned long | int | - | - |
|
||||
| 102 | sys_socketcall | net/socket.c | int | unsigned long * | - | - | - |
|
||||
| 103 | sys_syslog | kernel/printk.c | int | char * | int | - | - |
|
||||
| 104 | sys_setitimer | kernel/itimer.c | int | struct itimerval * | struct itimerval * | - | - |
|
||||
| 105 | sys_getitimer | kernel/itimer.c | int | struct itimerval * | - | - | - |
|
||||
| 106 | sys_newstat | fs/stat.c | char * | struct stat * | - | - | - |
|
||||
| 107 | sys_newlstat | fs/stat.c | char * | struct stat * | - | - | - |
|
||||
| 108 | sys_newfstat | fs/stat.c | unsigned int | struct stat * | - | - | - |
|
||||
1 | 109 | sys_uname | arch/i386/kernel/sys_i386.c | struct old_utsname * | - | - | - | - |
|
||||
| 110 | sys_iopl | arch/i386/kernel/ioport.c | unsigned long | - | - | - | - |
|
||||
| 111 | sys_vhangup | fs/open.c | - | - | - | - | - |
|
||||
| 112 | sys_idle | arch/i386/kernel/process.c | - | - | - | - | - |
|
||||
| 113 | sys_vm86old | arch/i386/kernel/vm86.c | unsigned long | struct vm86plus_struct * | - | - | - |
|
||||
| 114 | sys_wait4 | kernel/exit.c | pid_t | unsigned long * | int options | struct rusage * | - |
|
||||
| 115 | sys_swapoff | mm/swapfile.c | const char * | - | - | - | - |
|
||||
| 116 | sys_sysinfo | kernel/info.c | struct sysinfo * | - | - | - | - |
|
||||
* | 117 | sys_ipc(*Note) | arch/i386/kernel/sys_i386.c | uint | int | int | int | void * |
|
||||
| 118 | sys_fsync | fs/buffer.c | unsigned int | - | - | - | - |
|
||||
| 119 | sys_sigreturn | arch/i386/kernel/signal.c | unsigned long | - | - | - | - |
|
||||
| 120 | sys_clone | arch/i386/kernel/process.c | struct pt_regs | - | - | - | - |
|
||||
| 121 | sys_setdomainname | kernel/sys.c | char * | int | - | - | - |
|
||||
| 122 | sys_newuname | kernel/sys.c | struct new_utsname * | - | - | - | - |
|
||||
| 123 | sys_modify_ldt | arch/i386/kernel/ldt.c | int | void * | unsigned long | - | - |
|
||||
| 124 | sys_adjtimex | kernel/time.c | struct timex * | - | - | - | - |
|
||||
| 125 | sys_mprotect | mm/mprotect.c | unsigned long | size_t | unsigned long | - | - |
|
||||
1 | 126 | sys_sigprocmask | kernel/signal.c | int | old_sigset_t * | old_sigset_t * | - | - |
|
||||
| 127 | sys_create_module | kernel/module.c | const char * | size_t | - | - | - |
|
||||
| 128 | sys_init_module | kernel/module.c | const char * | struct module * | - | - | - |
|
||||
| 129 | sys_delete_module | kernel/module.c | const char * | - | - | - | - |
|
||||
| 130 | sys_get_kernel_syms | kernel/module.c | struct kernel_sym * | - | - | - | - |
|
||||
| 131 | sys_quotactl | fs/dquot.c | int | const char * | int | caddr_t | - |
|
||||
| 132 | sys_getpgid | kernel/sys.c | pid_t | - | - | - | - |
|
||||
1 | 133 | sys_fchdir | fs/open.c | unsigned int | - | - | - | - |
|
||||
| 134 | sys_bdflush | fs/buffer.c | int | long | - | - | - |
|
||||
| 135 | sys_sysfs | fs/super.c | int | unsigned long | unsigned long | - | - |
|
||||
| 136 | sys_personality | kernel/exec_domain.c | unsigned long | - | - | - | - |
|
||||
| 138 | sys_setfsuid | kernel/sys.c | uid_t | - | - | - | - |
|
||||
| 139 | sys_setfsgid | kernel/sys.c | gid_t | - | - | - | - |
|
||||
| 140 | sys_llseek | fs/read_write.c | unsigned int | unsigned long | unsigned long | loff_t * | unsigned int |
|
||||
| 89 | old_readdir | | unsigned int | void * | unsigned int | - | - |
|
||||
| 90 | old_mmap | | struct mmap_arg_struct * | - | - | - | - |
|
||||
| 91 | sys_munmap | | unsigned long | size_t | - | - | - |
|
||||
| 92 | sys_truncate | | const char * | unsigned long | - | - | - |
|
||||
| 93 | sys_ftruncate | | unsigned int | unsigned long | - | - | - |
|
||||
| 94 | sys_fchmod | | unsigned int | mode_t | - | - | - |
|
||||
1 | 95 | sys_fchown | fs/attr.c | unsigned int | uid_t | gid_t | - | - |
|
||||
| 96 | sys_getpriority | | int | int | - | - | - |
|
||||
| 97 | sys_setpriority | | int | int | int | - | - |
|
||||
| 99 | sys_statfs | | const char * | struct statfs * | - | - | - |
|
||||
| 100 | sys_fstatfs | | unsigned int | struct statfs * | - | - | - |
|
||||
| 101 | sys_ioperm | | unsigned long | unsigned long | int | - | - |
|
||||
| 102 | sys_socketcall | | int | unsigned long * | - | - | - |
|
||||
1 | 103 | sys_syslog | system/printk.c | int | char * | int | - | - |
|
||||
1 | 104 | sys_setitimer | hardware/timer.c | int | struct itimerval * | struct itimerval * | - | - |
|
||||
1 | 105 | sys_getitimer | hardware/timer.c | int | struct itimerval * | - | - | - |
|
||||
| 106 | sys_newstat | | char * | struct stat * | - | - | - |
|
||||
| 107 | sys_newlstat | | char * | struct stat * | - | - | - |
|
||||
| 108 | sys_newfstat | | unsigned int | struct stat * | - | - | - |
|
||||
1 | 109 | sys_uname | sys/utsname.c | struct old_utsname * | - | - | - | - |
|
||||
| 110 | sys_iopl | | unsigned long | - | - | - | - |
|
||||
| 111 | sys_vhangup | | - | - | - | - | - |
|
||||
| 112 | sys_idle | | - | - | - | - | - |
|
||||
| 113 | sys_vm86old | | unsigned long | struct vm86plus_struct * | - | - | - |
|
||||
| 114 | sys_wait4 | | pid_t | unsigned long * | int options | struct rusage * | - |
|
||||
| 115 | sys_swapoff | | const char * | - | - | - | - |
|
||||
| 116 | sys_sysinfo | | struct sysinfo * | - | - | - | - |
|
||||
* | 117 | sys_ipc(*Note) | | uint | int | int | int | void * |
|
||||
| 118 | sys_fsync | | unsigned int | - | - | - | - |
|
||||
1 | 119 | sys_sigreturn | system/signal.c | unsigned long | - | - | - | - |
|
||||
| 120 | sys_clone | | struct pt_regs | - | - | - | - |
|
||||
| 121 | sys_setdomainname | | char * | int | - | - | - |
|
||||
| 122 | sys_newuname | | struct new_utsname * | - | - | - | - |
|
||||
| 123 | sys_modify_ldt | | int | void * | unsigned long | - | - |
|
||||
| 124 | sys_adjtimex | | struct timex * | - | - | - | - |
|
||||
| 125 | sys_mprotect | | unsigned long | size_t | unsigned long | - | - |
|
||||
1 | 126 | sys_sigprocmask | system/signal.c | int | old_sigset_t * | old_sigset_t * | - | - |
|
||||
| 127 | sys_create_module | | const char * | size_t | - | - | - |
|
||||
| 128 | sys_init_module | | const char * | struct module * | - | - | - |
|
||||
| 129 | sys_delete_module | | const char * | - | - | - | - |
|
||||
| 130 | sys_get_kernel_syms | | struct kernel_sym * | - | - | - | - |
|
||||
| 131 | sys_quotactl | | int | const char * | int | caddr_t | - |
|
||||
| 132 | sys_getpgid | | pid_t | - | - | - | - |
|
||||
1 | 133 | sys_fchdir | process/process.c | unsigned int | - | - | - | - |
|
||||
| 134 | sys_bdflush | | int | long | - | - | - |
|
||||
| 135 | sys_sysfs | | int | unsigned long | unsigned long | - | - |
|
||||
| 136 | sys_personality | | unsigned long | - | - | - | - |
|
||||
| 138 | sys_setfsuid | | uid_t | - | - | - | - |
|
||||
| 139 | sys_setfsgid | | gid_t | - | - | - | - |
|
||||
| 140 | sys_llseek | | unsigned int | unsigned long | unsigned long | loff_t * | unsigned int |
|
||||
2 | 141 | sys_getdents | fs/readdir.c | unsigned int | void * | unsigned int | - | - |
|
||||
| 142 | sys_select | fs/select.c | int | fd_set * | fd_set * | fd_set * | struct timeval * |
|
||||
| 143 | sys_flock | fs/locks.c | unsigned int | unsigned int | - | - | - |
|
||||
| 144 | sys_msync | mm/filemap.c | unsigned long | size_t | int | - | - |
|
||||
| 145 | sys_readv | fs/read_write.c | unsigned long | const struct iovec * | unsigned long | - | - |
|
||||
| 146 | sys_writev | fs/read_write.c | unsigned long | const struct iovec * | unsigned long | - | - |
|
||||
| 147 | sys_getsid | kernel/sys.c | pid_t | - | - | - | - |
|
||||
| 148 | sys_fdatasync | fs/buffer.c | unsigned int | - | - | - | - |
|
||||
| 149 | sys_sysctl | kernel/sysctl.c | struct __sysctl_args * | - | - | - | - |
|
||||
| 150 | sys_mlock | mm/mlock.c | unsigned long | size_t | - | - | - |
|
||||
| 151 | sys_munlock | mm/mlock.c | unsigned long | size_t | - | - | - |
|
||||
| 152 | sys_mlockall | mm/mlock.c | int | - | - | - | - |
|
||||
| 153 | sys_munlockall | mm/mlock.c | - | - | - | - | - |
|
||||
1 | 154 | sys_sched_setparam | kernel/sched.c | pid_t | struct sched_param * | - | - | - |
|
||||
1 | 155 | sys_sched_getparam | kernel/sched.c | pid_t | struct sched_param * | - | - | - |
|
||||
| 156 | sys_sched_setscheduler | kernel/sched.c | pid_t | int | struct sched_param * | - | - |
|
||||
| 157 | sys_sched_getscheduler | kernel/sched.c | pid_t | - | - | - | - |
|
||||
| 158 | sys_sched_yield | kernel/sched.c | - | - | - | - | - |
|
||||
| 159 | sys_sched_get_priority_max | kernel/sched.c | int | - | - | - | - |
|
||||
| 160 | sys_sched_get_priority_min | kernel/sched.c | int | - | - | - | - |
|
||||
| 161 | sys_sched_rr_get_interval | kernel/sched.c | pid_t | struct timespec * | - | - | - |
|
||||
| 162 | sys_nanosleep | kernel/sched.c | struct timespec * | struct timespec * | - | - | - |
|
||||
| 163 | sys_mremap | mm/mremap.c | unsigned long | unsigned long | unsigned long | unsigned long | - |
|
||||
| 164 | sys_setresuid | kernel/sys.c | uid_t | uid_t | uid_t | - | - |
|
||||
| 165 | sys_getresuid | kernel/sys.c | uid_t * | uid_t * | uid_t * | - | - |
|
||||
| 166 | sys_vm86 | arch/i386/kernel/vm86.c | struct vm86_struct * | - | - | - | - |
|
||||
| 167 | sys_query_module | kernel/module.c | const char * | int | char * | size_t | size_t * |
|
||||
| 168 | sys_poll | fs/select.c | struct pollfd * | unsigned int | long | - | - |
|
||||
| 169 | sys_nfsservctl | fs/filesystems.c | int | void * | void * | - | - |
|
||||
| 170 | sys_setresgid | kernel/sys.c | gid_t | gid_t | gid_t | - | - |
|
||||
| 171 | sys_getresgid | kernel/sys.c | gid_t * | gid_t * | gid_t * | - | - |
|
||||
| 172 | sys_prctl | kernel/sys.c | int | unsigned long | unsigned long | unsigned long | unsigned long |
|
||||
| 173 | sys_rt_sigreturn | arch/i386/kernel/signal.c | unsigned long | - | - | - | - |
|
||||
| 174 | sys_rt_sigaction | kernel/signal.c | int | const struct sigaction * | struct sigaction * | size_t | - |
|
||||
| 175 | sys_rt_sigprocmask | kernel/signal.c | int | sigset_t * | sigset_t * | size_t | - |
|
||||
| 176 | sys_rt_sigpending | kernel/signal.c | sigset_t * | size_t | - | - | - |
|
||||
| 177 | sys_rt_sigtimedwait | kernel/signal.c | const sigset_t * | siginfo_t * | const struct timespec * | size_t | - |
|
||||
| 178 | sys_rt_sigqueueinfo | kernel/signal.c | int | int | siginfo_t * | - | - |
|
||||
| 179 | sys_rt_sigsuspend | arch/i386/kernel/signal.c | sigset_t * | size_t | - | - | - |
|
||||
| 180 | sys_pread | fs/read_write.c | unsigned int | char * | size_t | loff_t | - |
|
||||
| 181 | sys_pwrite | fs/read_write.c | unsigned int | const char * | size_t | loff_t | - |
|
||||
| 182 | sys_chown | fs/open.c | const char * | uid_t | gid_t | - | - |
|
||||
1 | 183 | sys_getcwd | fs/dcache.c | char * | unsigned long | - | - | - |
|
||||
| 184 | sys_capget | kernel/capability.c | cap_user_header_t | cap_user_data_t | - | - | - |
|
||||
| 185 | sys_capset | kernel/capability.c | cap_user_header_t | const cap_user_data_t | - | - | - |
|
||||
| 186 | sys_sigaltstack | arch/i386/kernel/signal.c | const stack_t * | stack_t * | - | - | - |
|
||||
| 187 | sys_sendfile | mm/filemap.c | int | int | off_t * | size_t | - |
|
||||
| | | | | | | | |
|
||||
2 | 188 | sys_waitperiod | kernel/sched.c | | | | | |
|
||||
| 142 | sys_select | | int | fd_set * | fd_set * | fd_set * | struct timeval * |
|
||||
| 143 | sys_flock | | unsigned int | unsigned int | - | - | - |
|
||||
| 144 | sys_msync | | unsigned long | size_t | int | - | - |
|
||||
| 145 | sys_readv | | unsigned long | const struct iovec * | unsigned long | - | - |
|
||||
| 146 | sys_writev | | unsigned long | const struct iovec * | unsigned long | - | - |
|
||||
1 | 147 | sys_getsid | process/scheduler.c | pid_t | - | - | - | - |
|
||||
| 148 | sys_fdatasync | | unsigned int | - | - | - | - |
|
||||
| 149 | sys_sysctl | | struct __sysctl_args * | - | - | - | - |
|
||||
| 150 | sys_mlock | | unsigned long | size_t | - | - | - |
|
||||
| 151 | sys_munlock | | unsigned long | size_t | - | - | - |
|
||||
| 152 | sys_mlockall | | int | - | - | - | - |
|
||||
| 153 | sys_munlockall | | - | - | - | - | - |
|
||||
1 | 154 | sys_sched_setparam | process/scheduler.c | pid_t | struct sched_param * | - | - | - |
|
||||
1 | 155 | sys_sched_getparam | process/scheduler.c | pid_t | struct sched_param * | - | - | - |
|
||||
| 156 | sys_sched_setscheduler | | pid_t | int | struct sched_param * | - | - |
|
||||
| 157 | sys_sched_getscheduler | | pid_t | - | - | - | - |
|
||||
| 158 | sys_sched_yield | | - | - | - | - | - |
|
||||
| 159 | sys_sched_get_priority_max | | int | - | - | - | - |
|
||||
| 160 | sys_sched_get_priority_min | | int | - | - | - | - |
|
||||
| 161 | sys_sched_rr_get_interval | | pid_t | struct timespec * | - | - | - |
|
||||
1 | 162 | sys_nanosleep | hardware/timer.c | struct timespec * | struct timespec * | - | - | - |
|
||||
| 163 | sys_mremap | | unsigned long | unsigned long | unsigned long | unsigned long | - |
|
||||
| 164 | sys_setresuid | | uid_t | uid_t | uid_t | - | - |
|
||||
| 165 | sys_getresuid | | uid_t * | uid_t * | uid_t * | - | - |
|
||||
| 166 | sys_vm86 | | struct vm86_struct * | - | - | - | - |
|
||||
| 167 | sys_query_module | | const char * | int | char * | size_t | size_t * |
|
||||
| 168 | sys_poll | | struct pollfd * | unsigned int | long | - | - |
|
||||
| 169 | sys_nfsservctl | | int | void * | void * | - | - |
|
||||
| 170 | sys_setresgid | | gid_t | gid_t | gid_t | - | - |
|
||||
| 171 | sys_getresgid | | gid_t * | gid_t * | gid_t * | - | - |
|
||||
| 172 | sys_prctl | | int | unsigned long | unsigned long | unsigned long | unsigned long |
|
||||
| 173 | sys_rt_sigreturn | | unsigned long | - | - | - | - |
|
||||
| 174 | sys_rt_sigaction | | int | const struct sigaction * | struct sigaction * | size_t | - |
|
||||
| 175 | sys_rt_sigprocmask | | int | sigset_t * | sigset_t * | size_t | - |
|
||||
| 176 | sys_rt_sigpending | | sigset_t * | size_t | - | - | - |
|
||||
| 177 | sys_rt_sigtimedwait | | const sigset_t * | siginfo_t * | const struct timespec * | size_t | - |
|
||||
| 178 | sys_rt_sigqueueinfo | | int | int | siginfo_t * | - | - |
|
||||
| 179 | sys_rt_sigsuspend | | sigset_t * | size_t | - | - | - |
|
||||
| 180 | sys_pread | | unsigned int | char * | size_t | loff_t | - |
|
||||
| 181 | sys_pwrite | | unsigned int | const char * | size_t | loff_t | - |
|
||||
1 | 182 | sys_chown | vfs/attr.c | const char * | uid_t | gid_t | - | - |
|
||||
1 | 183 | sys_getcwd | process/process.c | char * | unsigned long | - | - | - |
|
||||
| 184 | sys_capget | | cap_user_header_t | cap_user_data_t | - | - | - |
|
||||
| 185 | sys_capset | | cap_user_header_t | const cap_user_data_t | - | - | - |
|
||||
| 186 | sys_sigaltstack | | const stack_t * | stack_t * | - | - | - |
|
||||
| 187 | sys_sendfile | | int | int | off_t * | size_t | - |
|
||||
2 | 188 | sys_waitperiod | process/scheduler.c | | | | | |
|
||||
| 189 | sys_msgctl | | int | | | | |
|
||||
| 190 | sys_msgget | | | | | | |
|
||||
| 191 | sys_msgrcv | | | | | | |
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../root
|
||||
@@ -0,0 +1,22 @@
|
||||
SYNOPSIS
|
||||
chmod MODE FILE
|
||||
|
||||
DESCRIPTION
|
||||
chmod changes the file mode bits of the given file according to mode, which
|
||||
must be an octal number representing the bit pattern for the new mode bits.
|
||||
|
||||
The numeric mode is from one to four octal digits (0-7), derived by adding
|
||||
up the bits with values 4, 2, and 1. Omitted digits are assumed to be
|
||||
leading zeros. The first digit selects the set user ID (4) and set group
|
||||
ID (2) and restricted deletion or sticky (1) attributes. The second digit
|
||||
selects permissions for the user who owns the file: read (4), write (2),
|
||||
and execute (1); the third selects permissions for other users in the file's
|
||||
group, with the same values; and the fourth for other users not in the
|
||||
file's group, with the same values.
|
||||
|
||||
chmod never changes the permissions of symbolic links; the chmod system call
|
||||
cannot change their permissions.
|
||||
|
||||
EXAMPLES
|
||||
chmod 555 executable
|
||||
Changes the mode bits of executable to r-xr-xr-x.
|
||||
@@ -0,0 +1,19 @@
|
||||
SYNOPSIS
|
||||
chown [OWNER][:[GROUP]] FILE
|
||||
|
||||
DESCRIPTION
|
||||
chown changes the user and/or group ownership of the given file.
|
||||
If only a owner is given the file's group is not changed. If the owner
|
||||
is followed by a colon and a group name (or numeric group ID), the group
|
||||
ownership is changed as well. If the colon and group are given, but the
|
||||
owner is omitted, only the group of the file is changed.
|
||||
|
||||
chown never changes the ownership of symbolic links; the chown system call
|
||||
cannot change their ownership.
|
||||
|
||||
EXAMPLES
|
||||
chown root /u
|
||||
Change the owner of /u to "root".
|
||||
|
||||
chown root:staff /u
|
||||
Likewise, but also change its group to "staff".
|
||||
@@ -0,0 +1,5 @@
|
||||
SYNOPSIS
|
||||
false
|
||||
|
||||
DESCRIPTION
|
||||
false sets the exit status to 1.
|
||||
@@ -0,0 +1,15 @@
|
||||
SYNOPSIS
|
||||
id [OPTIONS]
|
||||
|
||||
DESCRIPTION
|
||||
Print user and group information for the current process.
|
||||
|
||||
The following options are available:
|
||||
|
||||
-g, --group
|
||||
print only the effective group ID
|
||||
|
||||
-u, --user
|
||||
print only the effective user ID
|
||||
|
||||
--help display a help message and exit
|
||||
@@ -0,0 +1,13 @@
|
||||
SYNOPSIS
|
||||
more [FILE]
|
||||
|
||||
DESCRIPTION
|
||||
more is a filter for paging through text one screenful at a time.
|
||||
|
||||
OPTIONS
|
||||
-h, --help: shows command help.
|
||||
|
||||
KEY BINDINGS
|
||||
q Exit from more
|
||||
space Display next screen size
|
||||
return Display next line
|
||||
@@ -5,6 +5,7 @@
|
||||
# Add the library.
|
||||
add_library(
|
||||
libc
|
||||
${CMAKE_SOURCE_DIR}/libc/src/unistd/dup.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/stdio.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/ctype.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/string.c
|
||||
@@ -32,6 +33,8 @@ add_library(
|
||||
${CMAKE_SOURCE_DIR}/libc/src/sys/utsname.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/sys/mman.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/sys/ioctl.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/unistd/chmod.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/unistd/chown.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/unistd/creat.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/unistd/getppid.c
|
||||
${CMAKE_SOURCE_DIR}/libc/src/unistd/getpid.c
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define O_ACCMODE 0003 ///< Bits defining the open mode
|
||||
#define O_RDONLY 00000000U ///< Open for reading only.
|
||||
#define O_WRONLY 00000001U ///< Open for writing only.
|
||||
#define O_RDWR 00000002U ///< Open for reading and writing.
|
||||
|
||||
+9
-2
@@ -37,10 +37,10 @@ typedef unsigned int ino_t;
|
||||
typedef unsigned int dev_t;
|
||||
|
||||
/// The type of user-id.
|
||||
typedef unsigned int uid_t;
|
||||
typedef int uid_t;
|
||||
|
||||
/// The type of group-id.
|
||||
typedef unsigned int gid_t;
|
||||
typedef int gid_t;
|
||||
|
||||
/// The type of offset.
|
||||
typedef long int off_t;
|
||||
@@ -72,6 +72,13 @@ typedef unsigned int pgprot_t;
|
||||
/// Counts the number of elements of an array.
|
||||
#define count_of(x) ((sizeof(x) / sizeof((x)[0])) / ((size_t)(!(sizeof(x) % sizeof((x)[0])))))
|
||||
|
||||
/// @brief Swaps two values.
|
||||
/// @details
|
||||
/// do { ... } while (0) allows to place multistatement operations, for
|
||||
/// instance, inside the following if stantement:
|
||||
/// if (condition)
|
||||
/// swap(var1, var2)
|
||||
/// which otherwise would be wrong.
|
||||
#define swap(a, b) \
|
||||
do { \
|
||||
typeof(a) temp = (a); \
|
||||
|
||||
@@ -174,6 +174,7 @@ char *strtok_r(char *str, const char *delim, char **saveptr);
|
||||
/// parsed token in buffer. The pointer `string` will be modified.
|
||||
/// @param string cursor used to parse the string, it will be modified.
|
||||
/// @param separators the list of separators we are using.
|
||||
/// @param offset the offset character from which we start extracting the next token.
|
||||
/// @param buffer the buffer where we save the parsed token.
|
||||
/// @param buflen the length of the buffer.
|
||||
/// @return 1 if we still have things to parse, 0 if we finished parsing.
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
#define bit_flip_assign(V, B) ((V) ^= (1U << (B))) ///< Flips the given bit, permanently.
|
||||
#define bit_toggle_assign(V, B, C) ((C) ? bit_set_assign(V, B) : bit_clear_assign(V, B)) ///< Sets the given bit based on control bit C.
|
||||
|
||||
#define bitmask_set(V, M) ((V) | (M)) ///< Sets the bits identified by the mask.
|
||||
#define bitmask_clear(V, M) ((V) & ~(M)) ///< Clears the bits identified by the mask.
|
||||
#define bitmask_flip(V, M) ((V) ^ (M)) ///< Flips the bits identified by the mask.
|
||||
#define bitmask_check(V, M) ((V) & (M)) ///< Checks if the bits identified by the mask are all 1.
|
||||
#define bitmask_set_assign(V, M) ((V) |= (M)) ///< Sets the bits identified by the mask, permanently.
|
||||
#define bitmask_clear_assign(V, M) ((V) &= ~(M)) ///< Clears the bits identified by the mask, permanently.
|
||||
#define bitmask_flip_assign(V, M) ((V) ^= (M)) ///< Flips the bits identified by the mask, permanently.
|
||||
#define bitmask_set(V, M) ((V) | (M)) ///< Sets the bits identified by the mask.
|
||||
#define bitmask_clear(V, M) ((V) & ~(M)) ///< Clears the bits identified by the mask.
|
||||
#define bitmask_flip(V, M) ((V) ^ (M)) ///< Flips the bits identified by the mask.
|
||||
#define bitmask_check(V, M) ((V) & (M)) ///< Checks if the bits identified by the mask are all 1.
|
||||
#define bitmask_exact(V, M) (((V) & (M)) == (M)) ///< Checks if all the bits identified by the mask are all 1.
|
||||
#define bitmask_set_assign(V, M) ((V) |= (M)) ///< Sets the bits identified by the mask, permanently.
|
||||
#define bitmask_clear_assign(V, M) ((V) &= ~(M)) ///< Clears the bits identified by the mask, permanently.
|
||||
#define bitmask_flip_assign(V, M) ((V) ^= (M)) ///< Flips the bits identified by the mask, permanently.
|
||||
|
||||
/// @brief Finds the first bit at zero, starting from the less significative bit.
|
||||
/// @param value the value we need to analyze.
|
||||
|
||||
+74
-8
@@ -61,7 +61,7 @@ int unlink(const char *path);
|
||||
int symlink(const char *linkname, const char *path);
|
||||
|
||||
/// @brief Read the symbolic link, if present.
|
||||
/// @param file the file for which we want to read the symbolic link information.
|
||||
/// @param path the file for which we want to read the symbolic link information.
|
||||
/// @param buffer the buffer where we will store the symbolic link path.
|
||||
/// @param bufsize the size of the buffer.
|
||||
/// @return The number of read characters on success, -1 otherwise and errno is set to indicate the error.
|
||||
@@ -106,26 +106,48 @@ pid_t getpgid(pid_t pid);
|
||||
/// @return returns zero. On error, -1 is returned, and errno is set appropriately.
|
||||
int setpgid(pid_t pid, pid_t pgid);
|
||||
|
||||
///@brief returns the group ID of the calling process.
|
||||
///@brief returns the real group ID of the calling process.
|
||||
///@return GID of the current process
|
||||
extern pid_t getgid(void);
|
||||
extern gid_t getgid(void);
|
||||
|
||||
///@brief sets the effective group ID of the calling process.
|
||||
///@param pid process identifier to
|
||||
///@brief returns the effective group ID of the calling process.
|
||||
///@return GID of the current process
|
||||
extern gid_t getegid(void);
|
||||
|
||||
///@brief sets the group IDs of the calling process.
|
||||
///@param gid the Group ID to set
|
||||
///@return On success, zero is returned.
|
||||
/// Otherwise returns -1 with errno set to :EINVAL or EPERM
|
||||
extern int setgid(pid_t pid);
|
||||
extern int setgid(gid_t gid);
|
||||
|
||||
///@brief Returns the User ID of the calling process.
|
||||
///@brief sets the real and effective group IDs of the calling process.
|
||||
///@param rgid the new real Group ID.
|
||||
///@param egid the effective real Group ID.
|
||||
///@return On success, zero is returned.
|
||||
/// Otherwise returns -1 with errno set EPERM
|
||||
extern int setregid(gid_t rgid, gid_t egid);
|
||||
|
||||
///@brief Returns the real User ID of the calling process.
|
||||
///@return User ID of the current process.
|
||||
extern uid_t getuid(void);
|
||||
|
||||
///@brief Sets the effective User ID of the calling process.
|
||||
///@brief Returns the effective User ID of the calling process.
|
||||
///@return User ID of the current process.
|
||||
extern uid_t geteuid(void);
|
||||
|
||||
///@brief Sets the User IDs of the calling process.
|
||||
///@param uid the new User ID.
|
||||
///@return On success, zero is returned.
|
||||
/// Otherwise returns -1 with errno set to :EINVAL or EPERM
|
||||
extern int setuid(uid_t uid);
|
||||
|
||||
///@brief Sets the effective and real User IDs of the calling process.
|
||||
///@param ruid the new real User ID.
|
||||
///@param euid the effective real User ID.
|
||||
///@return On success, zero is returned.
|
||||
/// Otherwise returns -1 with errno set to EPERM
|
||||
extern int setreuid(uid_t ruid, uid_t euid);
|
||||
|
||||
/// @brief Returns the parent process ID (PPID) of the calling process.
|
||||
/// @return pid_t parent process identifier.
|
||||
extern pid_t getppid(void);
|
||||
@@ -253,6 +275,12 @@ int fchdir(int fd);
|
||||
/// appropriately.
|
||||
ssize_t getdents(int fd, dirent_t *dirp, unsigned int count);
|
||||
|
||||
/// @brief Return a new file descriptor
|
||||
/// @param fd The fd pointing to the opened file.
|
||||
/// @return On success, a new file descriptor is returned.
|
||||
/// On error, -1 is returned, and errno is set appropriately.
|
||||
int dup(int fd);
|
||||
|
||||
/// @brief Send signal to calling thread after desired seconds.
|
||||
/// @param seconds the amount of seconds.
|
||||
/// @return If there is a previous alarm() request with time remaining, alarm()
|
||||
@@ -260,3 +288,41 @@ ssize_t getdents(int fd, dirent_t *dirp, unsigned int count);
|
||||
/// previous request would have generated a SIGALRM signal. Otherwise, alarm()
|
||||
/// shall return 0.
|
||||
unsigned alarm(int seconds);
|
||||
|
||||
/// @brief Change the file's mode bits.
|
||||
/// @param pathname The pathname of the file to change mode.
|
||||
/// @param mode The mode bits to set.
|
||||
/// @return On success, 0 is returned.
|
||||
/// On error, -1 is returned, and errno is set appropriately.
|
||||
int chmod(const char *pathname, mode_t mode);
|
||||
|
||||
/// @brief Change the file's mode bits.
|
||||
/// @param fd The fd pointing to the opened file.
|
||||
/// @param mode The mode bits to set.
|
||||
/// @return On success, 0 is returned.
|
||||
/// On error, -1 is returned, and errno is set appropriately.
|
||||
int fchmod(int fd, mode_t mode);
|
||||
|
||||
/// @brief Change the owner and group of a file.
|
||||
/// @param pathname The pathname of the file to change.
|
||||
/// @param owner The new owner to set.
|
||||
/// @param owner The new group to set.
|
||||
/// @return On success, 0 is returned.
|
||||
/// On error, -1 is returned, and errno is set appropriately.
|
||||
int chown(const char *pathname, uid_t owner, gid_t group);
|
||||
|
||||
/// @brief Change the owner and group of a file.
|
||||
/// @param fd The fd pointing to the opened file.
|
||||
/// @param owner The new owner to set.
|
||||
/// @param owner The new group to set.
|
||||
/// @return On success, 0 is returned.
|
||||
/// On error, -1 is returned, and errno is set appropriately.
|
||||
int fchown(int fd, uid_t owner, gid_t group);
|
||||
|
||||
/// @brief Change the owner and group of a file.
|
||||
/// @param pathname The pathname of the file to change.
|
||||
/// @param owner The new owner to set.
|
||||
/// @param owner The new group to set.
|
||||
/// @return On success, 0 is returned.
|
||||
/// On error, -1 is returned, and errno is set appropriately.
|
||||
int lchown(const char *pathname, uid_t owner, gid_t group);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/// @brief Define the functions required to turn double values into a string.
|
||||
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
#include "fcvt.h"
|
||||
#include "math.h"
|
||||
@@ -102,3 +103,5 @@ void fcvtbuf(double arg, int decimals, int *decpt, int *sign, char *buf, unsigne
|
||||
{
|
||||
cvt(arg, decimals, decpt, sign, buf, buf_size, 0);
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
+18
-12
@@ -16,18 +16,12 @@
|
||||
/// Determines the log level.
|
||||
static int max_log_level = LOGLEVEL_DEBUG;
|
||||
|
||||
void dbg_putchar(char c)
|
||||
{
|
||||
outportb(SERIAL_COM1, (unsigned char)c);
|
||||
}
|
||||
|
||||
void dbg_puts(const char *s)
|
||||
{
|
||||
while ((*s) != 0) {
|
||||
dbg_putchar(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Prints the correct header for the given debug level.
|
||||
/// @param file the file origin of the debug message.
|
||||
/// @param fun the function where the debug message was called.
|
||||
/// @param line the line in the file where debug message was called.
|
||||
/// @param log_level the log level.
|
||||
/// @param header the header we want to show.
|
||||
static inline void __debug_print_header(const char *file, const char *fun, int line, short log_level, char *header)
|
||||
{
|
||||
// "EMERG ", "ALERT ", "CRIT ", "ERR ", "WARNING", "NOTICE ", "INFO ", "DEBUG ", "DEFAULT",
|
||||
@@ -75,6 +69,18 @@ static inline void __debug_print_header(const char *file, const char *fun, int l
|
||||
}
|
||||
}
|
||||
|
||||
void dbg_putchar(char c)
|
||||
{
|
||||
outportb(SERIAL_COM1, (unsigned char)c);
|
||||
}
|
||||
|
||||
void dbg_puts(const char *s)
|
||||
{
|
||||
while ((*s) != 0) {
|
||||
dbg_putchar(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
void set_log_level(int level)
|
||||
{
|
||||
if ((level >= LOGLEVEL_EMERG) && (level <= LOGLEVEL_DEBUG)) {
|
||||
|
||||
+40
-16
@@ -13,25 +13,50 @@
|
||||
/// malloc(), calloc() or realloc().
|
||||
#define MALLOC_MAGIC_NUMBER 0x600DC0DE
|
||||
|
||||
/// @brief A structure that holds the information about an allocated chunk of
|
||||
/// memory through malloc.
|
||||
typedef struct {
|
||||
/// @brief A magic number that is used to check if the passed pointer is
|
||||
/// actually a malloc allocated memory.
|
||||
unsigned magic;
|
||||
/// @brief The size of the allocated memory, useful when doing a realloc.
|
||||
size_t size;
|
||||
} malloc_header_t;
|
||||
|
||||
/// @brief Extract the actual pointer to the allocated memory from the malloc header.
|
||||
/// @param header the header we are using.
|
||||
/// @return a pointer to the allocated memory.
|
||||
static inline void *malloc_header_to_ptr(malloc_header_t *header)
|
||||
{
|
||||
return (void *)((char *)header + sizeof(malloc_header_t));
|
||||
}
|
||||
|
||||
/// @brief Extract the malloc header, from the actual pointer to the allocated memory.
|
||||
/// @param ptr the pointer we use.
|
||||
/// @return the malloc header.
|
||||
static inline malloc_header_t *ptr_to_malloc_header(void *ptr)
|
||||
{
|
||||
return (malloc_header_t *)((char *)ptr - sizeof(malloc_header_t));
|
||||
}
|
||||
|
||||
void *malloc(unsigned int size)
|
||||
{
|
||||
assert(size && "Zero size requested.");
|
||||
size_t *ptr;
|
||||
// Compute the real size we need to allocate.
|
||||
size_t real_size = size + sizeof(malloc_header_t);
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
void *ptr;
|
||||
// Allocate the memory.
|
||||
__inline_syscall1(ptr, brk, real_size);
|
||||
__inline_syscall1(ptr, brk, size + sizeof(malloc_header_t));
|
||||
// Check for errors from the brk.
|
||||
if (ptr == 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Initialize the malloc header.
|
||||
malloc_header_t *malloc_header = (malloc_header_t *)ptr;
|
||||
malloc_header->magic = MALLOC_MAGIC_NUMBER;
|
||||
malloc_header->size = size;
|
||||
malloc_header_t *header = (malloc_header_t *)ptr;
|
||||
header->magic = MALLOC_MAGIC_NUMBER;
|
||||
header->size = size;
|
||||
// Return the allocated memory.
|
||||
return (void *)((char *)ptr + sizeof(malloc_header_t));
|
||||
return malloc_header_to_ptr(header);
|
||||
}
|
||||
|
||||
void *calloc(size_t num, size_t size)
|
||||
@@ -57,11 +82,11 @@ void *realloc(void *ptr, size_t size)
|
||||
return NULL;
|
||||
}
|
||||
// Get the malloc header.
|
||||
malloc_header_t *malloc_header = (malloc_header_t *)((char *)ptr - sizeof(malloc_header_t));
|
||||
malloc_header_t *header = ptr_to_malloc_header(ptr);
|
||||
// Check the header.
|
||||
assert(malloc_header->magic == MALLOC_MAGIC_NUMBER && "This is not a valid pointer.");
|
||||
assert(header->magic == MALLOC_MAGIC_NUMBER && "This is not a valid pointer.");
|
||||
// Get the old size.
|
||||
size_t old_size = malloc_header->size;
|
||||
size_t old_size = header->size;
|
||||
// Create the new pointer.
|
||||
void *newp = malloc(size);
|
||||
memset(newp, 0, size);
|
||||
@@ -73,14 +98,13 @@ void *realloc(void *ptr, size_t size)
|
||||
void free(void *ptr)
|
||||
{
|
||||
// Get the malloc header.
|
||||
malloc_header_t *malloc_header = (malloc_header_t *)((char *)ptr - sizeof(malloc_header_t));
|
||||
malloc_header_t *header = ptr_to_malloc_header(ptr);
|
||||
// Check the header.
|
||||
assert(malloc_header->magic == MALLOC_MAGIC_NUMBER && "This is not a valid pointer.");
|
||||
// Get the real pointer.
|
||||
assert(header->magic == MALLOC_MAGIC_NUMBER && "This is not a valid pointer.");
|
||||
ptr = (char *)ptr - sizeof(malloc_header_t);
|
||||
// Call the free.
|
||||
int _res;
|
||||
__inline_syscall1(_res, brk, ptr);
|
||||
__inline_syscall1(_res, brk, (char *)header);
|
||||
}
|
||||
|
||||
/// Seed used to generate random numbers.
|
||||
|
||||
+7
-7
@@ -221,7 +221,7 @@ char *strpbrk(const char *string, const char *control)
|
||||
int tokenize(const char *string, char *separators, size_t *offset, char *buffer, ssize_t buflen)
|
||||
{
|
||||
// If we reached the end of the parsed string, stop.
|
||||
if (string[*offset] == 0) {
|
||||
if ((*offset >= buflen) || (string[*offset] == 0)) {
|
||||
return 0;
|
||||
}
|
||||
// Keep copying character until we either reach 1) the end of the buffer, 2) a
|
||||
@@ -238,7 +238,8 @@ int tokenize(const char *string, char *separators, size_t *offset, char *buffer,
|
||||
}
|
||||
// Save the character.
|
||||
*buffer = string[*offset];
|
||||
// Advance the offset, decrese the available size in the buffer, and advance the buffer.
|
||||
// Advance the offset, decrese the available size in the buffer, and advance
|
||||
// the buffer.
|
||||
++(*offset), --buflen, ++buffer;
|
||||
} while ((buflen > 0) && (string[*offset] != 0));
|
||||
// Close the buffer.
|
||||
@@ -488,15 +489,14 @@ char *strcpy(char *dst, const char *src)
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
const char *it = s;
|
||||
while (*(++it) != 0) {}
|
||||
return ((it - s) < 0) ? 0 : (size_t)(it - s);
|
||||
for (; *it; it++);
|
||||
return (size_t)(it - s);
|
||||
}
|
||||
|
||||
size_t strnlen(const char *s, size_t count)
|
||||
{
|
||||
const char *it = s;
|
||||
while ((*(++it) != 0) && --count) {}
|
||||
return ((it - s) < 0) ? 0 : (size_t)(it - s);
|
||||
const char *p = memchr(s, 0, count);
|
||||
return p ? (size_t)(p-s) : count;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/// @file chmod.c
|
||||
/// @brief
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "sys/unistd.h"
|
||||
#include "sys/errno.h"
|
||||
#include "system/syscall_types.h"
|
||||
|
||||
_syscall2(int, chmod, const char *, pathname, mode_t, mode)
|
||||
|
||||
_syscall2(int, fchmod, int, fd, mode_t, mode)
|
||||
@@ -0,0 +1,14 @@
|
||||
/// @file chown.c
|
||||
/// @brief
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "sys/unistd.h"
|
||||
#include "sys/errno.h"
|
||||
#include "system/syscall_types.h"
|
||||
|
||||
_syscall3(int, chown, const char *, pathname, uid_t, owner, gid_t, group)
|
||||
|
||||
_syscall3(int, lchown, const char *, pathname, uid_t, owner, gid_t, group)
|
||||
|
||||
_syscall3(int, fchown, int, fd, uid_t, owner, gid_t, group)
|
||||
@@ -0,0 +1,10 @@
|
||||
/// @file dup.c
|
||||
/// @brief
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "sys/unistd.h"
|
||||
#include "system/syscall_types.h"
|
||||
#include "sys/errno.h"
|
||||
|
||||
_syscall1(int, dup, int, fd)
|
||||
@@ -8,3 +8,4 @@
|
||||
#include "system/syscall_types.h"
|
||||
|
||||
_syscall0(pid_t, getgid)
|
||||
_syscall0(gid_t, getegid)
|
||||
|
||||
@@ -8,3 +8,4 @@
|
||||
#include "system/syscall_types.h"
|
||||
|
||||
_syscall0(uid_t, getuid)
|
||||
_syscall0(uid_t, geteuid)
|
||||
|
||||
@@ -8,3 +8,4 @@
|
||||
#include "system/syscall_types.h"
|
||||
|
||||
_syscall1(int, setgid, pid_t, pid)
|
||||
_syscall2(int, setregid, gid_t, rgid, gid_t, egid)
|
||||
|
||||
@@ -8,3 +8,4 @@
|
||||
#include "system/syscall_types.h"
|
||||
|
||||
_syscall1(int, setuid, uid_t, pid)
|
||||
_syscall2(int, setreuid, uid_t, ruid, uid_t, euid)
|
||||
|
||||
@@ -31,12 +31,14 @@ set(KERNEL_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/devices/pci.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/devices/fpu.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/ata.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/mem.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/rtc.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/fdc.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/mouse.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/ps2.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/keyboard/keyboard.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/drivers/keyboard/keymap.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/fs/attr.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/fs/vfs.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/fs/read_write.c
|
||||
${CMAKE_SOURCE_DIR}/mentos/src/fs/open.c
|
||||
@@ -191,7 +193,7 @@ endif()
|
||||
|
||||
# =============================================================================
|
||||
# Set the list of valid keyboard mappings.
|
||||
set(KEYMAP_TYPES KEYMAP_US KEYMAP_IT)
|
||||
set(KEYMAP_TYPES KEYMAP_US KEYMAP_IT KEYMAP_DE)
|
||||
# Add the keyboard mapping.
|
||||
set(KEYMAP_TYPE "KEYMAP_US" CACHE STRING "Chose the type of keyboard mapping: ${KEYMAP_TYPES}")
|
||||
# List of keyboard mappings.
|
||||
|
||||
@@ -282,6 +282,10 @@ void pci_remap(void);
|
||||
/// @return interrupt number.
|
||||
int pci_get_interrupt(uint32_t device);
|
||||
|
||||
/// @brief Dumps on DEBUG, the information about the given device.
|
||||
/// @param device the device.
|
||||
/// @param vendorid the ID of the vendor.
|
||||
/// @param deviceid the ID of the device.
|
||||
void pci_dump_device_data(uint32_t device, uint16_t vendorid, uint16_t deviceid);
|
||||
|
||||
/// @brief Prints all the devices connected to the PCI interfance.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
typedef enum {
|
||||
KEYMAP_IT, ///< Identifies the IT keyboard mapping.
|
||||
KEYMAP_US, ///< Identifies the US keyboard mapping.
|
||||
KEYMAP_DE, ///< Identifies the DE keyboard mapping.
|
||||
KEYMAP_TYPE_MAX ///< The delimiter for the keyboard types.
|
||||
} keymap_type_t;
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/// @file mem.h
|
||||
/// @brief Drivers for memory devices
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
/// @addtogroup drivers Device Drivers
|
||||
/// @{
|
||||
/// @addtogroup mem Memory devices
|
||||
/// @brief Drivers for memory devices.
|
||||
/// @{
|
||||
|
||||
#pragma once
|
||||
|
||||
/// @brief Initializes the memory devices.
|
||||
/// @return 0 on success, 1 on error.
|
||||
int mem_devs_initialize(void);
|
||||
|
||||
/// @}
|
||||
/// @}
|
||||
@@ -0,0 +1,16 @@
|
||||
/// @file attr.h
|
||||
/// @brief change file attributes
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
int sys_chown(const char* path, uid_t owner, gid_t group);
|
||||
|
||||
int sys_lchown(const char* path, uid_t owner, gid_t group);
|
||||
|
||||
int sys_fchown(int fd, uid_t owner, gid_t group);
|
||||
|
||||
int sys_chmod(const char* path, mode_t mode);
|
||||
|
||||
int sys_fchmod(int fd, mode_t mode);
|
||||
@@ -187,3 +187,25 @@ int vfs_dup_task(struct task_struct *new_task, struct task_struct *old_task);
|
||||
/// @param task The task for which we destroy the file descriptor list.
|
||||
/// @return 0 on fail, 1 on success.
|
||||
int vfs_destroy_task(struct task_struct *task);
|
||||
|
||||
/// @brief Find the smallest available fd.
|
||||
/// @return -errno on fail, fd on success.
|
||||
int get_unused_fd(void);
|
||||
|
||||
/// @brief Return new smallest available file desriptor.
|
||||
/// @return -errno on fail, fd on success.
|
||||
int sys_dup(int fd);
|
||||
|
||||
/// @brief Check if the requested open flags against the file mask
|
||||
/// @param flags The requested open flags.
|
||||
/// @param mode The permissions of the file.
|
||||
/// @param uid The owner of the task opening the file.
|
||||
/// @param gid The group of the task opening the file.
|
||||
/// @return 0 on fail, 1 on success.
|
||||
int vfs_valid_open_permissions(int flags, mode_t mask, uid_t uid, gid_t gid);
|
||||
|
||||
/// @brief Check if the file is exectuable
|
||||
/// @param task The task to execute the file.
|
||||
/// @param file The file to execute.
|
||||
/// @return 0 on fail, 1 on success.
|
||||
int vfs_valid_exec_permission(struct task_struct *task, vfs_file_t *file);
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
/// Forward declaration of the VFS file.
|
||||
typedef struct vfs_file_t vfs_file_t;
|
||||
|
||||
/// Forward declaration of the inode attributes.
|
||||
struct iattr;
|
||||
|
||||
/// Function used to create a directory.
|
||||
typedef int (*vfs_mkdir_callback)(const char *, mode_t);
|
||||
/// Function used to remove a directory.
|
||||
@@ -48,6 +51,10 @@ typedef int (*vfs_ioctl_callback)(vfs_file_t *, int, void *);
|
||||
typedef int (*vfs_symlink_callback)(const char *, const char *);
|
||||
/// Function that reads the symbolic link data associated with a file.
|
||||
typedef ssize_t (*vfs_readlink_callback)(vfs_file_t *, char *, size_t);
|
||||
/// Function used to modify the attributes of an fs entry.
|
||||
typedef int (*vfs_setattr_callback)(const char *, struct iattr *);
|
||||
/// Function used to modify the attributes of a file.
|
||||
typedef int (*vfs_fsetattr_callback)(vfs_file_t *, struct iattr *);
|
||||
|
||||
/// @brief Filesystem information.
|
||||
typedef struct file_system_type {
|
||||
@@ -71,6 +78,8 @@ typedef struct vfs_sys_operations_t {
|
||||
vfs_creat_callback creat_f;
|
||||
/// Symbolic link creation function.
|
||||
vfs_symlink_callback symlink_f;
|
||||
/// Modifies the attributes of a file.
|
||||
vfs_setattr_callback setattr_f;
|
||||
} vfs_sys_operations_t;
|
||||
|
||||
/// @brief Set of functions used to perform operations on files.
|
||||
@@ -95,6 +104,8 @@ typedef struct vfs_file_operations_t {
|
||||
vfs_getdents_callback getdents_f;
|
||||
/// Reads the symbolik link data.
|
||||
vfs_readlink_callback readlink_f;
|
||||
/// Modifies the attributes of a file.
|
||||
vfs_fsetattr_callback setattr_f;
|
||||
} vfs_file_operations_t;
|
||||
|
||||
/// @brief Data structure that contains information about the mounted filesystems.
|
||||
@@ -162,3 +173,30 @@ typedef struct vfs_file_descriptor_t {
|
||||
/// Flags for file opening modes.
|
||||
int flags_mask;
|
||||
} vfs_file_descriptor_t;
|
||||
|
||||
/// @brief Data structure containing attributes of a file.
|
||||
struct iattr {
|
||||
unsigned int ia_valid;
|
||||
mode_t ia_mode;
|
||||
uid_t ia_uid;
|
||||
gid_t ia_gid;
|
||||
uint32_t ia_atime;
|
||||
uint32_t ia_mtime;
|
||||
uint32_t ia_ctime;
|
||||
};
|
||||
|
||||
#define ATTR_MODE (1 << 0)
|
||||
#define ATTR_UID (1 << 1)
|
||||
#define ATTR_GID (1 << 2)
|
||||
#define ATTR_ATIME (1 << 3)
|
||||
#define ATTR_MTIME (1 << 4)
|
||||
#define ATTR_CTIME (1 << 5)
|
||||
|
||||
#define IATTR_CHOWN(user, group) \
|
||||
{ .ia_valid = ATTR_UID | ATTR_GID, \
|
||||
.ia_uid = user, \
|
||||
.ia_gid = group }
|
||||
|
||||
#define IATTR_CHMOD(mode) \
|
||||
{ .ia_valid = ATTR_MODE, \
|
||||
.ia_mode = mode }
|
||||
|
||||
@@ -137,11 +137,15 @@ typedef struct mm_struct_t {
|
||||
/// @brief Cache used to store page tables.
|
||||
extern kmem_cache_t *pgtbl_cache;
|
||||
|
||||
static inline int vm_area_compare(const list_head *a, const list_head *b)
|
||||
/// @brief Comparison function between virtual memory areas.
|
||||
/// @param vma0 the first vm_area.
|
||||
/// @param vma1 the second vm_area.
|
||||
/// @return true if vma0 is after vma1.
|
||||
static inline int vm_area_compare(const list_head *vma0, const list_head *vma1)
|
||||
{
|
||||
vm_area_struct_t *_a = list_entry(a, vm_area_struct_t, vm_list);
|
||||
vm_area_struct_t *_b = list_entry(b, vm_area_struct_t, vm_list);
|
||||
return _a->vm_start > _b->vm_end;
|
||||
vm_area_struct_t *_vma0 = list_entry(vma0, vm_area_struct_t, vm_list);
|
||||
vm_area_struct_t *_vma1 = list_entry(vma1, vm_area_struct_t, vm_list);
|
||||
return _vma0->vm_start > _vma1->vm_end;
|
||||
}
|
||||
|
||||
/// @brief Initializes paging
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
/// @brief Type for slab flags.
|
||||
typedef unsigned int slab_flags_t;
|
||||
|
||||
/// @brief Type of function used as constructor/destructor for cache creation and destruction.
|
||||
typedef void (*kmem_fun_t)(void *);
|
||||
|
||||
/// Create a new cache.
|
||||
|
||||
@@ -87,9 +87,13 @@ typedef struct task_struct {
|
||||
/// The Process Group Id of the process
|
||||
pid_t pgid;
|
||||
/// The Group ID (GID) of the process
|
||||
pid_t rgid;
|
||||
/// The effective Group ID (GID) of the process
|
||||
pid_t gid;
|
||||
/// The User ID (UID) of the user owning the process.
|
||||
pid_t uid;
|
||||
uid_t ruid;
|
||||
/// The effective User ID (UID) of the process.
|
||||
uid_t uid;
|
||||
// -1 unrunnable, 0 runnable, >0 stopped.
|
||||
/// The current state of the process:
|
||||
__volatile__ long state;
|
||||
|
||||
@@ -131,21 +131,32 @@ pid_t sys_getpgid(pid_t pid);
|
||||
/// @return returns zero. On error, -1 is returned, and errno is set appropriately.
|
||||
int sys_setpgid(pid_t pid, pid_t pgid);
|
||||
|
||||
///@brief returns the group ID of the calling process.
|
||||
///@brief returns the real group ID of the calling process.
|
||||
///@return GID of the current process
|
||||
pid_t sys_getgid(void);
|
||||
gid_t sys_getgid(void);
|
||||
|
||||
///@brief sets the effective group ID of the calling process.
|
||||
///@param pid process identifier to
|
||||
///@brief sets the group ID of the calling process.
|
||||
///@param gid group id
|
||||
///@return On success, zero is returned.
|
||||
/// Otherwise returns -1 with errno set to :EINVAL or EPERM.
|
||||
int sys_setgid(pid_t pid);
|
||||
int sys_setgid(gid_t gid);
|
||||
|
||||
///@brief returns the effective group ID of the calling process.
|
||||
///@return GID of the current process
|
||||
gid_t sys_getegid(void);
|
||||
|
||||
///@brief sets the real and effective group ID of the calling process.
|
||||
///@param rgid real group id
|
||||
///@param egid effective group id
|
||||
///@return On success, zero is returned.
|
||||
/// Otherwise returns -1 with errno set to EPERM.
|
||||
int sys_setregid(gid_t rgid, gid_t egid);
|
||||
|
||||
/// @brief Returns the parent process ID (PPID) of the calling process.
|
||||
/// @return The parent process ID.
|
||||
pid_t sys_getppid(void);
|
||||
|
||||
/// @brief Returns the User ID (UID) of the calling process.
|
||||
/// @brief Returns the real User ID (UID) of the calling process.
|
||||
/// @return The User ID.
|
||||
uid_t sys_getuid(void);
|
||||
|
||||
@@ -155,6 +166,17 @@ uid_t sys_getuid(void);
|
||||
/// Otherwise returns -1 with errno set to :EINVAL or EPERM.
|
||||
int sys_setuid(uid_t uid);
|
||||
|
||||
/// @brief Returns the effective User ID (UID) of the calling process.
|
||||
/// @return The User ID.
|
||||
uid_t sys_geteuid(void);
|
||||
|
||||
/// @brief Set the real and effective User ID (UID) of the calling process.
|
||||
/// @param ruid the new real User ID.
|
||||
/// @param euid the new effective User ID.
|
||||
///@return On success, zero is returned.
|
||||
/// Otherwise returns -1 with errno set to EPERM.
|
||||
int sys_setreuid(uid_t ruid, uid_t euid);
|
||||
|
||||
/// @brief Adds the increment to the priority value of the task.
|
||||
/// @param increment The modifier to apply to the nice value.
|
||||
/// @return The new nice value.
|
||||
@@ -218,7 +240,7 @@ int sys_rmdir(const char *path);
|
||||
int sys_creat(const char *path, mode_t mode);
|
||||
|
||||
/// @brief Read the symbolic link, if present.
|
||||
/// @param file the file for which we want to read the symbolic link information.
|
||||
/// @param path the file for which we want to read the symbolic link information.
|
||||
/// @param buffer the buffer where we will store the symbolic link path.
|
||||
/// @param bufsize the size of the buffer.
|
||||
/// @return The number of read characters on success, -1 otherwise and errno is set to indicate the error.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "descriptor_tables/idt.h"
|
||||
#include "stdio.h"
|
||||
|
||||
// Default error messages for exceptions.
|
||||
/// @brief Default error messages for exceptions.
|
||||
static const char *exception_messages[32] = {
|
||||
"Division by zero",
|
||||
"Debug",
|
||||
|
||||
@@ -32,7 +32,8 @@ static list_head shared_interrupt_handlers[IRQ_NUM];
|
||||
/// Cache where we will store the data regarding an irq service.
|
||||
static kmem_cache_t *irq_cache;
|
||||
|
||||
/// @brief Creates a new irq struct.
|
||||
/// @brief Creates a new irq structure.
|
||||
/// @return a pointer to the newly created irq structure.
|
||||
static inline irq_struct_t *__irq_struct_alloc(void)
|
||||
{
|
||||
// Allocate the structure.
|
||||
@@ -46,6 +47,7 @@ static inline irq_struct_t *__irq_struct_alloc(void)
|
||||
}
|
||||
|
||||
/// @brief Destroys an irq struct.
|
||||
/// @param irq_struct the structure we need to destroy.
|
||||
static inline void __irq_struct_dealloc(irq_struct_t *irq_struct)
|
||||
{
|
||||
list_head_remove(&irq_struct->siblings);
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "string.h"
|
||||
#include "descriptor_tables/gdt.h"
|
||||
|
||||
/// @brief The kernel
|
||||
///
|
||||
static tss_entry_t kernel_tss;
|
||||
|
||||
void tss_init(uint8_t idx, uint32_t ss0)
|
||||
|
||||
@@ -60,6 +60,7 @@ static inline void __disable_fpu(void)
|
||||
}
|
||||
|
||||
/// @brief Restore the FPU for a process.
|
||||
/// @param proc the process for which we are restoring the FPU registers.
|
||||
static inline void __restore_fpu(task_struct *proc)
|
||||
{
|
||||
assert(proc && "Trying to restore FPU of NULL process.");
|
||||
@@ -69,7 +70,8 @@ static inline void __restore_fpu(task_struct *proc)
|
||||
__asm__ __volatile__("fxrstor (%0)" ::"r"(saves));
|
||||
}
|
||||
|
||||
/// Save the FPU for a process.
|
||||
/// @brief Save the FPU for a process.
|
||||
/// @param proc the process for which we are saving the FPU registers.
|
||||
static inline void __save_fpu(task_struct *proc)
|
||||
{
|
||||
assert(proc && "Trying to save FPU of NULL process.");
|
||||
@@ -129,6 +131,7 @@ static inline void __sigfpe_handler(pt_regs *f)
|
||||
/// @details
|
||||
/// For processors without a FPU, this tests that maths libraries link
|
||||
/// correctly.
|
||||
/// @return 1 on success, 0 on failure.
|
||||
static int __fpu_test(void)
|
||||
{
|
||||
double a = M_PI;
|
||||
|
||||
+84
-12
@@ -245,10 +245,14 @@ typedef struct ata_device_t {
|
||||
#define ATA_SECTOR_SIZE 512 ///< The sector size.
|
||||
#define ATA_DMA_SIZE 512 ///< The size of the DMA area.
|
||||
|
||||
/// @brief Keeps track of the incremental letters for the ATA drives.
|
||||
static char ata_drive_char = 'a';
|
||||
static int cdrom_number = 0;
|
||||
static uint32_t ata_pci = 0x00000000;
|
||||
/// @brief Keeps track of the incremental number for removable media.
|
||||
static int cdrom_number = 0;
|
||||
/// @brief We store the ATA pci address here.
|
||||
static uint32_t ata_pci = 0x00000000;
|
||||
|
||||
/// @brief The ATA primary master control register locations.
|
||||
static ata_device_t ata_primary_master = {
|
||||
.io_base = 0x1F0,
|
||||
.io_reg = {
|
||||
@@ -270,6 +274,7 @@ static ata_device_t ata_primary_master = {
|
||||
.slave = 0
|
||||
};
|
||||
|
||||
/// @brief The ATA primary slave control register locations.
|
||||
static ata_device_t ata_primary_slave = {
|
||||
.io_base = 0x1F0,
|
||||
.io_reg = {
|
||||
@@ -291,6 +296,7 @@ static ata_device_t ata_primary_slave = {
|
||||
.slave = 1
|
||||
};
|
||||
|
||||
/// @brief The ATA secondary master control register locations.
|
||||
static ata_device_t ata_secondary_master = {
|
||||
.io_base = 0x170,
|
||||
.io_reg = {
|
||||
@@ -312,6 +318,7 @@ static ata_device_t ata_secondary_master = {
|
||||
.slave = 0
|
||||
};
|
||||
|
||||
/// @brief The ATA secondary slave control register locations.
|
||||
static ata_device_t ata_secondary_slave = {
|
||||
.io_base = 0x170,
|
||||
.io_reg = {
|
||||
@@ -335,6 +342,9 @@ static ata_device_t ata_secondary_slave = {
|
||||
|
||||
// == SUPPORT FUNCTIONS =======================================================
|
||||
|
||||
/// @brief Returns the set of ATA errors as a string.
|
||||
/// @param error the variable containing all the error flags.
|
||||
/// @return the string with the list of errors.
|
||||
static inline const char *ata_get_device_error_str(uint8_t error)
|
||||
{
|
||||
static char str[50] = { 0 };
|
||||
@@ -366,6 +376,9 @@ static inline const char *ata_get_device_error_str(uint8_t error)
|
||||
return str;
|
||||
}
|
||||
|
||||
/// @brief Returns the device status as a string.
|
||||
/// @param status the device status.
|
||||
/// @return the device status as string.
|
||||
static inline const char *ata_get_device_status_str(uint8_t status)
|
||||
{
|
||||
static char str[50] = { 0 };
|
||||
@@ -397,11 +410,17 @@ static inline const char *ata_get_device_status_str(uint8_t status)
|
||||
return str;
|
||||
}
|
||||
|
||||
/// @brief Returns the device configuration as string.
|
||||
/// @param dev the devce.
|
||||
/// @return the device configuration as string.
|
||||
static inline const char *ata_get_device_settings_str(ata_device_t *dev)
|
||||
{
|
||||
return (dev->primary) ? ((dev->master) ? "Primary Master" : "Primary Slave") : ((dev->master) ? "Secondary Master" : "Secondary Slave");
|
||||
}
|
||||
|
||||
/// @brief Returns the device type as string.
|
||||
/// @param type the device type value.
|
||||
/// @return the device type as string.
|
||||
static inline const char *ata_get_device_type_str(ata_device_type_t type)
|
||||
{
|
||||
if (type == ata_dev_type_pata) {
|
||||
@@ -496,6 +515,7 @@ static inline void ata_io_wait(ata_device_t *dev)
|
||||
/// @param dev the device we need to wait for.
|
||||
/// @param mask the mask we use to access those bits.
|
||||
/// @param timeout the maximum number of cycles we are going to wait.
|
||||
/// @return 1 on success, 0 if it times out.
|
||||
static inline int ata_status_wait_not(ata_device_t *dev, long mask, long timeout)
|
||||
{
|
||||
uint8_t status;
|
||||
@@ -511,6 +531,8 @@ static inline int ata_status_wait_not(ata_device_t *dev, long mask, long timeout
|
||||
/// @brief Wait until the status bits selected through the mask are one.
|
||||
/// @param dev the device we need to wait for.
|
||||
/// @param mask the mask we use to access those bits.
|
||||
/// @param timeout the maximum number of cycles we are going to wait.
|
||||
/// @return 1 on success, 0 if it times out.
|
||||
static inline int ata_status_wait_for(ata_device_t *dev, long mask, long timeout)
|
||||
{
|
||||
uint8_t status;
|
||||
@@ -608,7 +630,6 @@ static inline uintptr_t ata_dma_malloc(size_t size, uintptr_t *physical)
|
||||
}
|
||||
|
||||
/// @brief Emables bus mastering, allowing Direct Memory Access (DMA) transactions.
|
||||
/// @param dev the device for which we enable bus mastering.
|
||||
static inline void ata_dma_enable_bus_mastering(void)
|
||||
{
|
||||
uint32_t pci_cmd = pci_read_32(ata_pci, PCI_COMMAND);
|
||||
@@ -662,7 +683,9 @@ static inline void ata_dma_initialize_bus_mastering_address(ata_device_t *dev)
|
||||
|
||||
// == ATA DEVICE MANAGEMENT ===================================================
|
||||
|
||||
/* on Primary bus: ctrl->base =0x1F0, ctrl->dev_ctl =0x3F6. REG_CYL_LO=4, REG_CYL_HI=5, REG_DEVSEL=6 */
|
||||
/// @brief Detects the type of device.
|
||||
/// @param dev the device for which we are checking the type.
|
||||
/// @return the device type.
|
||||
static inline ata_device_type_t ata_detect_device_type(ata_device_t *dev)
|
||||
{
|
||||
pr_debug("[%s] Detecting device type...\n", ata_get_device_settings_str(dev));
|
||||
@@ -730,6 +753,9 @@ static inline ata_device_type_t ata_detect_device_type(ata_device_t *dev)
|
||||
return ata_dev_type_unknown;
|
||||
}
|
||||
|
||||
/// @brief Initialises the given device.
|
||||
/// @param dev the device to initialize.
|
||||
/// @return 0 on success, 1 on error.
|
||||
static bool_t ata_device_init(ata_device_t *dev)
|
||||
{
|
||||
pr_debug("[%s] Initializing ATA device...\n", ata_get_device_settings_str(dev));
|
||||
@@ -761,6 +787,11 @@ static bool_t ata_device_init(ata_device_t *dev)
|
||||
}
|
||||
|
||||
// == ATA SECTOR READ/WRITE FUNCTIONS =========================================
|
||||
|
||||
/// @brief Reads an ATA sector.
|
||||
/// @param dev the device on which we perform the read.
|
||||
/// @param lba_sector the sector where we write.
|
||||
/// @param buffer the buffer we are writing.
|
||||
static void ata_device_read_sector(ata_device_t *dev, uint32_t lba_sector, uint8_t *buffer)
|
||||
{
|
||||
// Check if we are trying to perform the read on the correct drive type.
|
||||
@@ -843,6 +874,10 @@ static void ata_device_read_sector(ata_device_t *dev, uint32_t lba_sector, uint8
|
||||
spinlock_unlock(&dev->lock);
|
||||
}
|
||||
|
||||
/// @brief Writs an ATA sector.
|
||||
/// @param dev the device on which we perform the write.
|
||||
/// @param lba_sector the sector where we read.
|
||||
/// @param buffer the buffer where we store what we read.
|
||||
static void ata_device_write_sector(ata_device_t *dev, uint32_t lba_sector, uint8_t *buffer)
|
||||
{
|
||||
spinlock_lock(&dev->lock);
|
||||
@@ -912,6 +947,12 @@ static void ata_device_write_sector(ata_device_t *dev, uint32_t lba_sector, uint
|
||||
}
|
||||
|
||||
// == VFS CALLBACKS ===========================================================
|
||||
|
||||
/// @brief Implements the open function for an ATA device.
|
||||
/// @param path the phat to the device we want to open.
|
||||
/// @param flags we ignore these.
|
||||
/// @param mode we currently ignore this.
|
||||
/// @return the VFS file associated with the device.
|
||||
static vfs_file_t *ata_open(const char *path, int flags, mode_t mode)
|
||||
{
|
||||
pr_debug("ata_open(%s, %d, %d)\n", path, flags, mode);
|
||||
@@ -934,6 +975,9 @@ static vfs_file_t *ata_open(const char *path, int flags, mode_t mode)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// @brief Closes an ATA device.
|
||||
/// @param file the VFS file associated with the ATA device.
|
||||
/// @return 0 on success, it panics on failure.
|
||||
static int ata_close(vfs_file_t *file)
|
||||
{
|
||||
pr_debug("ata_close(%p)\n", file);
|
||||
@@ -951,6 +995,12 @@ static int ata_close(vfs_file_t *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Reads from an ATA device.
|
||||
/// @param file the VFS file associated with the ATA device.
|
||||
/// @param buffer the buffer where we store what we read.
|
||||
/// @param offset the offset where we want to read.
|
||||
/// @param size the size of the buffer.
|
||||
/// @return the number of read characters.
|
||||
static ssize_t ata_read(vfs_file_t *file, char *buffer, off_t offset, size_t size)
|
||||
{
|
||||
// pr_debug("ata_read(file: 0x%p, buffer: 0x%p, offest: %8d, size: %8d)\n", file, buffer, offset, size);
|
||||
@@ -1014,6 +1064,12 @@ static ssize_t ata_read(vfs_file_t *file, char *buffer, off_t offset, size_t siz
|
||||
return size;
|
||||
}
|
||||
|
||||
/// @brief Writes on an ATA device.
|
||||
/// @param file the VFS file associated with the ATA device.
|
||||
/// @param buffer the buffer we use to write.
|
||||
/// @param offset the offset where we want to write.
|
||||
/// @param size the size of the buffer.
|
||||
/// @return the number of written characters.
|
||||
static ssize_t ata_write(vfs_file_t *file, const void *buffer, off_t offset, size_t size)
|
||||
{
|
||||
pr_debug("ata_write(%p, %p, %d, %d)\n", file, buffer, offset, size);
|
||||
@@ -1072,6 +1128,10 @@ static ssize_t ata_write(vfs_file_t *file, const void *buffer, off_t offset, siz
|
||||
return size;
|
||||
}
|
||||
|
||||
/// @brief Stats an ATA device.
|
||||
/// @param dev the ATA device.
|
||||
/// @param stat the stat buffer.
|
||||
/// @return 0 on success.
|
||||
static int _ata_stat(const ata_device_t *dev, stat_t *stat)
|
||||
{
|
||||
if (dev && dev->fs_root) {
|
||||
@@ -1089,19 +1149,19 @@ static int _ata_stat(const ata_device_t *dev, stat_t *stat)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Retrieves information concerning the file at the given position.
|
||||
/// @param fid The file struct.
|
||||
/// @param stat The structure where the information are stored.
|
||||
/// @return 0 if success.
|
||||
/// @brief Retrieves information concerning the file at the given position.
|
||||
/// @param file the file.
|
||||
/// @param stat the structure where the information are stored.
|
||||
/// @return 0 if success.
|
||||
static int ata_fstat(vfs_file_t *file, stat_t *stat)
|
||||
{
|
||||
return _ata_stat(file->device, stat);
|
||||
}
|
||||
|
||||
/// @brief Retrieves information concerning the file at the given position.
|
||||
/// @param path The path where the file resides.
|
||||
/// @param stat The structure where the information are stored.
|
||||
/// @return 0 if success.
|
||||
/// @brief Retrieves information concerning the file at the given position.
|
||||
/// @param path the path where the file resides.
|
||||
/// @param stat the structure where the information are stored.
|
||||
/// @return 0 if success.
|
||||
static int ata_stat(const char *path, stat_t *stat)
|
||||
{
|
||||
super_block_t *sb = vfs_get_superblock(path);
|
||||
@@ -1135,6 +1195,9 @@ static vfs_file_operations_t ata_fs_operations = {
|
||||
.readlink_f = NULL,
|
||||
};
|
||||
|
||||
/// @brief Creates a VFS file, starting from an ATA device.
|
||||
/// @param dev the ATA device.
|
||||
/// @return a pointer to the VFS file on success, NULL on failure.
|
||||
static vfs_file_t *ata_device_create(ata_device_t *dev)
|
||||
{
|
||||
// Create the file.
|
||||
@@ -1155,6 +1218,9 @@ static vfs_file_t *ata_device_create(ata_device_t *dev)
|
||||
return file;
|
||||
}
|
||||
|
||||
/// @brief Detects and mount the given ATA device.
|
||||
/// @param dev the device we want to handle.
|
||||
/// @return the type of device.
|
||||
static ata_device_type_t ata_device_detect(ata_device_t *dev)
|
||||
{
|
||||
// Perform a soft reset.
|
||||
@@ -1232,6 +1298,12 @@ static void ata_irq_handler_slave(pt_regs *f)
|
||||
}
|
||||
|
||||
// == PCI FUNCTIONS ===========================================================
|
||||
|
||||
/// @brief Used while scanning the PCI interface.
|
||||
/// @param device the device we want to find.
|
||||
/// @param vendorid its vendor ID.
|
||||
/// @param deviceid its device ID.
|
||||
/// @param extra the devoce once we find it.
|
||||
static void pci_find_ata(uint32_t device, uint16_t vendorid, uint16_t deviceid, void *extra)
|
||||
{
|
||||
// Intel Corporation AND (IDE Interface OR PIIX4 IDE)
|
||||
|
||||
@@ -139,7 +139,7 @@ void init_keymaps(void)
|
||||
|
||||
keymaps[KEYMAP_IT][KEY_KP_DEC] = (keymap_t){ 0x532E, 0x532E, 0x5300, 0x5300 }; // 0x0053
|
||||
|
||||
// == ITALIAN KEY MAPPING =================================================
|
||||
// == US KEY MAPPING =================================================
|
||||
// Keys Normal Shifted Ctrl Alt
|
||||
keymaps[KEYMAP_US][KEY_A] = (keymap_t){ 0x1E61, 0x1E41, 0x1E01, 0x1E00 }; // 0x001E A
|
||||
keymaps[KEYMAP_US][KEY_B] = (keymap_t){ 0x3062, 0x3042, 0x3002, 0x3000 }; // 0x0030 B
|
||||
@@ -240,6 +240,110 @@ void init_keymaps(void)
|
||||
keymaps[KEYMAP_US][KEY_KP0] = (keymap_t){ 0x5230, 0x5230, 0x5200, 0x5200 }; // 0x0052
|
||||
|
||||
keymaps[KEYMAP_US][KEY_KP_DEC] = (keymap_t){ 0x532E, 0x532E, 0x5300, 0x5300 }; // 0x0053
|
||||
|
||||
// == GERMAN KEY MAPPING =================================================
|
||||
// TODO: Currently the german umlauts are replaced by their "base" vowel
|
||||
// Keys Normal Shifted Ctrl Alt
|
||||
keymaps[KEYMAP_DE][KEY_A] = (keymap_t){ 0x1E61, 0x1E41, 0x1E01, 0x1E00 }; // 0x001E A
|
||||
keymaps[KEYMAP_DE][KEY_B] = (keymap_t){ 0x3062, 0x3042, 0x3002, 0x3000 }; // 0x0030 B
|
||||
keymaps[KEYMAP_DE][KEY_C] = (keymap_t){ 0x2E63, 0x2E43, 0x2E03, 0x2E00 }; // 0x002E C
|
||||
keymaps[KEYMAP_DE][KEY_D] = (keymap_t){ 0x2064, 0x2044, 0x2004, 0x2000 }; // 0x0020 D
|
||||
keymaps[KEYMAP_DE][KEY_E] = (keymap_t){ 0x1265, 0x1245, 0x1205, 0x1200 }; // 0x0012 E
|
||||
keymaps[KEYMAP_DE][KEY_F] = (keymap_t){ 0x2166, 0x2146, 0x2106, 0x2100 }; // 0x0021 F
|
||||
keymaps[KEYMAP_DE][KEY_G] = (keymap_t){ 0x2267, 0x2247, 0x2207, 0x2200 }; // 0x0022 G
|
||||
keymaps[KEYMAP_DE][KEY_H] = (keymap_t){ 0x2368, 0x2348, 0x2308, 0x2300 }; // 0x0023 H
|
||||
keymaps[KEYMAP_DE][KEY_I] = (keymap_t){ 0x1769, 0x1749, 0x1709, 0x1700 }; // 0x0017 I
|
||||
keymaps[KEYMAP_DE][KEY_J] = (keymap_t){ 0x246A, 0x244A, 0x240A, 0x2400 }; // 0x0024 J
|
||||
keymaps[KEYMAP_DE][KEY_K] = (keymap_t){ 0x256B, 0x254B, 0x250B, 0x2500 }; // 0x0025 K
|
||||
keymaps[KEYMAP_DE][KEY_L] = (keymap_t){ 0x266C, 0x264C, 0x260C, 0x2600 }; // 0x0026 L
|
||||
keymaps[KEYMAP_DE][KEY_M] = (keymap_t){ 0x326D, 0x324D, 0x320D, 0x3200 }; // 0x0032 M
|
||||
keymaps[KEYMAP_DE][KEY_N] = (keymap_t){ 0x316E, 0x314E, 0x310E, 0x3100 }; // 0x0031 N
|
||||
keymaps[KEYMAP_DE][KEY_O] = (keymap_t){ 0x186F, 0x184F, 0x180F, 0x1800 }; // 0x0018 O
|
||||
keymaps[KEYMAP_DE][KEY_P] = (keymap_t){ 0x1970, 0x1950, 0x1910, 0x1900 }; // 0x0019 P
|
||||
keymaps[KEYMAP_DE][KEY_Q] = (keymap_t){ 0x1071, 0x1051, 0x1011, 0x1040 }; // 0x0010 Q @
|
||||
keymaps[KEYMAP_DE][KEY_R] = (keymap_t){ 0x1372, 0x1352, 0x1312, 0x1300 }; // 0x0013 R
|
||||
keymaps[KEYMAP_DE][KEY_S] = (keymap_t){ 0x1F73, 0x1F53, 0x1F13, 0x1F00 }; // 0x001F S
|
||||
keymaps[KEYMAP_DE][KEY_T] = (keymap_t){ 0x1474, 0x1454, 0x1414, 0x1400 }; // 0x0014 T
|
||||
keymaps[KEYMAP_DE][KEY_U] = (keymap_t){ 0x1675, 0x1655, 0x1615, 0x1600 }; // 0x0016 U
|
||||
keymaps[KEYMAP_DE][KEY_V] = (keymap_t){ 0x2F76, 0x2F56, 0x2F16, 0x2F00 }; // 0x002F V
|
||||
keymaps[KEYMAP_DE][KEY_W] = (keymap_t){ 0x1177, 0x1157, 0x1117, 0x1100 }; // 0x0011 W
|
||||
keymaps[KEYMAP_DE][KEY_X] = (keymap_t){ 0x2D78, 0x2D58, 0x2D18, 0x2D00 }; // 0x002D X
|
||||
keymaps[KEYMAP_DE][KEY_Y] = (keymap_t){ 0x1579, 0x1559, 0x1519, 0x1500 }; // 0x0015 Y
|
||||
keymaps[KEYMAP_DE][KEY_Z] = (keymap_t){ 0x2C7A, 0x2C5A, 0x2C1A, 0x2C00 }; // 0x002C Z
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_1] = (keymap_t){ 0x0231, 0x0221, 0x0200, 0x0200 }; // 0x0002 1 !
|
||||
keymaps[KEYMAP_DE][KEY_2] = (keymap_t){ 0x0332, 0x0322, 0x0300, 0x0300 }; // 0x0003 2 "
|
||||
keymaps[KEYMAP_DE][KEY_3] = (keymap_t){ 0x0433, 0x2BA7, 0x0000, 0x0400 }; // 0x0004 3 §
|
||||
keymaps[KEYMAP_DE][KEY_4] = (keymap_t){ 0x0534, 0x0524, 0x0000, 0x7B00 }; // 0x0005 4 $
|
||||
keymaps[KEYMAP_DE][KEY_5] = (keymap_t){ 0x0635, 0x0625, 0x0000, 0x7C00 }; // 0x0006 5 %
|
||||
keymaps[KEYMAP_DE][KEY_6] = (keymap_t){ 0x0736, 0x0726, 0x071E, 0x7D00 }; // 0x0007 6 &
|
||||
keymaps[KEYMAP_DE][KEY_7] = (keymap_t){ 0x0837, 0x082F, 0x0000, 0x087B }; // 0x0008 7 / {
|
||||
keymaps[KEYMAP_DE][KEY_8] = (keymap_t){ 0x0938, 0x0928, 0x0000, 0x095B }; // 0x0009 8 ( [
|
||||
keymaps[KEYMAP_DE][KEY_9] = (keymap_t){ 0x0A39, 0x0A29, 0x0000, 0x0A5D }; // 0x000A 9 ) ]
|
||||
keymaps[KEYMAP_DE][KEY_0] = (keymap_t){ 0x0B30, 0x0B3D, 0x0000, 0x0B7D }; // 0x000B 0 = }
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_GRAVE] = (keymap_t){ 0x0D5E, 0x28A7, 0x0000, 0x2900 }; // 0x0029 ^ °
|
||||
keymaps[KEYMAP_DE][KEY_APOSTROPHE] = (keymap_t){ 0x0C27, 0x0C3F, 0x0000, 0x0C5C }; // 0x000C sz ? '\'
|
||||
keymaps[KEYMAP_DE][KEY_I_ACC] = (keymap_t){ 0x0D00, 0x0D00, 0x0000, 0x0000 }; // 0x000D ` ´
|
||||
keymaps[KEYMAP_DE][KEY_LEFT_BRAKET] = (keymap_t){ 0x1A75, 0x1A55, 0x0000, 0x0000 }; // 0x001A ü Ü
|
||||
keymaps[KEYMAP_DE][KEY_RIGHT_BRAKET] = (keymap_t){ 0x1B2B, 0x1B2A, 0x0000, 0x1B7E }; // 0x001B + * ~
|
||||
keymaps[KEYMAP_DE][KEY_SEMICOLON] = (keymap_t){ 0x276F, 0x274F, 0x0000, 0x0000 }; // 0x0027 ö Ö
|
||||
keymaps[KEYMAP_DE][KEY_DOUBLE_QUOTES] = (keymap_t){ 0x2861, 0x2841, 0x0000, 0x0000 }; // 0x0028 ä Ä
|
||||
keymaps[KEYMAP_DE][KEY_BACKSLASH] = (keymap_t){ 0x2B23, 0x2B27, 0x0000, 0x0000 }; // 0x002B # '
|
||||
keymaps[KEYMAP_DE][KEY_KP_LESS] = (keymap_t){ 0x563C, 0x563E, 0x0000, 0x567C }; // 0x0056 < > |
|
||||
keymaps[KEYMAP_DE][KEY_COMMA] = (keymap_t){ 0x332C, 0x333B, 0x0000, 0x3300 }; // 0x0033 , ;
|
||||
keymaps[KEYMAP_DE][KEY_PERIOD] = (keymap_t){ 0x342E, 0x343A, 0x0000, 0x3400 }; // 0x0034 . :
|
||||
keymaps[KEYMAP_DE][KEY_MINUS] = (keymap_t){ 0x352D, 0x355F, 0x0000, 0x0000 }; // 0x0035 - _
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_F1] = (keymap_t){ 0x3B00, 0x5400, 0x5E00, 0x6800 }; // 0x003B F1
|
||||
keymaps[KEYMAP_DE][KEY_F2] = (keymap_t){ 0x3C00, 0x5500, 0x5F00, 0x6900 }; // 0x003C F2
|
||||
keymaps[KEYMAP_DE][KEY_F3] = (keymap_t){ 0x3D00, 0x5600, 0x6000, 0x6A00 }; // 0x003D F3
|
||||
keymaps[KEYMAP_DE][KEY_F4] = (keymap_t){ 0x3E00, 0x5700, 0x6100, 0x6B00 }; // 0x003E F4
|
||||
keymaps[KEYMAP_DE][KEY_F5] = (keymap_t){ 0x3F00, 0x5800, 0x6200, 0x6C00 }; // 0x003F F5
|
||||
keymaps[KEYMAP_DE][KEY_F6] = (keymap_t){ 0x4000, 0x5900, 0x6300, 0x6D00 }; // 0x0040 F6
|
||||
keymaps[KEYMAP_DE][KEY_F7] = (keymap_t){ 0x4100, 0x5A00, 0x6400, 0x6E00 }; // 0x0041 F7
|
||||
keymaps[KEYMAP_DE][KEY_F8] = (keymap_t){ 0x4200, 0x5B00, 0x6500, 0x6F00 }; // 0x0042 F8
|
||||
keymaps[KEYMAP_DE][KEY_F9] = (keymap_t){ 0x4300, 0x5C00, 0x6600, 0x7000 }; // 0x0043 F9
|
||||
keymaps[KEYMAP_DE][KEY_F10] = (keymap_t){ 0x4400, 0x5D00, 0x6700, 0x7100 }; // 0x0044 F10
|
||||
keymaps[KEYMAP_DE][KEY_F11] = (keymap_t){ 0x5700, 0x5900, 0x5B00, 0x5D00 }; // 0x0057 F11
|
||||
keymaps[KEYMAP_DE][KEY_F12] = (keymap_t){ 0x5800, 0x5A00, 0x5C00, 0x5E00 }; // 0x0058 F12
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_BACKSPACE] = (keymap_t){ 0x0E08, 0x0E08, 0x0E7F, 0x0E00 }; // 0x000E BackSpace
|
||||
keymaps[KEYMAP_DE][KEY_ENTER] = (keymap_t){ 0x1C0D, 0x1C0D, 0x1C0A, 0xA600 }; // 0x001C Enter
|
||||
keymaps[KEYMAP_DE][KEY_ESCAPE] = (keymap_t){ 0x011B, 0x011B, 0x011B, 0x0100 }; // 0x0001 Esc
|
||||
keymaps[KEYMAP_DE][KEY_TAB] = (keymap_t){ 0x0F09, 0x0F00, 0x9400, 0xA500 }; // 0x000F Tab
|
||||
keymaps[KEYMAP_DE][KEY_SPACE] = (keymap_t){ 0x3920, 0x3920, 0x3920, 0x3920 }; // 0x0039 SpaceBar
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_INSERT] = (keymap_t){ 0x5200, 0x5230, 0x9200, 0xA200 }; // 0xE052 Ins
|
||||
keymaps[KEYMAP_DE][KEY_HOME] = (keymap_t){ 0x4700, 0x4737, 0x7700, 0x9700 }; // 0xE047 Home
|
||||
keymaps[KEYMAP_DE][KEY_PAGE_UP] = (keymap_t){ 0x4900, 0x4939, 0x8400, 0x9900 }; // 0xE049 PgUp
|
||||
keymaps[KEYMAP_DE][KEY_DELETE] = (keymap_t){ 0x5300, 0x532E, 0x9300, 0xA300 }; // 0xE053 Del
|
||||
keymaps[KEYMAP_DE][KEY_END] = (keymap_t){ 0x4F00, 0x4F31, 0x7500, 0x9F00 }; // 0xE04F End
|
||||
keymaps[KEYMAP_DE][KEY_PAGE_DOWN] = (keymap_t){ 0x5100, 0x5133, 0x7600, 0xA100 }; // 0xE051 PgDn
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_UP_ARROW] = (keymap_t){ 0x4800, 0x4838, 0x8D00, 0x9800 }; // 0xE048 Up Arrow
|
||||
keymaps[KEYMAP_DE][KEY_DOWN_ARROW] = (keymap_t){ 0x5000, 0x5032, 0x9100, 0xA000 }; // 0xE050 Down Arrow
|
||||
keymaps[KEYMAP_DE][KEY_LEFT_ARROW] = (keymap_t){ 0x4B00, 0x4B34, 0x7300, 0x9B00 }; // 0xE04B Left Arrow
|
||||
keymaps[KEYMAP_DE][KEY_RIGHT_ARROW] = (keymap_t){ 0x4D00, 0x4D36, 0x7400, 0x9D00 }; // 0xE04D Right Arrow
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_KP_DIV] = (keymap_t){ 0x352F, 0x352F, 0x3500, 0x3500 }; // 0xE035 Kp.Div
|
||||
keymaps[KEYMAP_DE][KEY_KP_MUL] = (keymap_t){ 0x372A, 0x372A, 0x3700, 0x3700 }; // 0x0037 Kp.Mul
|
||||
keymaps[KEYMAP_DE][KEY_KP_SUB] = (keymap_t){ 0x4A2D, 0x4A2D, 0x4A00, 0x4A00 }; // 0x004A Kp.Sub
|
||||
keymaps[KEYMAP_DE][KEY_KP_ADD] = (keymap_t){ 0x4E2B, 0x4E2B, 0x4E00, 0x4E00 }; // 0x004E Kp.Add
|
||||
keymaps[KEYMAP_DE][KEY_KP_RETURN] = (keymap_t){ 0xE01C, 0xE01C, 0x1C00, 0x1C00 }; // 0xE01C Kp.Enter
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_KP7] = (keymap_t){ 0x4737, 0x4737, 0x4700, 0x4700 }; // 0x0047
|
||||
keymaps[KEYMAP_DE][KEY_KP8] = (keymap_t){ 0x4838, 0x4838, 0x4800, 0x4800 }; // 0x0048
|
||||
keymaps[KEYMAP_DE][KEY_KP9] = (keymap_t){ 0x4939, 0x4939, 0x4900, 0x4900 }; // 0x0049
|
||||
keymaps[KEYMAP_DE][KEY_KP4] = (keymap_t){ 0x4B34, 0x4B34, 0x4B00, 0x4B00 }; // 0x004B
|
||||
keymaps[KEYMAP_DE][KEY_KP5] = (keymap_t){ 0x4C35, 0x4C35, 0x4C00, 0x4C00 }; // 0x004C
|
||||
keymaps[KEYMAP_DE][KEY_KP6] = (keymap_t){ 0x4D36, 0x4D36, 0x4D00, 0x4D00 }; // 0x004D
|
||||
keymaps[KEYMAP_DE][KEY_KP1] = (keymap_t){ 0x4F31, 0x4F31, 0x4F00, 0x4F00 }; // 0x004F
|
||||
keymaps[KEYMAP_DE][KEY_KP2] = (keymap_t){ 0x5032, 0x5032, 0x5000, 0x5000 }; // 0x0050
|
||||
keymaps[KEYMAP_DE][KEY_KP3] = (keymap_t){ 0x5133, 0x5133, 0x5100, 0x5100 }; // 0x0051
|
||||
keymaps[KEYMAP_DE][KEY_KP0] = (keymap_t){ 0x5230, 0x5230, 0x5200, 0x5200 }; // 0x0052
|
||||
|
||||
keymaps[KEYMAP_DE][KEY_KP_DEC] = (keymap_t){ 0x532E, 0x532E, 0x5300, 0x5300 }; // 0x0053
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/// @file mem.c
|
||||
/// @brief Memory devices.
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
// Include the kernel log levels.
|
||||
#include "sys/kernel_levels.h"
|
||||
/// Change the header.
|
||||
#define __DEBUG_HEADER__ "[MEMDEV ]"
|
||||
/// Set the log level.
|
||||
#define __DEBUG_LEVEL__ GLOBAL_LOGLEVEL
|
||||
|
||||
#include "assert.h"
|
||||
#include "drivers/mem.h"
|
||||
#include "io/debug.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "string.h"
|
||||
#include "sys/errno.h"
|
||||
#include "system/syscall.h"
|
||||
|
||||
struct memdev;
|
||||
|
||||
struct memdev {
|
||||
vfs_file_t *file;
|
||||
struct memdev *next;
|
||||
};
|
||||
|
||||
static struct memdev *devices;
|
||||
|
||||
static void add_device(struct memdev *device) {
|
||||
struct memdev *dit = devices;
|
||||
for (;dit != NULL; dit = dit->next);
|
||||
if (dit == NULL) {
|
||||
devices = device;
|
||||
} else {
|
||||
dit->next = device;
|
||||
}
|
||||
}
|
||||
|
||||
static vfs_file_t* find_device_file(const char *path) {
|
||||
for(struct memdev *dev = devices; dev != NULL; dev = dev->next) {
|
||||
if (strcmp(dev->file->name, path) == 0) {
|
||||
return dev->file;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mem_stat(const char* path, stat_t *stat);
|
||||
|
||||
static vfs_sys_operations_t mem_sys_operations = {
|
||||
.mkdir_f = NULL,
|
||||
.rmdir_f = NULL,
|
||||
.stat_f = mem_stat,
|
||||
};
|
||||
|
||||
static vfs_file_t *null_open(const char *path, int flags, mode_t mode);
|
||||
static int null_close(vfs_file_t * file);
|
||||
static ssize_t null_write(vfs_file_t * file, const void *buffer, off_t offset, size_t size);
|
||||
static ssize_t null_read(vfs_file_t * file, char *buffer, off_t offset, size_t size);
|
||||
static int null_fstat(vfs_file_t * file, stat_t *stat);
|
||||
|
||||
static vfs_file_operations_t null_fs_operations = {
|
||||
.open_f = null_open,
|
||||
.unlink_f = NULL,
|
||||
.close_f = null_close,
|
||||
.read_f = null_read,
|
||||
.write_f = null_write,
|
||||
.lseek_f = NULL,
|
||||
.stat_f = null_fstat,
|
||||
.ioctl_f = NULL,
|
||||
.getdents_f = NULL
|
||||
};
|
||||
|
||||
static struct memdev *null_device_create(const char* name) {
|
||||
// Create the device.
|
||||
struct memdev *dev = kmalloc(sizeof(struct memdev));
|
||||
dev->next = NULL;
|
||||
|
||||
// Create the file.
|
||||
vfs_file_t *file = kmem_cache_alloc(vfs_file_cache, GFP_KERNEL);
|
||||
if (file == NULL) {
|
||||
pr_err("Failed to create null device.\n");
|
||||
return NULL;
|
||||
}
|
||||
dev->file = file;
|
||||
|
||||
// Set the device name.
|
||||
strncpy(file->name, name, NAME_MAX);
|
||||
file->count = 0;
|
||||
file->uid = 0;
|
||||
file->gid = 0;
|
||||
file->mask = 0x2000 | 0666;
|
||||
file->atime = sys_time(NULL);
|
||||
file->mtime = sys_time(NULL);
|
||||
file->ctime = sys_time(NULL);
|
||||
file->length = 0;
|
||||
// Set the operations.
|
||||
file->sys_operations = &mem_sys_operations;
|
||||
file->fs_operations = &null_fs_operations;
|
||||
return dev;
|
||||
}
|
||||
|
||||
static vfs_file_t* null_open(const char *path, int flags, mode_t mode) {
|
||||
vfs_file_t* file = find_device_file(path);
|
||||
if (file) {
|
||||
file->count++;
|
||||
}
|
||||
// TODO: check permissions
|
||||
return file;
|
||||
}
|
||||
|
||||
static int null_close(vfs_file_t * file) {
|
||||
assert(file && "Received null file.");
|
||||
file->count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t null_write(vfs_file_t * file, const void *buffer, off_t offset, size_t size) {
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t null_read(vfs_file_t * file, char *buffer, off_t offset, size_t size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int null_fstat(vfs_file_t * file, stat_t *stat)
|
||||
{
|
||||
pr_debug("null_fstat(%s, %p)\n", file->name, stat);
|
||||
stat->st_dev = 0;
|
||||
stat->st_ino = 0;
|
||||
stat->st_mode = file->mask;
|
||||
stat->st_uid = file->uid;
|
||||
stat->st_gid = file->gid;
|
||||
stat->st_atime = file->atime;
|
||||
stat->st_mtime = file->mtime;
|
||||
stat->st_ctime = file->ctime;
|
||||
stat->st_size = file->length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mem_stat(const char *path, stat_t *stat) {
|
||||
vfs_file_t* file = find_device_file(path);
|
||||
|
||||
if (file) {
|
||||
return file->fs_operations->stat_f(file, stat);
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int mem_devs_initialize(void)
|
||||
{
|
||||
struct memdev *devnull = null_device_create("/dev/null");
|
||||
if (!devnull) {
|
||||
pr_err("Failed to create devnull");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!vfs_mount("/dev/null", devnull->file)) {
|
||||
pr_err("Failed to mount /dev/null");
|
||||
return 1;
|
||||
}
|
||||
|
||||
add_device(devnull);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/// @file attr.c
|
||||
/// @brief change file attributes
|
||||
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "libgen.h"
|
||||
#include "process/scheduler.h"
|
||||
#include "fcntl.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "io/debug.h"
|
||||
#include "limits.h"
|
||||
#include "process/process.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "sys/errno.h"
|
||||
#include "system/printk.h"
|
||||
#include "system/syscall.h"
|
||||
|
||||
static int __setattr(const char *path, struct iattr* attr, bool_t follow_links) {
|
||||
// Allocate a variable for the path.
|
||||
char absolute_path[PATH_MAX];
|
||||
if (!realpath(path, absolute_path, sizeof(absolute_path))) {
|
||||
pr_err("sys_chown(%s): Cannot get the absolute path.", path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
super_block_t *sb = vfs_get_superblock(absolute_path);
|
||||
if (sb == NULL) {
|
||||
pr_err("do_chown(%s): Cannot find the superblock!\n", absolute_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
vfs_file_t *sb_root = sb->root;
|
||||
if (sb_root == NULL) {
|
||||
pr_err("do_chown(%s): Cannot find the superblock root!\n", absolute_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
// TODO: resolve links
|
||||
|
||||
// Check if the function is implemented.
|
||||
if (sb_root->sys_operations->setattr_f == NULL) {
|
||||
pr_err("setattr(%s): Function not supported in current filesystem.", absolute_path);
|
||||
return -ENOSYS;
|
||||
}
|
||||
return sb_root->sys_operations->setattr_f(absolute_path, attr);
|
||||
}
|
||||
|
||||
static inline void __iattr_set_owner_or_group(struct iattr *attr, uid_t owner, gid_t group) {
|
||||
if (owner != -1) {
|
||||
attr->ia_valid |= ATTR_UID;
|
||||
attr->ia_uid = owner;
|
||||
}
|
||||
if (group != -1) {
|
||||
attr->ia_valid |= ATTR_GID;
|
||||
attr->ia_gid = group;
|
||||
}
|
||||
}
|
||||
|
||||
int sys_chown(const char* path, uid_t owner, gid_t group) {
|
||||
struct iattr attr = {0};
|
||||
__iattr_set_owner_or_group(&attr, owner, group);
|
||||
return __setattr(path, &attr, true);
|
||||
}
|
||||
|
||||
int sys_lchown(const char* path, uid_t owner, gid_t group) {
|
||||
struct iattr attr = {0};
|
||||
__iattr_set_owner_or_group(&attr, owner, group);
|
||||
return __setattr(path, &attr, false);
|
||||
}
|
||||
|
||||
int sys_fchown(int fd, uid_t owner, gid_t group) {
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
|
||||
// Check the current FD.
|
||||
if (fd < 0 || fd >= task->max_fd) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
// Get the file.
|
||||
vfs_file_t *file = task->fd_list[fd].file_struct;
|
||||
if (file == NULL) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (!(task->uid == 0) || (task->uid == file->uid)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (owner != -1) {
|
||||
file->uid = owner;
|
||||
}
|
||||
|
||||
if (group != -1) {
|
||||
file->gid = group;
|
||||
}
|
||||
|
||||
if (file->fs_operations->setattr_f == NULL) {
|
||||
pr_err("No setattr function found for the current filesystem.\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
struct iattr attr = {0};
|
||||
__iattr_set_owner_or_group(&attr, owner, group);
|
||||
return file->fs_operations->setattr_f(file, &attr);
|
||||
}
|
||||
|
||||
int sys_chmod(const char* path, mode_t mode) {
|
||||
struct iattr attr = IATTR_CHMOD(mode);
|
||||
return __setattr(path, &attr, true);
|
||||
}
|
||||
|
||||
int sys_fchmod(int fd, mode_t mode) {
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
|
||||
// Check the current FD.
|
||||
if (fd < 0 || fd >= task->max_fd) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
// Get the file.
|
||||
vfs_file_t *file = task->fd_list[fd].file_struct;
|
||||
if (file == NULL) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (!(task->uid == 0) || (task->uid == file->uid)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
file->mask &= 0xFFFFFFFF & mode;
|
||||
|
||||
if (file->fs_operations->setattr_f == NULL) {
|
||||
pr_err("No setattr function found for the current filesystem.\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
struct iattr attr = IATTR_CHMOD(mode);
|
||||
return file->fs_operations->setattr_f(file, &attr);
|
||||
}
|
||||
+177
-64
@@ -4,10 +4,10 @@
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
// Setup the logging for this file (do this before any other include).
|
||||
#include "sys/kernel_levels.h" // Include kernel log levels.
|
||||
#define __DEBUG_HEADER__ "[EXT2 ]" ///< Change header.
|
||||
#include "sys/kernel_levels.h" // Include kernel log levels.
|
||||
#define __DEBUG_HEADER__ "[EXT2 ]" ///< Change header.
|
||||
#define __DEBUG_LEVEL__ LOGLEVEL_INFO ///< Set log level.
|
||||
#include "io/debug.h" // Include debugging functions.
|
||||
#include "io/debug.h" // Include debugging functions.
|
||||
|
||||
#include "assert.h"
|
||||
#include "fcntl.h"
|
||||
@@ -379,10 +379,12 @@ static int ext2_fstat(vfs_file_t *file, stat_t *stat);
|
||||
static int ext2_ioctl(vfs_file_t *file, int request, void *data);
|
||||
static ssize_t ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count);
|
||||
static ssize_t ext2_readlink(vfs_file_t *file, char *buffer, size_t bufsize);
|
||||
static int ext2_fsetattr(vfs_file_t *file, struct iattr *attr);
|
||||
|
||||
static int ext2_mkdir(const char *path, mode_t mode);
|
||||
static int ext2_rmdir(const char *path);
|
||||
static int ext2_stat(const char *path, stat_t *stat);
|
||||
static int ext2_setattr(const char *path, struct iattr *attr);
|
||||
static vfs_file_t *ext2_creat(const char *path, mode_t permission);
|
||||
static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path);
|
||||
|
||||
@@ -397,6 +399,7 @@ static vfs_sys_operations_t ext2_sys_operations = {
|
||||
.stat_f = ext2_stat,
|
||||
.creat_f = ext2_creat,
|
||||
.symlink_f = NULL,
|
||||
.setattr_f = ext2_setattr,
|
||||
};
|
||||
|
||||
/// Filesystem file operations.
|
||||
@@ -411,6 +414,7 @@ static vfs_file_operations_t ext2_fs_operations = {
|
||||
.ioctl_f = ext2_ioctl,
|
||||
.getdents_f = ext2_getdents,
|
||||
.readlink_f = ext2_readlink,
|
||||
.setattr_f = ext2_fsetattr,
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
@@ -467,60 +471,6 @@ static const char *time_to_string(uint32_t time)
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline int __ext2_valid_permissions(
|
||||
const task_struct *task,
|
||||
const mode_t mask,
|
||||
const uid_t uid,
|
||||
const gid_t gid,
|
||||
const int usr,
|
||||
const int grp,
|
||||
const int oth)
|
||||
{
|
||||
// The task is the owner.
|
||||
if ((mask & usr) && (task->uid == uid)) {
|
||||
return 1;
|
||||
}
|
||||
// The task belongs to the correct group.
|
||||
if ((mask & grp) && (task->gid == gid)) {
|
||||
return 1;
|
||||
}
|
||||
// The task is not the owner and does not belong to the correct group.
|
||||
if ((mask & oth) && (task->uid != uid) && (task->gid != gid)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Checks if the requests in flags are valid.
|
||||
/// @param flags the flags to check.
|
||||
/// @param mask the mask to check against.
|
||||
/// @param uid the uid of the owner.
|
||||
/// @param gid the gid of the owner.
|
||||
/// @return 1 on success, 0 otherwise.
|
||||
static int ext2_valid_permissions(int flags, mode_t mask, uid_t uid, gid_t gid)
|
||||
{
|
||||
// Check the permissions.
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
if (task == NULL) {
|
||||
pr_warning("Failed to get the current running process, assuming we are booting.\n");
|
||||
return 1;
|
||||
}
|
||||
// Init, and all root processes have full permissions.
|
||||
if ((task->pid == 0) || (task->uid == 0) || (task->gid == 0)) {
|
||||
return 1;
|
||||
}
|
||||
if (((flags & O_RDONLY) == O_RDONLY) && __ext2_valid_permissions(task, mask, uid, gid, S_IRUSR, S_IRGRP, S_IROTH)) {
|
||||
return 1;
|
||||
}
|
||||
if (((flags & O_WRONLY) == O_WRONLY) && __ext2_valid_permissions(task, mask, uid, gid, S_IWUSR, S_IWGRP, S_IWOTH)) {
|
||||
return 1;
|
||||
}
|
||||
if (((flags & O_RDWR) == O_RDWR) && __ext2_valid_permissions(task, mask, uid, gid, S_IRUSR | S_IWUSR, S_IRGRP | S_IWGRP, S_IROTH | S_IWOTH)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Dumps on debugging output the superblock.
|
||||
/// @param sb the object to dump.
|
||||
static void ext2_dump_superblock(ext2_superblock_t *sb)
|
||||
@@ -757,6 +707,28 @@ static void ext2_set_bitmap_bit(uint8_t *buffer, uint32_t linear_index, ext2_blo
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Checks if the task has x-permission for a given inode
|
||||
/// @param task the task to check permission for.
|
||||
/// @param inode the inode to check permission.
|
||||
/// @return 1 on success, 0 otherwise.
|
||||
static int __valid_x_permission(task_struct *task, ext2_inode_t *inode) {
|
||||
// Init, and all root processes always have permission
|
||||
if (!task || (task->pid == 0) || (task->uid == 0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check the owners permission
|
||||
if (task->uid == inode->uid) {
|
||||
return inode->mode & S_IXUSR;
|
||||
// Check the groups permission
|
||||
} else if (task->gid == inode->gid) {
|
||||
return inode->mode & S_IXGRP;
|
||||
}
|
||||
|
||||
// Check the others permission
|
||||
return inode->mode & S_IXOTH;
|
||||
}
|
||||
|
||||
/// @brief Searches for a free inode inside the group data loaded inside the cache.
|
||||
/// @param fs the ext2 filesystem structure.
|
||||
/// @param cache the cache from which we read the bgdt data.
|
||||
@@ -1455,7 +1427,6 @@ static ssize_t ext2_write_inode_block(ext2_filesystem_t *fs, ext2_inode_t *inode
|
||||
{
|
||||
while (block_index >= (inode->blocks_count / fs->blocks_per_block_count)) {
|
||||
ext2_allocate_inode_block(fs, inode, inode_index, (inode->blocks_count / fs->blocks_per_block_count));
|
||||
ext2_write_inode(fs, inode, inode_index);
|
||||
}
|
||||
// Get the real index.
|
||||
uint32_t real_index = ext2_get_real_block_index(fs, inode, block_index);
|
||||
@@ -1718,6 +1689,30 @@ static inline int ext2_directory_is_empty(ext2_filesystem_t *fs, uint8_t *cache,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ext2_clean_inode_content(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t inode_index)
|
||||
{
|
||||
// Check the type of operation.
|
||||
if ((inode->mode & EXT2_S_IFREG) != EXT2_S_IFREG) {
|
||||
pr_alert("Trying to clean the content of a non-regular file.\n");
|
||||
return 1;
|
||||
}
|
||||
// Allocate the cache.
|
||||
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
|
||||
// Get the cache size.
|
||||
size_t cache_size = fs->ext2_buffer_cache->size;
|
||||
// Clean the cache.
|
||||
memset(cache, 0, cache_size);
|
||||
for (ssize_t offset = 0, to_write; offset < inode->size;) {
|
||||
// We do not want to extend the size of the inode.
|
||||
to_write = max(min(offset + cache_size, inode->size), 0);
|
||||
// Override the content.
|
||||
offset += ext2_write_inode_data(fs, inode, inode_index, offset, to_write, (char *)cache);
|
||||
}
|
||||
// Free the cache.
|
||||
kmem_cache_free(cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Directory Entry Management Functions
|
||||
// ============================================================================
|
||||
@@ -1879,7 +1874,7 @@ free_cache_return_error:
|
||||
/// @param directory the directory in which we perform the search.
|
||||
/// @param name the name of the entry we are looking for.
|
||||
/// @param search the output variable where we save the info about the entry.
|
||||
/// @return 0 on success, -1 on failure.
|
||||
/// @return 0 on success, -errno on failure.
|
||||
static int ext2_find_direntry(ext2_filesystem_t *fs, ino_t ino, const char *name, ext2_direntry_search_t *search)
|
||||
{
|
||||
if (fs == NULL) {
|
||||
@@ -1910,6 +1905,13 @@ static int ext2_find_direntry(ext2_filesystem_t *fs, ino_t ino, const char *name
|
||||
pr_err("The parent inode is not a directory (ino: %d, mode: %d).\n", ino, inode.mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check that we are allowed to reach through the directory
|
||||
if (!__valid_x_permission(scheduler_get_current_process(), &inode)) {
|
||||
pr_err("The parent inode has no x permission (ino: %d, mode: %d).\n", ino, inode.mode);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
// Allocate the cache.
|
||||
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
|
||||
// Clean the cache.
|
||||
@@ -1970,7 +1972,7 @@ static int ext2_find_direntry_simple(ext2_filesystem_t *fs, ino_t ino, const cha
|
||||
|
||||
/// @brief Searches the entry specified in `path` starting from `directory`.
|
||||
/// @param directory the directory from which we start performing the search.
|
||||
/// @param path the path of the entry we are looking for, it cna be a relative path.
|
||||
/// @param path the path of the entry we are looking for, it can be a relative path.
|
||||
/// @param search the output variable where we save the entry information.
|
||||
/// @return 0 on success, -1 on failure.
|
||||
static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_search_t *search)
|
||||
@@ -2257,7 +2259,7 @@ static int ext2_create_inode(
|
||||
/// @return file descriptor number, -1 otherwise and errno is set to indicate the error.
|
||||
/// @details
|
||||
/// It is equivalent to: open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)
|
||||
static vfs_file_t *ext2_creat(const char *path, mode_t permission)
|
||||
static vfs_file_t *ext2_creat(const char *path, mode_t mode)
|
||||
{
|
||||
// Get the name of the directory.
|
||||
char parent_path[PATH_MAX];
|
||||
@@ -2309,8 +2311,7 @@ static vfs_file_t *ext2_creat(const char *path, mode_t permission)
|
||||
return file;
|
||||
}
|
||||
// Set the inode mode.
|
||||
uint32_t mode = EXT2_S_IFREG;
|
||||
mode |= 0xFFF & permission;
|
||||
mode = EXT2_S_IFREG | (0xFFF & mode);
|
||||
// Get the group index of the parent.
|
||||
uint32_t group_index = ext2_get_group_index_from_inode(fs, parent->ino);
|
||||
// Create and initialize the new inode.
|
||||
@@ -2324,6 +2325,10 @@ static vfs_file_t *ext2_creat(const char *path, mode_t permission)
|
||||
pr_err("Failed to write the newly created inode.\n");
|
||||
goto close_parent_return_null;
|
||||
}
|
||||
|
||||
// Clean the content of the newly created file.
|
||||
ext2_clean_inode_content(fs, &inode, inode_index);
|
||||
|
||||
// Initialize the file.
|
||||
if (ext2_allocate_direntry(fs, parent->ino, inode_index, file_name, ext2_file_type_regular_file) == -1) {
|
||||
pr_err("Failed to allocate a new direntry for the inode.\n");
|
||||
@@ -2411,12 +2416,17 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode)
|
||||
|
||||
ext2_dump_inode(&inode);
|
||||
|
||||
if (!ext2_valid_permissions(flags, inode.mode, inode.uid, inode.gid)) {
|
||||
if (!vfs_valid_open_permissions(flags, inode.mode, inode.uid, inode.gid)) {
|
||||
pr_err("Task does not have access permission.\n");
|
||||
errno = EACCES;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if the file is a regular file, and the user wants to write and truncate.
|
||||
if (bitmask_exact(inode.mode, EXT2_S_IFREG) && (bitmask_exact(flags, O_RDWR | O_TRUNC) || bitmask_exact(flags, O_RDONLY | O_TRUNC))) {
|
||||
ext2_clean_inode_content(fs, &inode, direntry.inode);
|
||||
}
|
||||
|
||||
vfs_file_t *file = ext2_find_vfs_file_with_inode(fs, direntry.inode);
|
||||
if (file == NULL) {
|
||||
// Allocate the memory for the file.
|
||||
@@ -2832,6 +2842,8 @@ static int ext2_mkdir(const char *path, mode_t permission)
|
||||
vfs_close(parent);
|
||||
return -ENOENT;
|
||||
}
|
||||
// Initialize the size of the inode to the block size.
|
||||
inode.size = fs->block_size;
|
||||
// Increase the number of directories inside the group.
|
||||
fs->block_groups[group_index].used_dirs_count += 1;
|
||||
// Update the bgdt.
|
||||
@@ -3010,6 +3022,107 @@ static int ext2_stat(const char *path, stat_t *stat)
|
||||
return __ext2_stat(&inode, stat);
|
||||
}
|
||||
|
||||
/// @brief Sets the attributes of an inode and saves it
|
||||
/// @param inode The inode to set the attributes
|
||||
/// @param stat The structure where the attributes are stored.
|
||||
/// @return 0 if success.
|
||||
static int __ext2_setattr(ext2_inode_t *inode, struct iattr *attr)
|
||||
{
|
||||
if (attr->ia_valid & ATTR_MODE) {
|
||||
inode->mode = (inode->mode & ~0xfff) | attr->ia_mode;
|
||||
}
|
||||
if (attr->ia_valid & ATTR_UID) {
|
||||
inode->uid = attr->ia_uid;
|
||||
}
|
||||
if (attr->ia_valid & ATTR_GID) {
|
||||
inode->gid = attr->ia_gid;
|
||||
}
|
||||
if (attr->ia_valid & ATTR_ATIME) {
|
||||
inode->atime = attr->ia_atime;
|
||||
}
|
||||
if (attr->ia_valid & ATTR_MTIME) {
|
||||
inode->mtime = attr->ia_mtime;
|
||||
}
|
||||
if (attr->ia_valid & ATTR_CTIME) {
|
||||
inode->ctime = attr->ia_ctime;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __ext2_check_setattr_permission(uid_t file_owner) {
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
return task->uid == 0 || task->uid == file_owner;
|
||||
}
|
||||
|
||||
/// @brief Set attributes of the file at the given position.
|
||||
/// @param file The file struct.
|
||||
/// @param stat The structure where the attributes are stored.
|
||||
/// @return 0 if success.
|
||||
static int ext2_fsetattr(vfs_file_t *file, struct iattr *attr)
|
||||
{
|
||||
if (!__ext2_check_setattr_permission(file->uid)) {
|
||||
return -EPERM;
|
||||
}
|
||||
// Get the filesystem.
|
||||
ext2_filesystem_t *fs = (ext2_filesystem_t *)file->device;
|
||||
if (fs == NULL) {
|
||||
pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", file->name);
|
||||
return -EPERM;
|
||||
}
|
||||
// Get the inode associated with the file.
|
||||
ext2_inode_t inode;
|
||||
if (ext2_read_inode(fs, &inode, file->ino) == -1) {
|
||||
pr_err("Failed to read the inode `%s`.\n", file->name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
__ext2_setattr(&inode, attr);
|
||||
return ext2_write_inode(fs, &inode, file->ino);
|
||||
}
|
||||
|
||||
/// @brief Set attributes of a file
|
||||
/// @param path The path where the file resides.
|
||||
/// @param stat The structure where the information are stored.
|
||||
/// @return 0 if success.
|
||||
static int ext2_setattr(const char *path, struct iattr *attr)
|
||||
{
|
||||
pr_debug("ext2_setattr(%s, %p)\n", path, stat);
|
||||
// Get the absolute path.
|
||||
char absolute_path[PATH_MAX];
|
||||
// If the first character is not the '/' then get the absolute path.
|
||||
if (!realpath(path, absolute_path, sizeof(absolute_path))) {
|
||||
pr_err("Cannot get the absolute path for path `%s`.\n", path);
|
||||
return -ENOENT;
|
||||
}
|
||||
// Get the EXT2 filesystem.
|
||||
ext2_filesystem_t *fs = get_ext2_filesystem(absolute_path);
|
||||
if (fs == NULL) {
|
||||
pr_err("Failed to get the EXT2 filesystem for absolute path `%s`.\n", absolute_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
// Prepare the structure for the direntry.
|
||||
ext2_dirent_t direntry;
|
||||
memset(&direntry, 0, sizeof(ext2_dirent_t));
|
||||
// Resolve the path.
|
||||
if (ext2_resolve_path_direntry(fs->root, absolute_path, &direntry)) {
|
||||
pr_err("Failed to resolve path `%s`.\n", absolute_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
// Get the inode associated with the directory entry.
|
||||
ext2_inode_t inode;
|
||||
if (ext2_read_inode(fs, &inode, direntry.inode) == -1) {
|
||||
pr_err("ext2_stat(%s): Failed to read the inode of `%s`.\n", path, direntry.name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!__ext2_check_setattr_permission(inode.uid)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
__ext2_setattr(&inode, attr);
|
||||
return ext2_write_inode(fs, &inode, direntry.inode);
|
||||
}
|
||||
|
||||
/// @brief Mounts the block device as an EXT2 filesystem.
|
||||
/// @param block_device the block device formatted as EXT2.
|
||||
/// @return the VFS root node of the EXT2 filesystem.
|
||||
|
||||
+3
-19
@@ -30,25 +30,9 @@ int sys_creat(const char *path, mode_t mode)
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
|
||||
// Search for an unused fd.
|
||||
int fd;
|
||||
for (fd = 0; fd < task->max_fd; ++fd) {
|
||||
if (!task->fd_list[fd].file_struct) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there is not fd available.
|
||||
if (fd >= MAX_OPEN_FD) {
|
||||
return -EMFILE;
|
||||
}
|
||||
|
||||
// If fd limit is reached, try to allocate more
|
||||
if (fd == task->max_fd) {
|
||||
if (!vfs_extend_task_fd_list(task)) {
|
||||
pr_err("Failed to extend the file descriptor list.\n");
|
||||
return -EMFILE;
|
||||
}
|
||||
}
|
||||
int fd = get_unused_fd();
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
// Try to open the file.
|
||||
vfs_file_t *file = vfs_creat(path, mode);
|
||||
|
||||
+3
-19
@@ -21,25 +21,9 @@ int sys_open(const char *pathname, int flags, mode_t mode)
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
|
||||
// Search for an unused fd.
|
||||
int fd;
|
||||
for (fd = 0; fd < task->max_fd; ++fd) {
|
||||
if (!task->fd_list[fd].file_struct) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there is not fd available.
|
||||
if (fd >= MAX_OPEN_FD) {
|
||||
return -EMFILE;
|
||||
}
|
||||
|
||||
// If fd limit is reached, try to allocate more
|
||||
if (fd == task->max_fd) {
|
||||
if (!vfs_extend_task_fd_list(task)) {
|
||||
pr_err("Failed to extend the file descriptor list.\n");
|
||||
return -EMFILE;
|
||||
}
|
||||
}
|
||||
int fd = get_unused_fd();
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
// Try to open the file.
|
||||
vfs_file_t *file = vfs_open(pathname, flags, mode);
|
||||
|
||||
@@ -60,7 +60,7 @@ ssize_t sys_write(int fd, const void *buf, size_t nbytes)
|
||||
vfs_file_descriptor_t *vfd = &task->fd_list[fd];
|
||||
|
||||
// Check the permissions.
|
||||
if (!(vfd->flags_mask & O_WRONLY)) {
|
||||
if (!bitmask_check(vfd->flags_mask, O_WRONLY | O_RDWR)) {
|
||||
return -EROFS;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level.
|
||||
#include "io/debug.h" // Include debugging functions.
|
||||
|
||||
#include "fcntl.h"
|
||||
#include "assert.h"
|
||||
#include "fs/procfs.h"
|
||||
#include "fs/vfs.h"
|
||||
@@ -604,3 +605,135 @@ int vfs_destroy_task(task_struct *task)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_unused_fd(void)
|
||||
{
|
||||
// Get the current task.
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
|
||||
// Search for an unused fd.
|
||||
int fd;
|
||||
for (fd = 0; fd < task->max_fd; ++fd) {
|
||||
if (!task->fd_list[fd].file_struct) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there is not fd available.
|
||||
if (fd >= MAX_OPEN_FD) {
|
||||
return -EMFILE;
|
||||
}
|
||||
|
||||
// If fd limit is reached, try to allocate more
|
||||
if (fd == task->max_fd) {
|
||||
if (!vfs_extend_task_fd_list(task)) {
|
||||
pr_err("Failed to extend the file descriptor list.\n");
|
||||
return -EMFILE;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int sys_dup(int fd)
|
||||
{
|
||||
// Get the current task.
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
|
||||
// Check the current FD.
|
||||
if (fd < 0 || fd >= task->max_fd) {
|
||||
return -EMFILE;
|
||||
}
|
||||
|
||||
// Get the file descriptor.
|
||||
vfs_file_descriptor_t *vfd = &task->fd_list[fd];
|
||||
vfs_file_t *file = vfd->file_struct;
|
||||
|
||||
// Check the file.
|
||||
if (file == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
fd = get_unused_fd();
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
// Increment file reference counter.
|
||||
file->count += 1;
|
||||
|
||||
// Install the new fd
|
||||
task->fd_list[fd].file_struct = file;
|
||||
task->fd_list[fd].flags_mask = vfd->flags_mask;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static inline int __valid_open_permissions(
|
||||
const mode_t mask,
|
||||
const int flags,
|
||||
const int read,
|
||||
const int write)
|
||||
{
|
||||
if ((flags & O_ACCMODE) == O_RDONLY) {
|
||||
return mask & read;
|
||||
}
|
||||
if ((flags & O_ACCMODE) == O_WRONLY) {
|
||||
return mask & write;
|
||||
}
|
||||
if ((flags & O_ACCMODE) == O_RDWR) {
|
||||
return mask & (write | read);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Checks if the requests in flags are valid.
|
||||
/// @param flags the flags to check.
|
||||
/// @param mask the mask to check against.
|
||||
/// @param uid the uid of the owner.
|
||||
/// @param gid the gid of the owner.
|
||||
/// @return 1 on success, 0 otherwise.
|
||||
int vfs_valid_open_permissions(int flags, mode_t mask, uid_t uid, gid_t gid)
|
||||
{
|
||||
// Check the permissions.
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
if (task == NULL) {
|
||||
pr_warning("Failed to get the current running process, assuming we are booting.\n");
|
||||
return 1;
|
||||
}
|
||||
// Init, and all root processes have full permissions.
|
||||
if ((task->pid == 0) || (task->uid == 0)) {
|
||||
return 1;
|
||||
}
|
||||
// Check the owners permission
|
||||
if (task->uid == uid) {
|
||||
return __valid_open_permissions(mask, flags, S_IRUSR, S_IWUSR);
|
||||
// Check the groups permission
|
||||
} else if (task->gid == gid) {
|
||||
return __valid_open_permissions(mask, flags, S_IRGRP, S_IWGRP);
|
||||
}
|
||||
|
||||
// Check the others permission
|
||||
return __valid_open_permissions(mask, flags, S_IROTH, S_IWOTH);
|
||||
}
|
||||
|
||||
/// @brief Checks if the task is allowed to execute the file
|
||||
/// @param task the task to execute the file.
|
||||
/// @param file the file to execute.
|
||||
/// @return 1 on success, 0 otherwise.
|
||||
int vfs_valid_exec_permission(task_struct *task, vfs_file_t *file) {
|
||||
// Init, and all root processes may execute any file with an execute bit set
|
||||
if ((task->pid == 0) || (task->uid == 0)) {
|
||||
return file->mask & (S_IXUSR | S_IXGRP | S_IXOTH);
|
||||
}
|
||||
|
||||
// Check the owners permission
|
||||
if (task->uid == file->uid) {
|
||||
return file->mask & S_IXUSR;
|
||||
// Check the groups permission
|
||||
} else if (task->gid == file->gid) {
|
||||
return file->mask & S_IXGRP;
|
||||
}
|
||||
|
||||
// Check the others permission
|
||||
return file->mask & S_IXOTH;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "drivers/keyboard/keymap.h"
|
||||
#include "drivers/ps2.h"
|
||||
#include "drivers/rtc.h"
|
||||
#include "drivers/mem.h"
|
||||
#include "fs/ext2.h"
|
||||
#include "fs/procfs.h"
|
||||
#include "fs/vfs.h"
|
||||
@@ -238,6 +239,16 @@ int kmain(boot_info_t *boot_informations)
|
||||
}
|
||||
print_ok();
|
||||
|
||||
//==========================================================================
|
||||
pr_notice(" Initialize memory devices...\n");
|
||||
printf(" Initialize memory devices...");
|
||||
if (mem_devs_initialize()) {
|
||||
print_fail();
|
||||
pr_emerg("Failed to initialize memory devices!\n");
|
||||
return 1;
|
||||
}
|
||||
print_ok();
|
||||
|
||||
//==========================================================================
|
||||
pr_notice(" Initialize 'procfs'...\n");
|
||||
printf(" Initialize 'procfs'...");
|
||||
@@ -340,6 +351,8 @@ int kmain(boot_info_t *boot_informations)
|
||||
// Set the keymap type.
|
||||
#ifdef USE_KEYMAP_US
|
||||
set_keymap_type(KEYMAP_US);
|
||||
#elif USE_KEYMAP_DE
|
||||
set_keymap_type(KEYMAP_DE);
|
||||
#else
|
||||
set_keymap_type(KEYMAP_IT);
|
||||
#endif
|
||||
|
||||
@@ -221,7 +221,7 @@ char *strpbrk(const char *string, const char *control)
|
||||
int tokenize(const char *string, char *separators, size_t *offset, char *buffer, ssize_t buflen)
|
||||
{
|
||||
// If we reached the end of the parsed string, stop.
|
||||
if (string[*offset] == 0) {
|
||||
if ((*offset >= buflen) || (string[*offset] == 0)) {
|
||||
return 0;
|
||||
}
|
||||
// Keep copying character until we either reach 1) the end of the buffer, 2) a
|
||||
@@ -488,15 +488,14 @@ char *strcpy(char *dst, const char *src)
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
const char *it = s;
|
||||
while (*(++it) != 0) {}
|
||||
return ((it - s) < 0) ? 0 : (size_t)(it - s);
|
||||
for(; *it; it++);
|
||||
return (size_t)(it - s);
|
||||
}
|
||||
|
||||
size_t strnlen(const char *s, size_t count)
|
||||
{
|
||||
const char *it = s;
|
||||
while ((*(++it) != 0) && --count) {}
|
||||
return ((it - s) < 0) ? 0 : (size_t)(it - s);
|
||||
const char *p = memchr(s, 0, count);
|
||||
return p ? (size_t)(p-s) : count;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
|
||||
@@ -124,6 +124,14 @@ static int __load_executable(const char *path, task_struct *task, uint32_t *entr
|
||||
pr_err("This is not a valid ELF executable `%s`!\n", path);
|
||||
return 0;
|
||||
}
|
||||
// Set the effective uid if the setuid bit is present.
|
||||
if (bitmask_check(file->mask, S_ISUID)) {
|
||||
task->uid = file->uid;
|
||||
}
|
||||
// Set the effective gid if the setgid bit is present.
|
||||
if (bitmask_check(file->mask, S_ISGID)) {
|
||||
task->gid = file->gid;
|
||||
}
|
||||
// FIXME: When threads will be implemented
|
||||
// they should share the mm, so the destroy_process_image must be called
|
||||
// only when all the threads are terminated. This can be accomplished by using
|
||||
@@ -179,7 +187,9 @@ static inline task_struct *__alloc_task(task_struct *source, task_struct *parent
|
||||
}
|
||||
// Set the statistics of the process.
|
||||
proc->uid = 0;
|
||||
proc->ruid = 0;
|
||||
proc->gid = 0;
|
||||
proc->rgid = 0;
|
||||
proc->sid = 0;
|
||||
proc->pgid = 0;
|
||||
proc->se.prio = DEFAULT_PRIO;
|
||||
@@ -425,7 +435,9 @@ pid_t sys_fork(pt_regs *f)
|
||||
proc->sid = current->sid;
|
||||
proc->pgid = current->pgid;
|
||||
proc->uid = current->uid;
|
||||
proc->ruid = current->ruid;
|
||||
proc->gid = current->gid;
|
||||
proc->rgid = current->rgid;
|
||||
|
||||
// Active the new process.
|
||||
scheduler_enqueue_task(proc);
|
||||
|
||||
@@ -376,38 +376,96 @@ int sys_setpgid(pid_t pid, pid_t pgid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uid_t sys_getuid(void)
|
||||
{
|
||||
if (runqueue.curr) {
|
||||
return runqueue.curr->uid;
|
||||
}
|
||||
#define RETURN_PROCESS_ATTR_OR_EPERM(attr) \
|
||||
if (runqueue.curr) { return runqueue.curr->attr; } \
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
uid_t sys_getuid(void) { RETURN_PROCESS_ATTR_OR_EPERM(ruid); }
|
||||
uid_t sys_geteuid(void) { RETURN_PROCESS_ATTR_OR_EPERM(uid); }
|
||||
|
||||
gid_t sys_getgid(void) { RETURN_PROCESS_ATTR_OR_EPERM(rgid); }
|
||||
gid_t sys_getegid(void) { RETURN_PROCESS_ATTR_OR_EPERM(gid); }
|
||||
|
||||
#define FAIL_ON_INV_ID(id) \
|
||||
if (id < 0) { return -EINVAL; }
|
||||
|
||||
#define FAIL_ON_INV_ID_OR_PROC(id) \
|
||||
FAIL_ON_INV_ID(id) \
|
||||
if (!runqueue.curr) { return -EPERM; }
|
||||
|
||||
#define IF_PRIVILEGED_SET_ALL_AND_RETURN(attr) \
|
||||
if (runqueue.curr->uid == 0) { \
|
||||
runqueue.curr->r ## attr = runqueue.curr->attr = attr; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define IF_RESET_SET_AND_RETURN(attr) \
|
||||
if (runqueue.curr->r ## attr == attr) { \
|
||||
runqueue.curr->attr = attr; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define SET_IF_PRIVILEGED_OR_FAIL(attr) \
|
||||
if (runqueue.curr->uid == 0) { \
|
||||
runqueue.curr->attr = attr; \
|
||||
} else { return -EPERM; }
|
||||
|
||||
int sys_setuid(uid_t uid)
|
||||
{
|
||||
if (runqueue.curr && (runqueue.curr->uid == 0)) {
|
||||
runqueue.curr->uid = uid;
|
||||
return 0;
|
||||
}
|
||||
FAIL_ON_INV_ID_OR_PROC(uid);
|
||||
IF_PRIVILEGED_SET_ALL_AND_RETURN(uid);
|
||||
IF_RESET_SET_AND_RETURN(uid);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
pid_t sys_getgid(void)
|
||||
int sys_setgid(gid_t gid)
|
||||
{
|
||||
if (runqueue.curr) {
|
||||
return runqueue.curr->gid;
|
||||
}
|
||||
FAIL_ON_INV_ID_OR_PROC(gid);
|
||||
IF_PRIVILEGED_SET_ALL_AND_RETURN(gid);
|
||||
IF_RESET_SET_AND_RETURN(gid);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
int sys_setgid(pid_t gid)
|
||||
int sys_setreuid(uid_t ruid, uid_t euid)
|
||||
{
|
||||
if (runqueue.curr && (runqueue.curr->uid == 0)) {
|
||||
runqueue.curr->gid = gid;
|
||||
return 0;
|
||||
if (!runqueue.curr) { return -EPERM; }
|
||||
|
||||
if (euid != -1) {
|
||||
FAIL_ON_INV_ID(euid);
|
||||
// Privileged or reset?
|
||||
if ((runqueue.curr->uid == 0) || (runqueue.curr->ruid == euid)) {
|
||||
runqueue.curr->uid = euid;
|
||||
} else {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
return -EPERM;
|
||||
|
||||
if (ruid != -1) {
|
||||
FAIL_ON_INV_ID(ruid);
|
||||
SET_IF_PRIVILEGED_OR_FAIL(ruid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sys_setregid(gid_t rgid, gid_t egid)
|
||||
{
|
||||
if (!runqueue.curr) { return -EPERM; }
|
||||
|
||||
if (egid != -1) {
|
||||
FAIL_ON_INV_ID(rgid);
|
||||
// Privileged or reset?
|
||||
if ((runqueue.curr->uid == 0) || (runqueue.curr->rgid == egid)) {
|
||||
runqueue.curr->gid = egid;
|
||||
} else {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
if (rgid != -1) {
|
||||
FAIL_ON_INV_ID(rgid);
|
||||
SET_IF_PRIVILEGED_OR_FAIL(rgid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_t sys_getppid(void)
|
||||
|
||||
+12
-10
@@ -13,6 +13,8 @@
|
||||
|
||||
#include "descriptor_tables/isr.h"
|
||||
#include "devices/fpu.h"
|
||||
#include "fs/attr.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "fs/ioctl.h"
|
||||
#include "hardware/timer.h"
|
||||
#include "kernel.h"
|
||||
@@ -69,8 +71,8 @@ void syscall_init(void)
|
||||
sys_call_table[__NR_chdir] = (SystemCall)sys_chdir;
|
||||
sys_call_table[__NR_time] = (SystemCall)sys_time;
|
||||
sys_call_table[__NR_mknod] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_chmod] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_lchown] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_chmod] = (SystemCall)sys_chmod;
|
||||
sys_call_table[__NR_lchown] = (SystemCall)sys_lchown;
|
||||
sys_call_table[__NR_stat] = (SystemCall)sys_stat;
|
||||
sys_call_table[__NR_lseek] = (SystemCall)sys_lseek;
|
||||
sys_call_table[__NR_getpid] = (SystemCall)sys_getpid;
|
||||
@@ -91,15 +93,15 @@ void syscall_init(void)
|
||||
sys_call_table[__NR_rename] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_mkdir] = (SystemCall)sys_mkdir;
|
||||
sys_call_table[__NR_rmdir] = (SystemCall)sys_rmdir;
|
||||
sys_call_table[__NR_dup] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_dup] = (SystemCall)sys_dup;
|
||||
sys_call_table[__NR_pipe] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_times] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_brk] = (SystemCall)sys_brk;
|
||||
sys_call_table[__NR_setgid] = (SystemCall)sys_setgid;
|
||||
sys_call_table[__NR_getgid] = (SystemCall)sys_getgid;
|
||||
sys_call_table[__NR_signal] = (SystemCall)sys_signal;
|
||||
sys_call_table[__NR_geteuid] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_getegid] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_geteuid] = (SystemCall)sys_geteuid;
|
||||
sys_call_table[__NR_getegid] = (SystemCall)sys_getegid;
|
||||
sys_call_table[__NR_acct] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_umount] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_ioctl] = (SystemCall)sys_ioctl;
|
||||
@@ -116,8 +118,8 @@ void syscall_init(void)
|
||||
sys_call_table[__NR_sigaction] = (SystemCall)sys_sigaction;
|
||||
sys_call_table[__NR_sgetmask] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_ssetmask] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_setreuid] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_setregid] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_setreuid] = (SystemCall)sys_setreuid;
|
||||
sys_call_table[__NR_setregid] = (SystemCall)sys_setregid;
|
||||
sys_call_table[__NR_sigsuspend] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_sigpending] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_sethostname] = (SystemCall)sys_ni_syscall;
|
||||
@@ -139,8 +141,8 @@ void syscall_init(void)
|
||||
sys_call_table[__NR_munmap] = (SystemCall)sys_munmap;
|
||||
sys_call_table[__NR_truncate] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_ftruncate] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_fchmod] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_fchown] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_fchmod] = (SystemCall)sys_fchmod;
|
||||
sys_call_table[__NR_fchown] = (SystemCall)sys_fchown;
|
||||
sys_call_table[__NR_getpriority] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_setpriority] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_statfs] = (SystemCall)sys_ni_syscall;
|
||||
@@ -225,7 +227,7 @@ void syscall_init(void)
|
||||
sys_call_table[__NR_rt_sigsuspend] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_pread] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_pwrite] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_chown] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_chown] = (SystemCall)sys_chown;
|
||||
sys_call_table[__NR_getcwd] = (SystemCall)sys_getcwd;
|
||||
sys_call_table[__NR_capget] = (SystemCall)sys_ni_syscall;
|
||||
sys_call_table[__NR_capset] = (SystemCall)sys_ni_syscall;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# List of programs.
|
||||
set(PROGRAM_LIST
|
||||
more.c
|
||||
chmod.c
|
||||
chown.c
|
||||
id.c
|
||||
stat.c
|
||||
false.c
|
||||
nice.c
|
||||
ls.c
|
||||
mkdir.c
|
||||
|
||||
+40
-34
@@ -12,24 +12,6 @@
|
||||
#include <strerror.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static inline void print_content(const char *path, char *buffer, unsigned buflen)
|
||||
{
|
||||
pr_warning("Printing content of %s\n", path);
|
||||
// Open the file.
|
||||
int fd = open(path, O_RDONLY, 42);
|
||||
if (fd >= 0) {
|
||||
ssize_t bytes_read = 0;
|
||||
// Put on the standard output the characters.
|
||||
while ((bytes_read = read(fd, buffer, buflen)) > 0) {
|
||||
write(STDOUT_FILENO, buffer, bytes_read);
|
||||
}
|
||||
// Close the file descriptor.
|
||||
close(fd);
|
||||
} else {
|
||||
printf("cat: %s: %s\n\n", path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
@@ -46,34 +28,58 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int status = 0;
|
||||
int fd;
|
||||
// Prepare the buffer for reading.
|
||||
char buffer[BUFSIZ];
|
||||
// Iterate the arguments.
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
// Create the stat buffer.
|
||||
stat_t statbuf;
|
||||
// Initialize the file path.
|
||||
char *filepath = argv[i];
|
||||
|
||||
// Stat the file.
|
||||
if (stat(argv[i], &statbuf) == -1) {
|
||||
printf("cat: %s: %s\n\n", argv[i], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
// If it is a regular file, just print the content.
|
||||
if (S_ISREG(statbuf.st_mode)) {
|
||||
print_content(argv[i], buffer, BUFSIZ);
|
||||
|
||||
} else if (S_ISDIR(statbuf.st_mode)) {
|
||||
printf("cat: %s: Is a directory\n\n", argv[i]);
|
||||
status = 1;
|
||||
|
||||
} else if (S_ISLNK(statbuf.st_mode)) {
|
||||
if (readlink(argv[i], buffer, BUFSIZ)) {
|
||||
print_content(buffer, buffer, BUFSIZ);
|
||||
} else {
|
||||
printf("cat: %s: %s\n\n", argv[i], strerror(errno));
|
||||
status = 1;
|
||||
// Check if it is a link.
|
||||
if (S_ISLNK(statbuf.st_mode)) {
|
||||
// Read the content of the link.
|
||||
if (readlink(filepath, buffer, BUFSIZ) < 0) {
|
||||
printf("cat: %s: %s\n\n", filepath, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
// Change the filepath.
|
||||
filepath = buffer;
|
||||
// Run the stat again, with the real file.
|
||||
if (stat(filepath, &statbuf) == -1) {
|
||||
printf("cat: %s: %s\n", filepath, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it is a directory.
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
printf("cat: %s: Is a directory\n", filepath);
|
||||
continue;
|
||||
}
|
||||
// If it is a regular file, open the file in read-only.
|
||||
if (S_ISREG(statbuf.st_mode)) {
|
||||
fd = open(filepath, O_RDONLY, 0);
|
||||
}
|
||||
if (fd < 0) {
|
||||
printf("cat: %s: %s\n", filepath, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
ssize_t bytes_read = 0;
|
||||
// Put on the standard output the characters.
|
||||
while ((bytes_read = read(fd, buffer, BUFSIZ)) > 0) {
|
||||
write(STDOUT_FILENO, buffer, bytes_read);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/// @file chmod.c
|
||||
/// @brief change file permissions
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <strerror.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mode_t mode = 0;
|
||||
char *endptr;
|
||||
gid_t gid = -1;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(STDERR_FILENO, "%s: MODE FILE\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mode = strtol(argv[1], &endptr, 8);
|
||||
if (*endptr != '\0') {
|
||||
fprintf(STDERR_FILENO, "%s: invalid mode: '%s'\n", argv[0], argv[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (chmod(argv[2], mode) == -1) {
|
||||
fprintf(STDERR_FILENO, "%s: changing permissions of %s: %s\n",
|
||||
argv[0], argv[2], strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/// @file chown.c
|
||||
/// @brief change file ownership
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <strerror.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *idptr;
|
||||
char *saveptr;
|
||||
char *endptr;
|
||||
uid_t uid = -1;
|
||||
gid_t gid = -1;
|
||||
passwd_t *pwd;
|
||||
group_t *grp;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(STDERR_FILENO, "%s: [OWNER][:[GROUP]] FILE\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
idptr = strtok_r(argv[1], ":", &saveptr);
|
||||
if (argv[1][0] != ':') { /* Skip the username */
|
||||
uid = strtol(idptr, &endptr, 10); /* Allow a numeric string */
|
||||
if (*endptr != '\0') { /* Was not pure numeric string */
|
||||
pwd = getpwnam(idptr); /* Try getting UID for username */
|
||||
if (pwd == NULL) {
|
||||
fprintf(STDERR_FILENO, "%s: invalid user: %s\n", argv[0], idptr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
uid = pwd->pw_uid;
|
||||
}
|
||||
idptr = strtok_r(NULL, ":", &saveptr);
|
||||
}
|
||||
|
||||
if (idptr != NULL) {
|
||||
gid = strtol(idptr, &endptr, 10); /* Allow a numeric string */
|
||||
if (*endptr != '\0') { /* Was not pure numeric string */
|
||||
grp = getgrnam(idptr); /* Try getting GID for groupname */
|
||||
if (grp == NULL) {
|
||||
fprintf(STDERR_FILENO, "%s: invalid group: %s\n", argv[0], idptr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
gid = grp->gr_gid;
|
||||
}
|
||||
}
|
||||
|
||||
if (chown(argv[2], uid, gid) == -1) {
|
||||
fprintf(STDERR_FILENO, "%s: changing ownership of %s: %s\n",
|
||||
argv[0], argv[2], strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/// @file false.c
|
||||
/// @brief
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <sys/unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/// @file id.c
|
||||
/// @brief
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <sys/unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
printf("uid=%d gid=%d\n", geteuid(), getegid());
|
||||
} else if (strncmp(argv[1], "--help", 6) == 0) {
|
||||
printf("Usage: %s [OPTION]\n", argv[0]);
|
||||
printf("Print user and group information\n\n");
|
||||
printf(" -g, --group print only the effective group ID");
|
||||
printf(" -u, --user print only the effective user ID");
|
||||
printf(" --help display this help and exit");
|
||||
} else if (strncmp(argv[1], "-u", 2) == 0 || strncmp(argv[1], "--user", 6) == 0) {
|
||||
printf("%d\n", geteuid());
|
||||
} else if (strncmp(argv[1], "-g", 2) == 0 || strncmp(argv[1], "--group", 7) == 0) {
|
||||
printf("%d\n", getegid());
|
||||
} else {
|
||||
printf("%s: invalid option '%s'\n", argv[0], argv[1]);
|
||||
printf("Try '%s --help' for more information\n", argv[0]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+11
-6
@@ -7,18 +7,23 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
char *_argv[] = { "login", NULL };
|
||||
int status;
|
||||
if (fork() == 0) {
|
||||
execv("/bin/login", _argv);
|
||||
printf("This is bad, I should not be here! EXEC NOT WORKING\n");
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "EndlessLoop"
|
||||
while (1) {
|
||||
wait(&status);
|
||||
pid_t login = fork();
|
||||
if (login == 0) {
|
||||
execv("/bin/login", _argv);
|
||||
printf("This is bad, I should not be here! EXEC NOT WORKING\n");
|
||||
}
|
||||
|
||||
while (wait(&status) != login);
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
char *pager = "cat";
|
||||
char *pager = "more";
|
||||
char filepath[PATH_MAX];
|
||||
strcpy(filepath, "/usr/share/man/");
|
||||
strcat(filepath, argv[1]);
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/// @file more.c
|
||||
/// @brief `more` program.
|
||||
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "stdbool.h"
|
||||
#include "stddef.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <strerror.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <limits.h>
|
||||
|
||||
// Video dimensions defined in mentos/src/io/video.c
|
||||
#define HEIGHT 25
|
||||
#define WIDTH 80
|
||||
#define LAST_LINE (HEIGHT - 1)
|
||||
|
||||
static void erase_backwards(int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++) {
|
||||
putchar('\b');
|
||||
}
|
||||
}
|
||||
|
||||
static void page_content(int fd)
|
||||
{
|
||||
int lines = 0;
|
||||
char line[WIDTH + 2];
|
||||
char *lineend;
|
||||
while ((lineend = fgets(line, WIDTH, fd))) {
|
||||
if (lineend - line == WIDTH && line[WIDTH - 1] != '\n') {
|
||||
line[WIDTH - 1] = '+';
|
||||
line[WIDTH] = '\n';
|
||||
line[WIDTH + 1] = 0;
|
||||
}
|
||||
|
||||
printf("%s", line);
|
||||
|
||||
lines++;
|
||||
if (lines == LAST_LINE) {
|
||||
int prompt = printf("--more--");
|
||||
int c;
|
||||
bool_t quit = false;
|
||||
do {
|
||||
c = getchar();
|
||||
if (c == 'q') {
|
||||
quit = true;
|
||||
} else if (c == '\n') {
|
||||
lines = LAST_LINE - 1;
|
||||
} else if (c == ' ') {
|
||||
lines = 0;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (1);
|
||||
erase_backwards(prompt);
|
||||
if (quit)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Check if `--help` is provided.
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0)) {
|
||||
printf("Display the content of a file.\n");
|
||||
printf("Usage:\n");
|
||||
printf(" more [FILE]\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
char buffer[PATH_MAX];
|
||||
char *filepath = argv[1];
|
||||
|
||||
struct termios _termios;
|
||||
tcgetattr(STDIN_FILENO, &_termios);
|
||||
_termios.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, 0, &_termios);
|
||||
|
||||
int fd = STDOUT_FILENO;
|
||||
if (argc > 1) {
|
||||
// State the file.
|
||||
stat_t statbuf;
|
||||
if (stat(filepath, &statbuf) == -1) {
|
||||
printf("more: %s: %s\n", filepath, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Check if it is a link.
|
||||
if (S_ISLNK(statbuf.st_mode)) {
|
||||
// Read the content of the link.
|
||||
if (readlink(filepath, buffer, BUFSIZ) < 0) {
|
||||
printf("more: %s: %s\n\n", filepath, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// Change the filepath.
|
||||
filepath = buffer;
|
||||
// Run the stat again, with the real file.
|
||||
if (stat(filepath, &statbuf) == -1) {
|
||||
printf("more: %s: %s\n", filepath, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it is a directory.
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
printf("more: %s: Is a directory\n", filepath);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// If it is a regular file, open the file in read-only.
|
||||
if (S_ISREG(statbuf.st_mode)) {
|
||||
fd = open(filepath, O_RDONLY, 0);
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
printf("more: %s: %s\n", filepath, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
page_content(fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/// @file stat.c
|
||||
/// @brief display file status
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <io/debug.h>
|
||||
#include <stdio.h>
|
||||
#include <strerror.h>
|
||||
#include <string.h>
|
||||
#include <sys/bitops.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
// Copied from mentos/src/fs/ext2.c
|
||||
// File types.
|
||||
#define S_IFMT 0xF000 ///< Format mask
|
||||
#define S_IFSOCK 0xC000 ///< Socket
|
||||
#define S_IFLNK 0xA000 ///< Symbolic link
|
||||
#define S_IFREG 0x8000 ///< Regular file
|
||||
#define S_IFBLK 0x6000 ///< Block device
|
||||
#define S_IFDIR 0x4000 ///< Directory
|
||||
#define S_IFCHR 0x2000 ///< Character device
|
||||
#define S_IFIFO 0x1000 ///< Fifo
|
||||
|
||||
void __print_time(const char* prefix, time_t *time) {
|
||||
tm_t *timeinfo = localtime(time);
|
||||
printf("%s%d-%d-%d %d:%d:%d\n",
|
||||
prefix,
|
||||
timeinfo->tm_year,
|
||||
timeinfo->tm_mon,
|
||||
timeinfo->tm_mday,
|
||||
timeinfo->tm_hour,
|
||||
timeinfo->tm_min,
|
||||
timeinfo->tm_sec);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("%s: missing operand.\n", argv[0]);
|
||||
printf("Try '%s --help' for more information.\n\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(argv[1], "--help") == 0) {
|
||||
printf("Usage: %s FILE\n", argv[0]);
|
||||
printf( "Display file status.\n");
|
||||
exit(0);
|
||||
}
|
||||
stat_t statbuf;
|
||||
if(stat(argv[1], &statbuf) == -1) {
|
||||
printf("%s: cannot stat '%s': %s\n", argv[0], argv[1], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
printf("File: %s\n", argv[1]);
|
||||
printf("Size: %s\n", to_human_size(statbuf.st_size));
|
||||
printf("File type: ");
|
||||
switch (statbuf.st_mode & S_IFMT) {
|
||||
case S_IFBLK: printf("block device\n"); break;
|
||||
case S_IFCHR: printf("character device\n"); break;
|
||||
case S_IFDIR: printf("directory\n"); break;
|
||||
case S_IFIFO: printf("FIFO/pipe\n"); break;
|
||||
case S_IFLNK: printf("symlink\n"); break;
|
||||
case S_IFREG: printf("regular file\n"); break;
|
||||
case S_IFSOCK: printf("socket\n"); break;
|
||||
default: printf("unknown?\n"); break;
|
||||
}
|
||||
printf("Access: (%.4o/", statbuf.st_mode & 0xFFF);
|
||||
// Print the access permissions.
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IRUSR) ? 'r' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IWUSR) ? 'w' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IXUSR) ? 'x' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IRGRP) ? 'r' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IWGRP) ? 'w' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IXGRP) ? 'x' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IROTH) ? 'r' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IWOTH) ? 'w' : '-');
|
||||
putchar(bitmask_check(statbuf.st_mode, S_IXOTH) ? 'x' : '-');
|
||||
printf(") Uid: (%d) Gid: (%d)\n", statbuf.st_uid, statbuf.st_gid);
|
||||
__print_time("Access: ", &statbuf.st_atime);
|
||||
__print_time("Modify: ", &statbuf.st_mtime);
|
||||
__print_time("Change: ", &statbuf.st_ctime);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
# List of programs.
|
||||
set(TEST_LIST
|
||||
t_dup.c
|
||||
t_creat.c
|
||||
t_write_read.c
|
||||
t_gid.c
|
||||
t_alarm.c
|
||||
t_periodic3.c
|
||||
@@ -14,7 +17,6 @@ set(TEST_LIST
|
||||
t_sigmask.c
|
||||
t_getenv.c
|
||||
t_sigusr.c
|
||||
t_exec_callee.c
|
||||
t_shmget.c
|
||||
t_stopcont.c
|
||||
t_semop.c
|
||||
|
||||
@@ -23,6 +23,8 @@ void sig_handler(int sig)
|
||||
printf("handler(%d) : Correct signal. ABRT (%d/3)\n", sig, counter);
|
||||
if (counter < 3)
|
||||
abort();
|
||||
else
|
||||
exit(0);
|
||||
|
||||
} else {
|
||||
printf("handler(%d) : Wrong signal.\n", sig);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/// @file t_creat.c
|
||||
/// @brief test the creat syscall
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strerror.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int fd = creat("foo", 0660);
|
||||
if (fd < 0) {
|
||||
printf("creat: foo: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (write(fd, "foo", 3) != 3) {
|
||||
printf("write: foo: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct stat_t st;
|
||||
if (stat("foo", &st) < 0) {
|
||||
printf("stat: foo: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (st.st_size != 3) {
|
||||
printf("Wrong file size. (expected: 3, is: %u)\n", st.st_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/// @file t_dup.c
|
||||
/// @brief Test the dup syscall
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <strerror.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *file = "t_dup_file";
|
||||
int fd1, fd2;
|
||||
int flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
|
||||
|
||||
fd1 = open(file, flags, mode);
|
||||
if (fd1 < 0) {
|
||||
printf("Failed to open file %s: %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd2 = dup(fd1);
|
||||
if (fd2 < 0) {
|
||||
printf("Failed to dup fd %d: %s\n", fd1, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (write(fd1, "foo", 3) != 3) {
|
||||
printf("Writing to fd %d failed: %s\n", fd1, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
close(fd1);
|
||||
|
||||
if (write(fd2, "bar", 3) != 3) {
|
||||
printf("Writing to fd %d failed: %s\n", fd2, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
close(fd2);
|
||||
|
||||
fd1 = open(file, O_RDONLY, 0);
|
||||
if (fd1 < 0) {
|
||||
printf("Failed to open file %s: %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char buf[7];
|
||||
buf[6] = 0;
|
||||
if (read(fd1, &buf, 6) < 0) {
|
||||
printf("Reading from fd %d failed: %s\n", fd1, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(buf, "foobar") != 0) {
|
||||
printf("Unexpected file content: %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
unlink(file);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/// @file t_exec_callee.c
|
||||
/// @brief
|
||||
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *ENV_VAR = getenv("ENV_VAR");
|
||||
if (ENV_VAR == NULL) {
|
||||
printf("Failed to get env: `ENV_VAR`\n");
|
||||
return 1;
|
||||
}
|
||||
printf("ENV_VAR = %s\n", ENV_VAR);
|
||||
return 0;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// ========================================================================
|
||||
// Generating a key using ftok
|
||||
key = ftok("/home/user/test7.txt", 5);
|
||||
key = ftok("/README", 5);
|
||||
if (key < 0) {
|
||||
perror("Failed to generate key using ftok");
|
||||
return 1;
|
||||
|
||||
@@ -22,12 +22,12 @@ int main(int argc, char *argv[])
|
||||
sched_setparam(cpid, ¶m);
|
||||
int counter = 0;
|
||||
if (fork() == 0) {
|
||||
char *_argv[] = { "/bin/periodic2", NULL };
|
||||
char *_argv[] = { "/bin/tests/t_periodic2", NULL };
|
||||
execv(_argv[0], _argv);
|
||||
printf("This is bad, I should not be here! EXEC NOT WORKING\n");
|
||||
}
|
||||
if (fork() == 0) {
|
||||
char *_argv[] = { "/bin/periodic3", NULL };
|
||||
char *_argv[] = { "/bin/tests/t_periodic3", NULL };
|
||||
execv(_argv[0], _argv);
|
||||
printf("This is bad, I should not be here! EXEC NOT WORKING\n");
|
||||
}
|
||||
|
||||
@@ -17,10 +17,6 @@ int main(int argc, char *argv[])
|
||||
union semun arg;
|
||||
long ret, semid;
|
||||
|
||||
op[0].sem_num = 0;
|
||||
op[0].sem_op = -2;
|
||||
op[0].sem_flg = IPC_NOWAIT;
|
||||
|
||||
// ========================================================================
|
||||
// Create the first semaphore.
|
||||
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
@@ -78,21 +74,16 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
printf("[child] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
|
||||
printf("[child] Exit, now.\n", semid, ret);
|
||||
|
||||
// ========================================================================
|
||||
// Delete the semaphore set.
|
||||
ret = semctl(semid, 0, IPC_RMID, 0);
|
||||
if (ret < 0) {
|
||||
perror("Failed to remove semaphore set");
|
||||
}
|
||||
printf("[child] Correctly removed semaphore set.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
op[0].sem_num = 0;
|
||||
op[0].sem_op = -2;
|
||||
op[0].sem_flg = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Perform the operations.
|
||||
if (semop(semid, op, 2) < 0) {
|
||||
// Perform the operation.
|
||||
if (semop(semid, op, 1) < 0) {
|
||||
perror("Failed to perform operation");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// ========================================================================
|
||||
// Generating a key using ftok
|
||||
key = ftok("/home/user/test7.txt", 5);
|
||||
key = ftok("/README", 5);
|
||||
if (key < 0) {
|
||||
perror("Failed to generate key using ftok.");
|
||||
return 1;
|
||||
|
||||
@@ -18,25 +18,13 @@ void sig_handler(int sig)
|
||||
if (sig == SIGFPE) {
|
||||
printf("handler(%d) : Correct signal. FPE\n", sig);
|
||||
printf("handler(%d) : Exiting\n", sig);
|
||||
// exit(1);
|
||||
exit(0);
|
||||
} else {
|
||||
printf("handler(%d) : Wrong signal.\n", sig);
|
||||
}
|
||||
printf("handler(%d) : Ending handler.\n", sig);
|
||||
}
|
||||
|
||||
long int fact(int n)
|
||||
{
|
||||
if (n == 0 || n == 1) {
|
||||
return 1;
|
||||
}
|
||||
long int pro = 1;
|
||||
while (n != 1) {
|
||||
pro *= n--;
|
||||
}
|
||||
return pro;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
sigaction_t action;
|
||||
|
||||
@@ -19,7 +19,7 @@ void sig_handler_info(int sig, siginfo_t *siginfo)
|
||||
printf("handler(%d, %p) : Correct signal.\n", sig, siginfo);
|
||||
printf("handler(%d, %p) : Code : %d\n", sig, siginfo, siginfo->si_code);
|
||||
printf("handler(%d, %p) : Exiting\n", sig, siginfo);
|
||||
exit(1);
|
||||
exit(0);
|
||||
} else {
|
||||
printf("handler(%d, %p) : Wrong signal.\n", sig, siginfo);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ void sig_handler(int sig)
|
||||
counter += 1;
|
||||
|
||||
if (counter == 2)
|
||||
exit(1);
|
||||
exit(0);
|
||||
|
||||
} else {
|
||||
printf("handler(%d) : Wrong signal.\n", sig);
|
||||
@@ -51,5 +51,5 @@ int main(int argc, char *argv[])
|
||||
kill(getpid(), SIGUSR2);
|
||||
|
||||
while(1) { };
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -41,18 +41,16 @@ int main(int argc, char *argv[])
|
||||
sleep(2);
|
||||
printf("Sending stop sig to child\n");
|
||||
|
||||
#if 1
|
||||
if (kill(child_pid, SIGSTOP) == -1)
|
||||
printf("Errore invio stop\n");
|
||||
#endif
|
||||
printf("Error sending signal\n");
|
||||
|
||||
wait(NULL);
|
||||
} else {
|
||||
int c = 0;
|
||||
for (;;) {
|
||||
printf("c: %d\n", c++);
|
||||
for (int c = 0; c < 5; c++) {
|
||||
printf("c: %d\n", c);
|
||||
sleep(3);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/// @file t_write_read.c
|
||||
/// @brief Test consecutive writes
|
||||
/// @copyright (c) 2024 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strerror.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <math.h>
|
||||
#include <io/debug.h>
|
||||
|
||||
int create_file(const char *filename, mode_t mode)
|
||||
{
|
||||
int fd = creat(filename, mode);
|
||||
if (fd < 0) {
|
||||
printf("Failed to create file %s: %s\n", filename, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
close(fd);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int check_content(const char *filename, const char *content, int length)
|
||||
{
|
||||
pr_notice("Check content(%s, %s, %d)\n", filename, content, length);
|
||||
|
||||
char buffer[256];
|
||||
memset(buffer, 0, 256);
|
||||
// Open the file.
|
||||
int fd = open(filename, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
printf("Failed to open file %s: %s\n", filename, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Read the content.
|
||||
if (read(fd, &buffer, max(min(length, 256), 0)) < 0) {
|
||||
printf("Reading from file %s failed: %s\n", filename, strerror(errno));
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (strcmp(buffer, content) != 0) {
|
||||
printf("Unexpected file content `%s`, expecting `%s`.\n", buffer, content);
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int write_content(const char *filename, const char *content, int length, int truncate, int append)
|
||||
{
|
||||
pr_notice("Write content(%s, %s, %d, TRUNC: %d, APP: %d)\n", filename, content, length, truncate, append);
|
||||
|
||||
int flags = O_WRONLY | (truncate ? O_TRUNC : append ? O_APPEND :
|
||||
0);
|
||||
// Open the file.
|
||||
int fd = open(filename, flags, 0);
|
||||
if (fd < 0) {
|
||||
printf("Failed to open file %s: %s\n", filename, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Read the content.
|
||||
if (write(fd, content, length) < 0) {
|
||||
printf("Writing on file %s failed: %s\n", filename, strerror(errno));
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
close(fd);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int test_write_read(const char *filename)
|
||||
{
|
||||
char buf[7] = { 0 };
|
||||
// Create the file.
|
||||
if (create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Open the file.
|
||||
int fd = open(filename, O_WRONLY, 0);
|
||||
if (fd < 0) {
|
||||
printf("Failed to open file %s: %s\n", filename, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (write(fd, "foo", 3) != 3) {
|
||||
printf("First write to %s failed: %s\n", filename, strerror(errno));
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (write(fd, "bar", 3) != 3) {
|
||||
printf("Second write to %s failed: %s\n", filename, strerror(errno));
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Close the file.
|
||||
close(fd);
|
||||
// Check the content.
|
||||
if (check_content(filename, "foobar", 6)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int test_truncate(const char *filename)
|
||||
{
|
||||
if (create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (write_content(filename, "foobar", 6, 0, 0)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (check_content(filename, "foobar", 6)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (write_content(filename, "bark", 4, 0, 0)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (check_content(filename, "barkar", 6)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (write_content(filename, "barf", 4, 1, 0)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (check_content(filename, "barf", 6)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int test_append(const char *filename)
|
||||
{
|
||||
if (create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (write_content(filename, "fusro", 5, 0, 0)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (write_content(filename, "dah", 3, 0, 1)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (check_content(filename, "fusrodah", 8)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *filename = "test.txt";
|
||||
|
||||
printf("Running `test_write_read`...\n");
|
||||
if (test_write_read(filename)) {
|
||||
unlink(filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
unlink(filename);
|
||||
|
||||
printf("Running `test_truncate`...\n");
|
||||
if (test_truncate(filename)) {
|
||||
unlink(filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
unlink(filename);
|
||||
|
||||
printf("Running `test_append`...\n");
|
||||
if (test_append(filename)) {
|
||||
unlink(filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user