Refactor filesystem & stl code

This commit is contained in:
EnderIce2
2024-05-18 07:42:01 +03:00
parent 77a291d08b
commit 6801475243
186 changed files with 15784 additions and 9746 deletions

293
include/interface/driver.h Normal file
View File

@ -0,0 +1,293 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_DRIVER_FUNCTIONS_H__
#define __FENNIX_API_DRIVER_FUNCTIONS_H__
#include <types.h>
typedef enum
{
_drf_Entry,
_drf_Final,
_drf_Panic,
_drf_Probe,
} __driverRegFunc;
typedef union
{
struct
{
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
uint8_t Button6 : 1;
uint8_t Button7 : 1;
uint8_t Button8 : 1;
};
uint8_t Value;
} __MouseButtons;
typedef struct
{
/* PCIDevice */ void *Device;
/* __PCIArray */ void *Next;
} __PCIArray;
/* ========================================== */
#define PCI_END 0x0000
#define KEY_NULL 0x00
typedef enum
{
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEYPAD_7,
KEYPAD_8,
KEYPAD_9,
KEYPAD_MINUS,
KEYPAD_4,
KEYPAD_5,
KEYPAD_6,
KEYPAD_PLUS,
KEYPAD_1,
KEYPAD_2,
KEYPAD_3,
KEYPAD_0,
KEYPAD_PERIOD,
KEYPAD_RETURN,
KEYPAD_ASTERISK,
KEYPAD_SLASH,
KEY_LEFT_CTRL,
KEY_RIGHT_CTRL,
KEY_LEFT_SHIFT,
KEY_RIGHT_SHIFT,
KEY_LEFT_ALT,
KEY_RIGHT_ALT,
KEY_ESCAPE,
KEY_MINUS,
KEY_EQUAL,
KEY_BACKSPACE,
KEY_TAB,
KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET,
KEY_RETURN,
KEY_SEMICOLON,
KEY_APOSTROPHE,
KEY_BACK_TICK,
KEY_BACKSLASH,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_SPACE,
KEY_CAPS_LOCK,
KEY_NUM_LOCK,
KEY_SCROLL_LOCK,
KEY_PRINT_SCREEN,
KEY_HOME,
KEY_UP_ARROW,
KEY_LEFT_ARROW,
KEY_RIGHT_ARROW,
KEY_DOWN_ARROW,
KEY_PAGE_UP,
KEY_PAGE_DOWN,
KEY_END,
KEY_INSERT,
KEY_DELETE,
KEY_LEFT_GUI,
KEY_RIGHT_GUI,
KEY_APPS,
KEY_MULTIMEDIA_PREV_TRACK,
KEY_MULTIMEDIA_NEXT_TRACK,
KEY_MULTIMEDIA_MUTE,
KEY_MULTIMEDIA_CALCULATOR,
KEY_MULTIMEDIA_PLAY,
KEY_MULTIMEDIA_STOP,
KEY_MULTIMEDIA_VOL_DOWN,
KEY_MULTIMEDIA_VOL_UP,
KEY_MULTIMEDIA_WWW_HOME,
KEY_MULTIMEDIA_WWW_SEARCH,
KEY_MULTIMEDIA_WWW_FAVORITES,
KEY_MULTIMEDIA_WWW_REFRESH,
KEY_MULTIMEDIA_WWW_STOP,
KEY_MULTIMEDIA_WWW_FORWARD,
KEY_MULTIMEDIA_WWW_BACK,
KEY_MULTIMEDIA_MY_COMPUTER,
KEY_MULTIMEDIA_EMAIL,
KEY_MULTIMEDIA_MEDIA_SELECT,
KEY_ACPI_POWER,
KEY_ACPI_SLEEP,
KEY_ACPI_WAKE,
KEY_PRESSED = 0x80,
} KeyScanCodes;
typedef enum
{
IOCTL_AUDIO_GET_VOLUME = 0,
IOCTL_AUDIO_SET_VOLUME = 1,
IOCTL_AUDIO_GET_MUTE = 2,
IOCTL_AUDIO_SET_MUTE = 3,
IOCTL_AUDIO_GET_SAMPLE_RATE = 4,
IOCTL_AUDIO_SET_SAMPLE_RATE = 5,
IOCTL_AUDIO_GET_CHANNELS = 6,
IOCTL_AUDIO_SET_CHANNELS = 7,
} AudioIoctl;
typedef enum
{
IOCTL_NET_GET_MAC = 0,
} NetIoctl;
typedef enum
{
MAP_PRESENT = 1 << 0,
MAP_WRITE = 1 << 1,
MAP_USER = 1 << 2,
MAP_WRITE_THROUGH = 1 << 3,
MAP_CACHE_DISABLE = 1 << 4,
} PageMapFlags;
typedef struct
{
struct
{
uint8_t Major;
uint8_t Minor;
uint8_t Patch;
} APIVersion;
dev_t MajorID;
uintptr_t Base;
/* Internal */
int (*RegisterFunction)(dev_t MajorID, void *Function, __driverRegFunc Type);
int (*GetDriverInfo)(dev_t MajorID, const char *Name, const char *Description, const char *Author, const char *Version, const char *License);
/* Interrupts */
int (*RegisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*OverrideInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*UnregisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*UnregisterAllInterruptHandlers)(dev_t MajorID, void *Handler);
/* /dev/... */
dev_t (*RegisterDevice)(dev_t MajorID, char Prefix[8], void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterDevice)(dev_t MajorID, dev_t MinorID);
/* Logging */
void (*KPrint)(dev_t MajorID, const char *Format, va_list args);
void (*KernelLog)(dev_t MajorID, const char *Format, va_list args);
/* Memory */
void *(*RequestPages)(dev_t MajorID, size_t Pages);
void (*FreePages)(dev_t MajorID, void *Pointer, size_t Pages);
/* Mapping */
void (*AppendMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
void (*RemoveMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
void (*MapPages)(dev_t MajorID, void *PhysicalAddress, void *VirtualAddress, size_t Pages, uint32_t Flags);
void (*UnmapPages)(dev_t MajorID, void *VirtualAddress, size_t Pages);
/* Scheduling */
pid_t (*CreateKernelProcess)(dev_t MajorID, const char *Name);
pid_t (*CreateKernelThread)(dev_t MajorID, pid_t pId, const char *Name, void *EntryPoint, void *Argument);
pid_t (*GetCurrentProcess)(dev_t MajorID);
int (*KillProcess)(dev_t MajorID, pid_t pId, int ExitCode);
int (*KillThread)(dev_t MajorID, pid_t tId, pid_t pId, int ExitCode);
void (*Yield)(dev_t MajorID);
void (*Sleep)(dev_t MajorID, uint64_t Milliseconds);
/* PCI */
__PCIArray *(*GetPCIDevices)(dev_t MajorID, uint16_t Vendors[], uint16_t Devices[]);
void (*InitializePCI)(dev_t MajorID, void *Header);
uint32_t (*GetBAR)(dev_t MajorID, uint8_t Index, void *Header);
/* Kernel std API */
void *(*memcpy)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
void *(*memset)(dev_t MajorID, void *Destination, int Value, size_t Length);
void *(*memmove)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
int (*memcmp)(dev_t MajorID, const void *Left, const void *Right, size_t Length);
size_t (*strlen)(dev_t MajorID, const char *String);
char *(*strcpy)(dev_t MajorID, char *Destination, const char *Source);
char *(*strcat)(dev_t MajorID, char *Destination, const char *Source);
int (*strcmp)(dev_t MajorID, const char *Left, const char *Right);
int (*strncmp)(dev_t MajorID, const char *Left, const char *Right, size_t Length);
char *(*strchr)(dev_t MajorID, const char *String, int Character);
char *(*strrchr)(dev_t MajorID, const char *String, int Character);
char *(*strstr)(dev_t MajorID, const char *Haystack, const char *Needle);
} __driverAPI;
#endif // !__FENNIX_API_DRIVER_FUNCTIONS_H__

604
include/interface/errno.h Normal file
View File

@ -0,0 +1,604 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_ERRNO_H__
#define __FENNIX_KERNEL_ERRNO_H__
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
typedef enum
{
/**
* No Error
*/
EOK = 0,
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
E2BIG = 1,
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
EACCES = 2,
/**
* Address in use. The specified address is in use.
*/
EADDRINUSE = 3,
/**
* Address not available. The specified address is not available from
* the local system.
*/
EADDRNOTAVAIL = 4,
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
EAFNOSUPPORT = 5,
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
EAGAIN = 6,
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
EALREADY = 7,
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
EBADF = 8,
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
EBADMSG = 9,
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
EBUSY = 10,
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
ECANCELED = 11,
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
ECHILD = 12,
/**
* Connection aborted. The connection has been aborted.
*/
ECONNABORTED = 13,
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
ECONNREFUSED = 14,
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
ECONNRESET = 15,
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
EDEADLK = 16,
/**
* Destination address required. No bind address was established.
*/
EDESTADDRREQ = 17,
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
EDOM = 18,
/**
* Reserved.
*/
EDQUOT = 19,
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
EEXIST = 20,
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
EFAULT = 21,
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
EFBIG = 22,
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
EHOSTUNREACH = 23,
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
EIDRM = 24,
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
EILSEQ = 25,
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
EINPROGRESS = 26,
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
EINTR = 27,
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
EINVAL = 28,
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
EIO = 29,
/**
* Socket is connected. The specified socket is already connected.
*/
EISCONN = 30,
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
EISDIR = 31,
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
ELOOP = 32,
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
EMFILE = 33,
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
EMLINK = 34,
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
EMSGSIZE = 35,
/**
* Reserved.
*/
EMULTIHOP = 36,
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
ENAMETOOLONG = 37,
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
ENETDOWN = 38,
/**
* The connection was aborted by the network.
*/
ENETRESET = 39,
/**
* Network unreachable. No route to the network is present.
*/
ENETUNREACH = 40,
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
ENFILE = 41,
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
ENOBUFS = 42,
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
ENODATA = 43,
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
ENODEV = 44,
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
ENOENT = 45,
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
ENOEXEC = 46,
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
ENOLCK = 47,
/**
* Reserved.
*/
ENOLINK = 48,
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
ENOMEM = 49,
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
ENOMSG = 50,
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
ENOPROTOOPT = 51,
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
ENOSPC = 52,
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
ENOSR = 53,
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
ENOSTR = 54,
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
ENOSYS = 55,
/**
* Socket not connected. The socket is not connected.
*/
ENOTCONN = 56,
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- <slash> character and ends
* with one or more trailing <slash> characters.
*/
ENOTDIR = 57,
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
ENOTEMPTY = 58,
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
ENOTRECOVERABLE = 59,
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
ENOTSOCK = 60,
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
ENOTSUP = 61,
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
ENOTTY = 62,
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
ENXIO = 63,
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
EOPNOTSUPP = 64,
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
EOVERFLOW = 65,
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
EOWNERDEAD = 66,
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
EPERM = 67,
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
EPIPE = 68,
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
EPROTO = 69,
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
EPROTONOSUPPORT = 70,
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
EPROTOTYPE = 71,
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
ERANGE = 72,
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
EROFS = 73,
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
ESPIPE = 74,
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
ESRCH = 75,
/**
* Reserved.
*/
ESTALE = 76,
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
ETIME = 77,
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
ETIMEDOUT = 78,
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
ETXTBSY = 79,
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
EWOULDBLOCK = 80,
/**
* Improper link. A link to a file on another file system was attempted.
*/
EXDEV = 81,
__ERRNO_MAX
} KernelErrors;
#include <types.h>
EXTERNC int *__errno_location(void) __attribute__((const));
#define errno (*__errno_location())
#ifdef __cplusplus
extern "C"
{
#endif
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
#endif // !__FENNIX_KERNEL_ERRNO_H__

378
include/interface/fs.h Normal file
View File

@ -0,0 +1,378 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_FILESYSTEM_H__
#define __FENNIX_API_FILESYSTEM_H__
#ifdef __kernel__
#include <types.h>
#endif
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/**
* File type mask for the upper 32 bits of mode_t.
*
* @note Maybe it will be used in the future.
*/
#define S_IFMT32 037777600000
/**
* File type mask.
*
* This mask is used to extract the file type
* from the mode field of a stat structure.
*
* Doing bitwise AND with this mask will return
* the file type.
* Example: st_mode & S_IFMT
*
* Doing bitwise negation and AND with this mask
* will return the permissions.
* Example: st_mode & ~S_IFMT
*/
#define S_IFMT 0170000
/* Whiteout */
#define S_IFWHT 0160000
/* Socket */
#define S_IFSOCK 0140000
/* Symbolic link */
#define S_IFLNK 0120000
/* Regular file */
#define S_IFREG 0100000
/* Block device */
#define S_IFBLK 0060000
/* Directory */
#define S_IFDIR 0040000
/* Character device */
#define S_IFCHR 0020000
/* FIFO */
#define S_IFIFO 0010000
#define S_ISUID 04000
#define S_ISGID 02000
#define S_ISVTX 01000
/** Owner: RWX */
#define S_IRWXU 0700
/** Owner: R */
#define S_IRUSR 0400
/** Owner: W */
#define S_IWUSR 0200
/** Owner: X */
#define S_IXUSR 0100
/** Group: RWX */
#define S_IRWXG 0070
/** Group: R */
#define S_IRGRP 0040
/** Group: W */
#define S_IWGRP 0020
/** Group: X */
#define S_IXGRP 0010
/** Other: RWX */
#define S_IRWXO 0007
/** Other: R */
#define S_IROTH 0004
/** Other: W */
#define S_IWOTH 0002
/** Other: X */
#define S_IXOTH 0001
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define DT_UNKNOWN 0x0
#define DT_FIFO 0x1
#define DT_CHR 0x2
#define DT_DIR 0x4
#define DT_BLK 0x6
#define DT_REG 0x8
#define DT_LNK 0xA
#define DT_SOCK 0xC
#define DT_WHT 0xE
#define IFTODT(x) ((x) >> 12 & 0xF)
#define DTTOIF(x) ((x) << 12)
#define SYMLOOP_MAX 40
#ifndef __cplusplus
#define static_assert _Static_assert
#endif
#ifdef __LP64__
static_assert(sizeof(dev_t) == 8, "dev_t must be 64 bits");
static_assert(sizeof(ino_t) == 8, "ino_t must be 64 bits");
static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
static_assert(sizeof(off_t) == 8, "off_t must be 64 bits");
static_assert(sizeof(time_t) == 8, "time_t must be 64 bits");
static_assert(sizeof(blksize_t) == 8, "blksize_t must be 64 bits");
static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
#else
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits");
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits");
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits");
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits");
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");
static_assert(sizeof(blkcnt_t) == 4, "blkcnt_t must be 32 bits");
#endif
#undef static_assert
struct kstat
{
/** Device ID of the file. */
dev_t Device;
/** Inode number. */
ino_t Index;
/** File type and mode. */
mode_t Mode;
/** Number of hard links. */
nlink_t HardLinks;
/** User ID of the file's owner. */
uid_t UserID;
/** Group ID of the file's owner. */
gid_t GroupID;
/** Device ID for special files. */
dev_t RawDevice;
/** Size of the file in bytes. */
off_t Size;
/** Time of last access. */
time_t AccessTime;
/** Time of last modification. */
time_t ModifyTime;
/** Time of last status change. */
time_t ChangeTime;
/** Optimal I/O block size. */
blksize_t BlockSize;
/** Number of blocks allocated. */
blkcnt_t Blocks;
/** Additional file attributes. */
mode_t Attribute;
#ifdef __cplusplus
dev_t MakeDevice(int Major, int Minor)
{
return ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(Device) >> 8) & 0xFFF;
}
int GetMinor()
{
return Device & 0xFF;
}
void SetFileType(mode_t Type)
{
Mode = (Mode & ~S_IFMT) |
(Type & S_IFMT);
}
mode_t GetFileType() { return Mode & S_IFMT; }
void ClearFileType() { Mode = Mode & ~S_IFMT; }
bool IsType(mode_t Type) { return (Mode & S_IFMT) == Type; }
void SetPermissions(mode_t Permissions)
{
Mode = (Mode & S_IFMT) |
(Permissions & ~S_IFMT);
}
mode_t GetPermissions() { return Mode & ~S_IFMT; }
void ClearPermissions() { Mode = Mode & S_IFMT; }
#endif // __cplusplus
};
struct kdirent
{
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
struct InodeOperations
{
int (*Lookup)(struct Inode *Parent, const char *Name, struct Inode **Result);
int (*Create)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*Remove)(struct Inode *Parent, const char *Name);
int (*Rename)(struct Inode *Parent, const char *OldName, const char *NewName);
ssize_t (*Read)(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t (*Write)(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
int (*Truncate)(struct Inode *Node, off_t Size);
int (*Open)(struct Inode *Node, int Flags, mode_t Mode);
int (*Close)(struct Inode *Node);
int (*Ioctl)(struct Inode *Node, unsigned long Request, void *Argp);
ssize_t (*ReadDir)(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
int (*MkDir)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*RmDir)(struct Inode *Parent, const char *Name);
int (*SymLink)(struct Inode *Parent, const char *Name, const char *Target, struct Inode **Result);
ssize_t (*ReadLink)(struct Inode *Node, char *Buffer, size_t Size);
off_t (*Seek)(struct Inode *Node, off_t Offset);
int (*Stat)(struct Inode *Node, struct kstat *Stat);
} __attribute__((packed));
#define I_FLAG_MOUNTPOINT 0x1
#define I_FLAG_CACHE_KEEP 0x2
struct Inode
{
dev_t Device, RawDevice;
ino_t Index;
mode_t Mode;
uint32_t Flags;
off_t Offset;
void *PrivateData;
#ifdef __cplusplus
/* ... */
void SetDevice(int Major, int Minor)
{
this->RawDevice = ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(this->RawDevice) >> 8) & 0xFFF;
}
int GetMinor()
{
return this->RawDevice & 0xFF;
}
Inode()
{
Index = 0;
Mode = 0;
Device = 0;
RawDevice = 0;
Flags = 0;
PrivateData = nullptr;
}
~Inode() = default;
#else // __cplusplus
#define INODE_MAKEDEV(major, minor) \
((dev_t)(((major & 0xFFF) << 8) | \
(minor & 0xFF)))
#define INODE_MAJOR(rdev) \
((int)(((rdev) >> 8) & 0xFFF))
#define INODE_MINOR(rdev) \
((int)((rdev) & 0xFF))
#endif // __cplusplus
};
struct SuperBlockOperations
{
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
int (*DeleteInode)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Synchronize the filesystem.
*
* Write all pending changes to the disk.
*
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
*
* @return Zero on success, otherwise an error code.
*/
int (*Synchronize)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Destroy the filesystem.
*
* Unregister the filesystem and free all resources.
*
* @param Info Filesystem to destroy.
*
* @return Zero on success, otherwise an error code.
*/
int (*Destroy)(FileSystemInfo *Info);
} __attribute__((packed));
struct FileSystemInfo
{
const char *Name;
int Flags;
struct SuperBlockOperations SuperOps;
struct InodeOperations Ops;
void *PrivateData;
} __attribute__((packed));
dev_t RegisterFileSystem(FileSystemInfo *Info, struct Inode *Root);
int UnregisterFileSystem(dev_t Device);
#endif // !__FENNIX_API_FILESYSTEM_H__

View File

@ -0,0 +1,111 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef syscall0
static inline long syscall0(long syscall)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall1
static inline long syscall1(long syscall, long arg1)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall2
static inline long syscall2(long syscall, long arg1, long arg2)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall3
static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall4
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
{
long ret;
register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall5
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall6
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#endif
#endif // !__FENNIX_API_SYSCALLS_LIST_H__