77 Commits

Author SHA1 Message Date
Enrico Fraccaroli (Galfurian) 21728285a6 Reactivate test_write_read function. 2024-03-01 14:28:00 -05:00
Enrico Fraccaroli 636f8c68c5 Merge pull request #41 from fischerling/fix-permissions
Fix and rework our permission permissions
2024-03-01 14:26:43 -05:00
Enrico Fraccaroli (Galfurian) 50569ed1c8 Fix cat to handle symlinks correctly. 2024-03-01 13:51:06 -05:00
Enrico Fraccaroli (Galfurian) 81ca704adb Check for symbolic links in more function. 2024-03-01 13:45:29 -05:00
Enrico Fraccaroli a4091ca57b Merge pull request #40 from fischerling/add-pager
add simple `more(1)` implementation and use it for man pages
2024-03-01 13:32:27 -05:00
Enrico Fraccaroli (Galfurian) 57bd59bb43 Fix proper error checking with readlink in cat. 2024-03-01 13:21:21 -05:00
Florian Fischer f687b89c74 ext2: check directory permissions during resolving of paths 2024-03-01 18:29:25 +01:00
Florian Fischer 0347054fae fs: move and fix generic permission checks
As defined by POSIX permissions are checked for the first matching class,
user, group or others.
Only the permissions of this first matching class are considered.

For example:
Consider a process running for user and group.
A file with user:group -w- rw- --- is not readable by user, and
thus not readable by the process.
However, it is readable by anyone else in the group.

Additionally, since the permission checks are generic and not exclusive
to the ext2 driver, they are moved to the vfs code.
2024-03-01 17:55:58 +01:00
Enrico Fraccaroli 2df2f34f22 Merge pull request #39 from fischerling/fix-strlen
fix str[n]len implementations
2024-03-01 11:27:09 -05:00
Florian Fischer 9bb19e22be man: use more as pager for man 2024-03-01 17:22:04 +01:00
Florian Fischer 2644a07f66 add simple more implementation 2024-03-01 17:21:26 +01:00
Florian Fischer c8db92b7b7 fix str[n]len implementations
The current implementations do not count the length of empty strings
correctly.
The following buffer content "\0foo\0" is considered a string with
length 4, because the iteration pointer is incremented before
it is dereferenced to check for a null char.

Replace the broken strlen functions with the implementation of musl libc.
2024-03-01 17:13:39 +01:00
Enrico Fraccaroli (Galfurian) 082ea79648 Add newline at the end of fcvt. 2024-03-01 09:16:25 -05:00
Enrico Fraccaroli 272a246e29 Merge pull request #38 from fischerling/setattr
support setting file attributes
2024-03-01 09:14:46 -05:00
Enrico Fraccaroli (Galfurian) 67223d0edf Extend the write/read test. 2024-02-29 16:44:26 -05:00
Enrico Fraccaroli (Galfurian) e4e740c1c5 Add the ext2_clean_inode_content function to clear the content of an inode. Use it to implement the O_TRUNC. 2024-02-29 16:44:11 -05:00
Enrico Fraccaroli (Galfurian) d213be2bcf Add the bitmask_exact. 2024-02-29 16:43:33 -05:00
Florian Fischer 2ab2dd8a11 add manual pages for chown and chmod 2024-02-29 22:04:09 +01:00
Florian Fischer f4f57e0750 ext2: implement setattr support
This adds support for chown and chmod on etx2 filesystems.
2024-02-29 22:04:09 +01:00
Florian Fischer 548feeaf7d add simple chmod implementation 2024-02-29 22:04:09 +01:00
Florian Fischer 761abc0172 add simple chown program 2024-02-29 22:04:09 +01:00
Florian Fischer 61024ac3f3 add *chmod, and *chown syscalls 2024-02-29 21:49:01 +01:00
Florian Fischer 9ee6421e1b fs: add callbacks to change file attributes 2024-02-29 21:49:01 +01:00
Enrico Fraccaroli (Galfurian) 79a9897a61 Extend the test to include checks on truncate. 2024-02-29 14:28:22 -05:00
Enrico Fraccaroli (Galfurian) 0b1bc2844b Fix wrong check in sys_write. 2024-02-29 14:27:55 -05:00
Enrico Fraccaroli f538920b24 Merge pull request #36 from fischerling/implement-id-separation
Implement user and group ID separation
2024-02-29 13:58:04 -05:00
Enrico Fraccaroli (Galfurian) 152f141d5a Remove const from ata devices. 2024-02-29 13:17:37 -05:00
Enrico Fraccaroli (Galfurian) 61824151fb Add more missing comments. 2024-02-29 13:14:38 -05:00
Enrico Fraccaroli (Galfurian) 9950584c12 Add comment to the __debug_print_header function. 2024-02-29 12:56:45 -05:00
Enrico Fraccaroli (Galfurian) 113e902a62 Add comments to the function vm_area_compare. 2024-02-29 12:56:14 -05:00
Enrico Fraccaroli (Galfurian) 91e1a116c7 Disable doxygen for fcvt.c file. 2024-02-29 12:51:04 -05:00
Enrico Fraccaroli (Galfurian) e67aced2c0 Add missing comments for pci_dump_device_data function. 2024-02-29 12:50:49 -05:00
Enrico Fraccaroli (Galfurian) 179a301c40 Merge branch 'develop' of github.com:mentos-team/MentOS into develop 2024-02-29 12:30:35 -05:00
Enrico Fraccaroli fb1a6fcf15 Merge pull request #35 from fischerling/restart-login
init: restart the login process after the user session terminated
2024-02-29 12:29:32 -05:00
Enrico Fraccaroli 9bb52a8494 Merge pull request #37 from fischerling/add-dev-null
drivers: implement memory device driver
2024-02-29 12:28:08 -05:00
Enrico Fraccaroli bd864fe384 Merge pull request #34 from fischerling/implement_dup
Implement dup syscall
2024-02-29 12:26:21 -05:00
Florian Fischer 3bf6119030 drivers: implement memory device driver
The first and only memory device mounted at /dev/null discards all data
written to it and always returns 0 bytes when read.
2024-02-29 17:59:24 +01:00
Florian Fischer dba41a3719 fix usage of pid_t instead of gid_t 2024-02-29 17:55:48 +01:00
Florian Fischer b149807ccc support and use the new uid syscalls from userspace 2024-02-29 17:55:48 +01:00
Florian Fischer 43c5bbaaff exec: support SUID and SGID bits 2024-02-29 17:55:48 +01:00
Florian Fischer 9f0d8eca0d implement effective and real user and group id separation
New syscalls:
  * geteuid
  * setreuid
  * getegid
  * setregid
2024-02-29 17:55:48 +01:00
Florian Fischer 9de28df51a stddef: make uid_t and gid_t signed
POSIX describes uid_t and gid_t as SIGNED integer types.
They need to be able to store -1 for various syscalls.
2024-02-29 17:55:47 +01:00
Florian Fischer 58ceead501 add simple id implementation 2024-02-29 17:55:47 +01:00
Florian Fischer 1a6a590eee init: restart the login process after the user session terminated 2024-02-29 17:47:00 +01:00
Florian Fischer cf8781398d use get_unused_fd helper to find the lowest available fd 2024-02-29 17:43:28 +01:00
Florian Fischer 2d8350f732 implement dup syscall 2024-02-29 17:43:20 +01:00
Enrico Fraccaroli (Galfurian) b79f768a0f Use the ptr_to_malloc_header function. 2024-02-29 11:18:03 -05:00
Enrico Fraccaroli (Galfurian) 45229810be - Check for errors from the brk;
- Use the new malloc_header_to_ptr function in malloc;
2024-02-29 11:17:09 -05:00
Enrico Fraccaroli (Galfurian) 670320df13 malloc(0) is implementation-dependant, we return NULL. 2024-02-29 11:16:29 -05:00
Enrico Fraccaroli (Galfurian) f088eb4058 - Add comments to the malloc_header_t structure;
- Add functions that extract the memory pointer from a pointer to the header, and vice versa;
2024-02-29 11:15:25 -05:00
Enrico Fraccaroli (Galfurian) 7b6076b612 Add an explanation for the swap macro. 2024-02-29 11:07:55 -05:00
Enrico Fraccaroli (Galfurian) d213276817 Add missing comment for the offset argument of tokenize. Add error checko on the offset. 2024-02-29 11:06:04 -05:00
Enrico Fraccaroli (Galfurian) ed7454f1e0 Translate italian text to english. 2024-02-29 11:04:47 -05:00
Enrico Fraccaroli 806664f61c Merge pull request #32 from fischerling/stopcont-test
remove infinite loop in t_stopcont
2024-02-29 11:03:43 -05:00
Enrico Fraccaroli 8852d09693 Merge pull request #31 from fischerling/test-semflg-test
fix t_semflg test
2024-02-29 10:59:41 -05:00
Enrico Fraccaroli 8262982e87 Merge pull request #30 from fischerling/cleanup-tests
Some miscellaneous cleanups for the included tests
2024-02-29 10:56:34 -05:00
Enrico Fraccaroli fbff702922 Merge pull request #29 from fischerling/add-utils
Add false and stat util
2024-02-29 10:50:14 -05:00
Enrico Fraccaroli cd60f1602e Merge pull request #28 from fischerling/improve-syscall-doc
doc: update the implemented syscalls
2024-02-29 10:46:22 -05:00
Enrico Fraccaroli 354470b85b Merge pull request #27 from fischerling/add-german-keymap
add german keymap
2024-02-29 10:44:40 -05:00
Florian Fischer 43054529d5 add creat test
Tesing commit f7e53f9b00.
2024-02-29 16:12:09 +01:00
Florian Fischer fe4c4e337e remove infinite loop in t_stopcont
Remove useless preprocessor define.

Terminate the child after 15 seconds.

Since the parent is waiting for the child to terminate it is still
guaranteed that the child was continued.
2024-02-29 16:09:39 +01:00
Florian Fischer 63b8d9420a fix t_semflg test
Remove the double semaphore cleanup in the child and the parent.

Set nops to 1 since there is only one operation not two.

Use a blocking semaphore operation in the parent to wait for the
child increasing the semaphore value.
2024-02-29 16:07:50 +01:00
Florian Fischer 7b54ff8d2a tests: exit with 0 when the test succeeds. 2024-02-29 16:05:11 +01:00
Florian Fischer 65393843a5 tests: use files that actually exist
Commit af79958f1a removed
a lot of files including /home/user/test7.txt used in some tests.

Replace /home/user/test7.txt with /README.
2024-02-29 16:04:56 +01:00
Florian Fischer afa3d4fb66 tests: remove the not used t_exec_callee 2024-02-29 16:04:49 +01:00
Florian Fischer f124be1cf7 tests: add simple test for small consecutive writes
This test was written for: 4d4504486d.
2024-02-29 16:04:37 +01:00
Florian Fischer 88b1846a43 tests: fix paths to the other periodic tests 2024-02-29 15:58:48 +01:00
Florian Fischer 8e1696d701 add simple stat.1 implementation 2024-02-29 15:52:49 +01:00
Florian Fischer ebd07576fa programs: add simple false program 2024-02-29 15:52:34 +01:00
Florian Fischer ce99aff26b doc: update the implemented syscalls
Fix the listed source files for implemented syscalls and remove
the files for not implemented ones.
2024-02-29 15:48:27 +01:00
Florian Fischer 5b4c3bb0f4 add german keymap 2024-02-29 15:44:31 +01:00
Enrico Fraccaroli (Galfurian) 53d1e8ad68 Set the size of every new directory to the block_size 2024-02-28 12:14:54 -05:00
Enrico Fraccaroli (Galfurian) ed50926b46 Remove ext2_write_inode call from ext2_write_inode_block, because is already called by ext2_allocate_inode_block internally on success. 2024-02-28 12:13:35 -05:00
Enrico Fraccaroli (Galfurian) bc0c921316 Merge branch 'master' into develop 2024-02-28 12:10:37 -05:00
Enrico Fraccaroli (Galfurian) 189f2ceb77 Merge branch 'master' into develop 2024-02-26 10:03:44 -05:00
Enrico Fraccaroli e31e40ba2e Merge branch 'master' into develop 2024-01-25 16:03:26 +01:00
Enrico Fraccaroli (Galfurian) ce9d95e4e8 Merge tag 'v0.6.0' into develop
Release v0.6.0.
2024-01-17 13:50:23 +01:00
77 changed files with 2245 additions and 485 deletions
+164 -165
View File
@@ -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 | | | | | | |
+1
View File
@@ -0,0 +1 @@
../../root
+22
View File
@@ -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.
+19
View File
@@ -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".
+5
View File
@@ -0,0 +1,5 @@
SYNOPSIS
false
DESCRIPTION
false sets the exit status to 1.
+15
View File
@@ -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
+13
View File
@@ -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
+3
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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); \
+1
View File
@@ -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.
+8 -7
View File
@@ -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
View File
@@ -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);
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+12
View File
@@ -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)
+14
View File
@@ -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)
+10
View File
@@ -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)
+1
View File
@@ -8,3 +8,4 @@
#include "system/syscall_types.h"
_syscall0(pid_t, getgid)
_syscall0(gid_t, getegid)
+1
View File
@@ -8,3 +8,4 @@
#include "system/syscall_types.h"
_syscall0(uid_t, getuid)
_syscall0(uid_t, geteuid)
+1
View File
@@ -8,3 +8,4 @@
#include "system/syscall_types.h"
_syscall1(int, setgid, pid_t, pid)
_syscall2(int, setregid, gid_t, rgid, gid_t, egid)
+1
View File
@@ -8,3 +8,4 @@
#include "system/syscall_types.h"
_syscall1(int, setuid, uid_t, pid)
_syscall2(int, setreuid, uid_t, ruid, uid_t, euid)
+3 -1
View File
@@ -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.
+4
View File
@@ -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.
+1
View File
@@ -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;
+18
View File
@@ -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);
/// @}
/// @}
+16
View File
@@ -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);
+22
View File
@@ -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);
+38
View 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 }
+8 -4
View File
@@ -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
+1
View File
@@ -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.
+5 -1
View File
@@ -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;
+29 -7
View File
@@ -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.
+1 -1
View File
@@ -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",
+3 -1
View File
@@ -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);
+2
View File
@@ -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)
+4 -1
View File
@@ -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
View File
@@ -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)
+105 -1
View File
@@ -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
}
/// @}
+167
View File
@@ -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;
}
+137
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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;
}
+133
View File
@@ -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;
}
+13
View File
@@ -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
+5 -6
View File
@@ -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)
+12
View File
@@ -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);
+77 -19
View File
@@ -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
View File
@@ -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;
+6
View File
@@ -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
View File
@@ -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;
}
+37
View File
@@ -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);
}
+65
View File
@@ -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);
}
+11
View File
@@ -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);
}
+30
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+87
View File
@@ -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;
}
+3 -1
View File
@@ -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
+2
View File
@@ -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);
+37
View File
@@ -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;
}
+64
View File
@@ -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;
}
-18
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -22,12 +22,12 @@ int main(int argc, char *argv[])
sched_setparam(cpid, &param);
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");
}
+6 -15
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+1 -13
View File
@@ -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;
+1 -1
View File
@@ -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);
}
+2 -2
View File
@@ -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;
}
+4 -6
View File
@@ -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;
+174
View File
@@ -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;
}