Return to Docs

The PortaLinux C API: Base Runtime

For release 1.07


The PortaLinux Runtime is the runtime for PortaLinux applications written in the C programming language and it is a foundational part of the PortaLinux C API, containing crucial routines such as the memory tracker and string tokenizer. This documentation page will detail all of the functions and types within it.

Section 1: Types


These are all of the defined types within the PortaLinux Runtime. They are not all in the same header, as having all types in one header wouldn't have allowed for self-contained modules.

Aliases and Abstract Types

Section 1.1


These variable types are either aliases to built-in types in C, or abstract structures. Due to the lack of actual things to document, they will all be within the same page.

byte_t

typedef uint8_t byte_t;

This is an alias for an unsigned 8-bit integer.

memptr_t

typedef void* memptr_t;

This is an alias for an untyped pointer.

plmt_t

typedef struct plmt plmt_t;

This is the structure for the Memory Tracker API. It keeps track of how many allocations have been made as well as how big each allocation is.

plfile_t

typedef struct plfile plfile_t;

This is the structure for the File Operations API. It holds the file pointer if an actual file, or a memory buffer if a memory file. It also keeps track of the offset position as well as other information.

plptr_t

Section 1.2


A structure made for representing pointers while keeping size information. It has a size field in addition to the untyped pointer field. This structure is the base for most other complex types in the Runtime.

Definition

typedef struct plptr { memptr_t pointer; size_t size; } plptr_t;

plrtret_t

Section 1.3


An enumerator that defines any and all possible errors that could be thrown by the Runtime as an unsigned 64-bit integer. Upper 16 bits are flags, lower 48 bytes are an error number. This is mainly used by function plRTErrorString.

Definition/Value List

typedef enum plrtret { PLRT_ERROR = ((uint64_t)1 << UINT_SHIFT_LIMIT), // Flag. Declares this unsigned 64-bit integer as a Runtime error. PLRT_ERRNO = ((uint64_t)1 << (UINT_SHIFT_LIMIT - 1)), // Flag. Declares that this error code is a POSIX errno number instead of a Runtime error number. PLRT_OOM = 1, // System or Memory Tracker is out of memory. Error thrown when allocating over the allocation limit or when internal allocation fails. PLRT_FAILED_ALLOC = 2, // Memory Tracker failed to allocate memory. Could happen due to a number of reasons. PLRT_INVALID_PTR = 3, // Invalid Pointer Given. This error code is unused by the Runtime, but it was most likely originally used for reallocation failures. PLRT_NULL_PTR = 4, // Null Pointer Given. This is the most used error code within the Runtime. It's used by all functions that take a pointer, which is almost all of them. PLRT_ACCESS = 5, // Access to resource has been denied. Unused within the Runtime, might've been used by the PortaLinux Init System. PLRT_INVALID_MODE = 6, // Invalid file mode. Error thrown when trying to open a physical file with a mode that is not supported. PLRT_ALREADY_EXISTS = 7, // File already exists. Unused within the Runtime, might've been used by the PortaLinux Init System. PLRT_NO_EXIST = 8, // File doesn't exist. Unused within the Runtime, might've been used by the PortaLinux Init System. PLRT_IOERR = 9, // Generic Input/Output error. Used in some File Operations API functions PLRT_NOT_DIR = 10, // Not a directory. Unused within the Runtime, might've been used by the PortaLinux Init System. PLRT_NOT_FILE = 11, // Not a file. Unused within the Runtime, might've been used by the PortaLinux Init System. PLRT_NOT_PLCHAR = 12, // Not a UTF-32/plchar_t string. Used within some String Operations API functions that require UTF-32 strings. PLRT_NOT_COMPRESSED = 13, // Not a C-style string. Almost all functions within the String Operations API as well as the entire String Parsing API throw this error. PLRT_MATCH_NOT_FOUND = 14, // Could not find match in string. Originally used within the searcher functions in the String Operations API prior to being refactored before 1.00. Mostly just a pl32lib relic. PLRT_TOKENIZER_FAILURE = 15, // Internal Tokenizer failure. Currently unused within the Runtime, but originally used to debug the tokenizer prior to 1.00. PLRT_TOKENIZER_WTF = 16, // This error should never be thrown. If you get it, either something is deeply wrong with your device or you just modified the code. PLRT_INVALID_TOKEN = 17, // Invalid PLML Token. Error thrown when trying to parse an invalid PLML token. PLRT_INCOMPATIBLE_FILETYPE = 18, // Incompatible memory file type. Currently only thrown by one function within the File Operations API (This is bound to change). Happens when a function only supports binary memory files. PLRT_MISMATCHED_DATAFORM = 19 // Mismatched data formats. Currently only thrown by one function within the File Operations API (This is also bound to change). Happens when a function is given a UTF-32/plchar_t string to write into a binary memory file and vice-versa. } plrtret_t;

Example Usage

In order to have the final error number, the flags and the base error number must be bitwise OR'd, like so:

plrtret_t errCode = PLRT_ERROR | PLRT_NULL_PTR;

plmtaction_t

Section 1.4


An enumerator for telling plMTMemAmnt what information to return

Definition/Value List

typedef enum plmtaction { PLMT_GET_USEDMEM, // Get the current usage PLMT_GET_MAXMEM, // Get the maximum amount that can be used PLMT_SET_MAXMEM // Set a new maximum amount } plmtaction_t;

plchar_t

Section 1.5


A structure (will eventually be turned into a union) made for representing UTF-8/16/32 characters. Within the Runtime, it's mainly used for representing UTF-8 characters in a fixed-width way. It only has a bytes field, which is just an array of 4 unsigned 8-bit integers.

Definition

typedef struct plchar { byte_t bytes[4]; } plchar_t;

plstring_t

Section 1.6


A structure that represents a Rust-style Unicode string. It has a data field, which contains the actual string data as well as the size, a memory tracker pointer field as a way to tell whether or not it's allocated, and a boolean field that determines whether the string is a UTF-32/plchar_t string or not.

Definition

typedef struct plstring { plptr_t data; plmt_t* mt; bool isplChar; } plstring_t;

plmltype_t

Section 1.7


An enumerator for all of the types supported by the PortaLinux Markup Language. Used by plmltoken_t and plsimpletoken_t

Definition/Value List

typedef enum plmltype { PLML_TYPE_NULL, // Null Value. Default value. PLML_TYPE_INT, // Integer. PLML_TYPE_BOOL, // Boolean. PLML_TYPE_FLOAT, // Floating-point Number, Double-Precision. PLML_TYPE_STRING, // String. PLML_TYPE_HEADER // Header. } plmltype_t;

plmlval_t

Section 1.8


A union for representing the value of a PortaLinux Markup Language token. Used by plmltoken_t and plsimpletoken_t

Definition

typedef union plmlval { long integer; bool boolean; double decimal; plptr_t string; plptr_t array; } plmlval_t;

plsimpletoken_t

Section 1.9


A simplified version of plmltoken_t. It only has a value field as well as a type field. It's only used by internal PortaLinux Markup Language API functions.

Definition

typedef struct simpletoken { plmltype_t type; plmlval_t value; } plsimpletoken_t;

plmltoken_t

Section 1.10


A structure that defines a parsed PortaLinux Markup Language token. It has a name field, a type field, a value field, a boolean field to determine whether or nit it's an array and a read-only memory tracker pointer field.

Definition

typedef struct plmltoken { plstring_t name; plmltype_t type; plmlval_t value; bool isArray; const plmt_t* const mt; } plmltoken_t;

plloglevel_t

Section 1.11


An enumerator for the logger functions within the Miscellaneous POSIX-Dependent functions group.

Definition

typedef enum plloglevel { LOG_DEBUG, // Debug Log Level LOG_INFO, // Info Log Level LOG_WARNING, // Warning Log Level LOG_ERROR, // Error Log Level LOG_FATAL_ERROR // Fatal Error Log Level } plloglevel_t;

Section 2: Error Handling API


This API is used for error-handling within and outside the Runtime. Supported error codes can be seen here

plRTErrorString

Section 2.1


Puts an error string in the given pointer to the fat pointer structure. This structure must contain a pointer to a string buffer, it cannot be null. The error string given is determined by the error code given.

Definition

void plRTErrorString(plptr_t* buffer, plrtret_t errCode);

Example Usage

char charBuffer[512] = "" plptr_t stringPointer = { .pointer = charBuffer, .size = 512 }; plRTErrorString(&stringPointer, PLRT_ERROR | PLRT_NULL_PTR); printf("%s\n", charBuffer); // Outputs 'The pointer(s) given is/are NULL'

plRTPanic

Section 2.2


Prints an error message before aborting the program. There is also a boolean toggle for printing an extra message denoting the panic as a bug within the software.

Definition

void plRTPanic(char* msg, plrtret_t errCode, bool isDeveloperBug);

Example Usage

if(pointer == NULL) plRTPanic("main", PLRT_ERROR | PLRT_NULL_PTR, true);

Section 3: Memory Tracker API


This API is used for safe memory management within the Runtime.

plMTInit

Section 3.1


Initializes a memory tracker structure (plmt_t) and returns it. The given size becomes the new allocation limit. If this value is 0, it will default to a 128MiB allocation limit.

No Null Return Guarantee: This function will always return a valid pointer.

Definition

plmt_t* plMTInit(size_t maxMemoryAlloc);

Example Usage

plmt_t* memoryTracker = plMTInit(64 * 1024);

plMTStop

Section 3.2


Deallocates all allocation entries, and deallocate the entire memory tracker structure.

Definition

void plMTStop(plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(64 * 1024); plMTStop(memoryTracker);

plMTMemAmnt

Section 3.3


Gets either current amount of memory allocated, the current allocation limit or sets a new allocation limit depending on the action enumerator value given (See plmtaction_t).

Definition

size_t plMTMemAmnt(plmt_t* mt, plmtaction_t action, size_t size);

Example Usage

plmt_t* memoryTracker = plMTInit(64 * 1024); size_t currentMaxAmnt = plMTMemAmnt(&memoryTracker, PLMT_GET_MAXMEM, 0); printf("%d\n", currentMaxAmnt); // Outputs '65535' plMTStop(memoryTracker);

plMTAlloc

Section 3.4


Allocates a memory buffer of the given size and returns a pointer to it.

No Null Return Guarantee: This function will always return a valid pointer.

Definition

memptr_t plMTAlloc(plmt_t* mt, size_t size);

Example Usage

plmt_t* memoryTracker = plMTInit(64 * 1024); size_t currentUsage = plMTMemAmnt(&memoryTracker, PLMT_GET_USEDMEM, 0); printf("%d\n", currentUsage); // Outputs '0' char* string = plMTAlloc(memoryTracker, 256); currentUsage = plMTMemAmnt(&memoryTracker, PLMT_GET_USEDMEM, 0); printf("%d\n", currentUsage); // Outputs '256' plMTStop(memoryTracker);

plMTRealloc

Section 3.5


Resizes the given buffer to the given new size and returns the new pointer.

Definition

memptr_t plMTRealloc(plmt_t* mt, memptr_t pointer, size_t size);

Example Usage

plmt_t* memoryTracker = plMTInit(64 * 1024); char* string = plMTAlloc(memoryTracker, 256); size_t currentUsage = plMTMemAmnt(&memoryTracker, PLMT_GET_USEDMEM, 0); printf("%d\n", currentUsage); // Outputs '256' plMTRealloc(memoryTracker, string, 512); currentUsage = plMTMemAmnt(&memoryTracker, PLMT_GET_USEDMEM, 0); printf("%d\n", currentUsage); // Outputs '512' plMTRealloc(memoryTracker, string, 128); currentUsage = plMTMemAmnt(&memoryTracker, PLMT_GET_USEDMEM, 0); printf("%d\n", currentUsage); // Outputs '128' plMTStop(memoryTracker);

plMTFree

Section 3.6


Frees up the memory buffer given as well as its entry within the memory tracker.

Definition

void plMTFree(plmt_t* mt, memptr_t pointer);

Example Usage

plmt_t* memoryTracker = plMTInit(64 * 1024); char* string = plMTAlloc(memoryTracker, 256); size_t currentUsage = plMTMemAmnt(&memoryTracker, PLMT_GET_USEDMEM, 0); printf("%d\n", currentUsage); // Outputs '256' plMTFree(memoryTracker, string); currentUsage = plMTMemAmnt(&memoryTracker, PLMT_GET_USEDMEM, 0); printf("%d\n", currentUsage); // Outputs '0' plMTStop(memoryTracker);

Section 4: String Operations API


This API is used as a replacement for the Standard C Library string functions, which have a lot of modern features missing, such as UTF-8 support. The Runtime's String Operations API adds these features as well as better string tokenizers and memory search functions. It is recommended to become acquainted with the plchar_t and plstring_t structures

plRTGetUTFCharSize

Section 4.1


Returns the size of a UTF-8 character.

Definition

size_t plRTGetUTFCharSize(uint8_t chr);

Example Usage

plchar_t utfChar = { .bytes = "ñ" }; size_t sizeOfUTFChar = plRTGetUTFCharSize(utfChar.bytes[0]); // Should return '2'

plRTStrFromCStr

Section 4.2


Converts a C-style string (cStr) into a plstring_t structure. A memory tracker structure can be passed in order to duplicate the given string and place it into a memory-allocated buffer. Returns the converted string.

No Null Return Guarantee: This function will always return a valid pointer.

Definition

plstring_t plRTStrFromCStr(char* cStr, plmt_t* mt);

Example Usage

// This would be memory allocated plmt_t* memoryTracker = plMTInit(1024); char cString[64] = "Hello, World!"; plstring_t safeString = plRTStrFromCStr(cString, memoryTracker);

// This would not be memory allocated plstring_t otherSafeString = plRTStrFromCStr("Hello, World!", NULL);

plRTStrFromPLPtr

Section 4.3


Converts a Runtime pointer structure (plptr_t) into a plstring_t structure. A memory tracker structure can be passed in order to duplicate the given string and place it into a memory-allocated buffer. It also has a two more arguments; one to specify whether or not a string is a UTF-32/plchar_t string and another to specify whether or not this pointer points to the heap (If not, it will utilize the given memory tracker structure to allocate a buffer). Returns the converted string.

Definition

plstring_t plRTStrFromPLPtr(plptr_t pointer, plmt_t* mt, bool isplChar, bool isMemAlloc);

Example Usage

char string[64] = "Hello, World!"; plptr_t rtStringPointer = { .pointer = string, .size = strlen(string) }; plstring_t safeString = plRTStrFromPLPtr(rtStringPointer, NULL, false, false);

plRTStrCompress

Section 4.4


Converts a plchar_t array into a C-style string. The memory tracker structure is required.

No Null Return Guarantee: This function will always return a valid pointer.

Definition

void plRTStrCompress(plstring_t* plCharStr, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plchar_t charString = { { .bytes = "H" }; { .bytes = "e" }; { .bytes = "l" }; { .bytes = "l" }; { .bytes = "o" }; }; plstring_t safeString = { .data = { .pointer = charString, .size = 5 }, .mt = NULL, .isplChar = true }; plRTStrCompress(safeString, memoryTracker);

plRTStrDecompress

Section 4.5


Converts a C-style string into a plchar_t array. The memory tracker structure is required.

No Null Return Guarantee: This function will always return a valid pointer.

Definition

void plRTStrDecompress(plstring_t* cStr, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char cString[64] = "Hello, World!"; plstring_t safeString = plRTStrFromCStr(cString, memoryTracker); plRTStrDecompress(safeString, memoryTracker);

plRTMemMatch

Section 4.6


Finds a match of memBlock2 within memBlock1. memBlock2 cannot be bigger than memBlock1.

Definition

memptr_t plRTMemMatch(plptr_t memBlock1, plptr_t memBlock2);

Example Usage

char string[64] = "Hello, World!"; char matchString[4] = "Wor"; plptr_t ptrToString = { .pointer = string, .size = strlen(string) }; plptr_t ptrToMString = { .pointer = matchString, .size = 3 }; memptr_t pointerToMatch = plRTMemMatch(ptrToString, ptrToMString); // Should return (string + 7)

plRTStrcmp

Section 4.7


Compares two strings. Returns 0 if exactly the same, a positive value if string1 is bigger, or a negative value if string2 is bigger.

Definition

int plRTStrcmp(plstring_t string1, plstring_t string2);

Example Usage

char string[64] = "Hello, World!"; plstring_t string1 = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plstring_t string2 = { .data = { .pointer = string, .size = string1.size - 1 }, .mt = NULL, .isplChar = false }; printf("%d", plRTStrcmp(string1, string2)); // Outputs positive value printf("%d", plRTStrcmp(string2, string1)); // Outputs negative value printf("%d", plRTStrcmp(string1, string1)); // Outputs '0'

plRTStrchr

Section 4.8


Searches the given character within the given string. The third argument determines the search start position.

Definition

int64_t plRTStrchr(plstring_t string, plchar_t chr, size_t startAt);

Example Usage

char string[64] = "Hello, World!"; plchar_t searchChar = { .bytes = "l"}; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; int64_t charPosition = plRTStrchr(safeString, searchChar, 0); // Returns '3'

plRTStrstr

Section 4.9


Searches string2 within string1. The third argument determines the search start position.

Definition

int64_t plRTStrstr(plstring_t string1, plstring_t string2, size_t startAt);

Example Usage

char string[64] = "Hello, World!"; char matchString[4] = "Wor"; plstring_t string = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plstring_t searchString = { .data = { .pointer = matchString, .size = 3 }, .mt = NULL, .isplChar = false }; int64_t patternPosition = plRTStrstr(string, searchString, 0); // Returns '7'

plRTStrtok

Section 4.10


Generates a memory-allocated token from the given string determined by the given delimiters. The string to tokenize must always be stored in string and the ending state is stored in leftoverStr.

Definition

plstring_t plRTStrtok(plstring_t string, plstring_t delimiter, plstring_t* leftoverStr, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "Hello, World!"; plstring_t tokens[2]; plstring_t endingState; plchar_t delimiters = { { .bytes = "\n" }; { .bytes = " " }; { .bytes = "," }; { .bytes = "!" }; }; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plstring_t safeDelimiters = { .data = { .pointer = delimiters, .size = 4 }, .mt = NULL, .isplChar = true }; tokens[0] = plRTStrtok(safeString, safeDelimiters, &endingState, memoryTracker); tokens[1] = plRTStrtok(endingState, safeDelimiters, &endingState, memoryTracker); printf("'%s','%s'\n", tokens[1], tokens[0]); // Outputs "'World','Hello'"

plRTStrdup

Section 4.11


Duplicates a string. If the string is a UTF-32/plchar_t string, it can be ran through plRTCompress by setting the compress argument to true. Returns duplicated string in a memory-allocated buffer.

Definition

plstring_t plRTStrdup(plstring_t string, bool compress, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "Hello, World!"; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plstring_t duplicatedString = plRTStrdup(safeString, false, memoryTracker);

Section 5: File Operations API


This API reimplements the Standard C Library file functions and adds memory-allocated buffer support (similar to GNU's fmemopen).

plFMemCreate

Section 5.1


Creates a memory-allocated buffer encapsulated within a file handle (plfile_t), which can then be used with all of the standard file functions. This is the only way to create a text-mode memory buffer file.

No Null Return Guarantee: This function will always return a valid pointer.

Definition

plfile_t* plFMemCreate(bool textMode, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memoryBuffer = plFMemCreate(false, memoryTracker);

plFOpen

Section 5.2


Creates a file handle. if path is null, then it will create a binary-mode memory buffer file.

No Null Return Guarantee: This function will always return a valid pointer.

Definition

plfile_t* plFOpen(char* filename, char* mode, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* realFile = plFOpen("file.txt", "r+", memoryTracker);

plFToP

Section 5.3


Converts a Standard C Library file handle into a Runtime file handle (plfile_t).

Definition

plfile_t* plFToP(FILE* pointer, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); FILE* file = fopen("file.txt", "r+"); plfile_t* rFile = plFToP(file, memoryTracker);

plFClose

Section 5.4


Closes a file handle.

Definition

plfile_t* plFClose(plfile_t* ptr);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* realFile = plFOpen("file.txt", "r+", memoryTracker); plFClose(realFile);

plFRead

Section 5.5


Reads from the file stream and puts it into the given buffer. The amount of bytes (plchar_t characters when using a text-mode memory buffer file) is determined by the size of the buffer given (ptr.size).

Definition

size_t plFRead(plptr_t ptr, plfile_t* stream);

Example Usage

char buffer[64]; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* realFile = plFOpen("file.txt", "r+", memoryTracker); plptr_t safeBuffer = { .pointer = buffer, .size = 64 }; plFRead(safeBuffer, realFile); plFClose(realFile);

plFWrite

Section 5.6


Writes the contents of the given buffer into the file stream. The amount of bytes (plchar_t characters when using a text-mode memory buffer file) is determined by the size of the buffer given (ptr.size).

Definition

size_t plFWrite(plptr_t ptr, plfile_t* stream);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); // See #plFSeek (Section 5.7) plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s\n", buffer); // Outputs 'Hello, World!'

plFSeek

Section 5.7


Moves file offset position to specified location (See fseek(3)).

Definition

size_t plFSeek(plfile_t* stream, long int offset, int whence);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 2, SEEK_SET); plFWrite(safeBuffer, memFile); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s\n", charBuffer); // Outputs 'HelHello, World!'

plFTell

Section 5.8


Tells the current file offset position.

Definition

size_t plFTell(plfile_t* stream);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 2, SEEK_SET); plFWrite(safeBuffer, memFile); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s; %d\n", buffer, plFTell(memFile)); // Outputs 'HelHello, World!; 25'

plFPutPLChar

Section 5.9


Puts a UTF-32/plchar_t character into the file stream.

Definition

bool plFPutPLChar(plchar_t ch, plfile_t* stream);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; plchar_t exclamation = { .bytes = "!"}; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 2, SEEK_SET); plFWrite(safeBuffer, memFile); plFPutPLChar(exclamation, memFile); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s\n", buffer); // Outputs 'HelHello, World!!'

plFGetPLChar

Section 5.10


Gets a UTF-32/plchar_t character from the file stream.

Definition

bool plFGetPLChar(plchar_t* ch, plfile_t* stream);

Example Usage

plchar_t bufChar; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 4, SEEK_SET); plFGetPLChar(&bufChar, memFile); plFClose(realFile); printf("%c\n", bufChar.bytes[0]); // Outputs 'o'

plFInsert

Section 5.11


Inserts the bytes (plchar_t characters when using a text-mode memory buffer file) in bytes.

Definition

void plFInsert(plfile_t* stream, plptr_t bytes);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 2, SEEK_SET); plFInsert(memFile, safeBuffer); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s\n", buffer); // Outputs 'HelHello, World!lo, World!'

plFRemove

Section 5.12


Removes the bytes (plchar_t characters when using a text-mode memory buffer file) specified in amount.

Definition

void plFRemove(plfile_t* stream, size_t amount, bool removeLeftToRight);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 2, SEEK_SET); plFRemove(memFile, 3, true); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s\n", buffer); // Outputs 'Helorld!'

char buffer[64]; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 5, SEEK_SET); plFRemove(memFile, 3, false); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s\n", buffer); // Outputs 'He, World!'

plFPutC

Section 5.13


Puts an ASCII character into the file stream.

Definition

int plFPutC(char ch, plfile_t* stream);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; char exclamation = '!'}; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 2, SEEK_SET); plFWrite(safeBuffer, memFile); plFPutC(exclamation, memFile); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFRead(safeBuffer, memFile); plFClose(realFile); printf("%s\n", buffer); // Outputs 'HelHello, World!!'

plFGetC

Section 5.14


Gets an ASCII character from the file stream.

Definition

int plFGetC(plfile_t* stream);

Example Usage

char bufChar; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plptr_t safeBuffer = { .pointer = string, .size = strlen(string) }; plFWrite(safeBuffer, memFile); plFSeek(memFile, 4, SEEK_SET); bufChar = plFGetC(memFile); plFClose(realFile); printf("%c\n", bufChar); // Outputs 'o'

plFPuts

Section 5.15


Writes the contents of the given buffer into the file stream. The amount of bytes (plchar_t characters when using a text-mode memory buffer file) is determined by the size of the buffer given (string.data.size).

Definition

size_t plFPuts(plstring_t string, plfile_t* stream);

Example Usage

char buffer[64]; char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* memFile = plFOpen(NULL, "w+", memoryTracker); plstring_t safeBuffer = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plFPuts(safeBuffer, memFile); safeBuffer.pointer = buffer; safeBuffer.size = 64; plFSeek(memFile, 0, SEEK_SET); plFGets(&safeBuffer, memFile); // See Section plFGets plFClose(realFile); printf("%s\n", buffer); // Outputs 'Hello, World!'

plFGets

Section 5.16


Reads from the file stream and puts it into the given buffer. The amount of bytes is determined by the size of the buffer given (string->data.size).

Definition

size_t plFGets(plstring_t* string, plfile_t* stream);

Example Usage

char buffer[64]; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* realFile = plFOpen("file.txt", "r+", memoryTracker); plstring_t safeBuffer = { .data = { .pointer = buffer, .size = 64 }, .mt = NULL, .isplChar = false }; plFGets(&safeBuffer, realFile); plFClose(realFile);

plFFlush

Section 5.17


Forces a write of all buffered data if an output stream, and discards all buffered data if an input stream (See fflush(3)). This function is a no-op on memory buffer files.

Definition

void plFFlush(plfile_t* stream);

Example Usage

char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* realFile = plFOpen("file.txt", "r+", memoryTracker); plstring_t safeBuffer = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plFPuts(safeBuffer, realFile); plFFlush(realFile); plFClose(realFile);

plFLoad

Section 5.18


Loads a physical file into memory, effectively turning it into a memory buffer file.

Definition

void plFFLoad(plfile_t* stream);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* realFile = plFOpen("file.txt", "r+", memoryTracker); plFLoad(realFile);

plFUnload

Section 5.19


Writes all contents of the memory buffer into the actual physical file currently loaded into memory.

Definition

void plFUnload(plfile_t* stream);

Example Usage

char string[64] = "Hello, World!"; plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* realFile = plFOpen("file.txt", "r+", memoryTracker); plFLoad(realFile); plFPuts(safeBuffer, realFile); plFUnload(realFile); plFClose(realFile);

Section 6: String Parsing API


This API implements a string tokenizer/parser similar to that of the Unix shell interpreter. This could be considered an extension of the String Operations API

plRTTokenize

Section 6.1


Similar to plRTStrtok, but token generation is similar to that of the Unix shell interpreter and thus delimiters are not controlled by the user.

Definition

plstring_t plRTTokenize(plstring_t string, plstring_t* leftoverStr, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "Hello, World!"; plstring_t tokens[2]; plstring_t endingState; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; tokens[0] = plRTTokenize(safeString, &endingState, memoryTracker); tokens[1] = plRTTokenize(endingState, &endingState, memoryTracker); printf("'%s','%s'\n", tokens[1], tokens[0]); // Outputs "'World','Hello'"

plRTParser

Section 6.2


Fully tokenizes a string into an array of tokens. It's the equivalent of this code snippet:

int iterator = 0; tokens[0] = plRTTokenize(safeString, &endingState, memoryTracker); while(leftoverStr.data.pointer != NULL) tokens[i] = plRTTokenize(endingState, &endingState, memoryTracker);

Definition

plptr_t plRTParser(plstring_t string, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "variable = \"Hello, World!\""; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plptr_t tokens = plRTParser(safeString, memoryTracker); plstring_t* rawTokens = tokens.pointer; printf("'%s','%s','%s'\n", rawTokens[0].data.pointer, rawTokens[1].data.pointer, rawTokens[2].data.pointer); // Outputs "'variable','=','"Hello, World!"'"

plRTFreeParsedString

Section 6.3


Frees the string array generated by plRTParser.

Definition

void plRTFreeParsedString(plptr_t stringArray);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "variable = \"Hello, World!\""; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plptr_t tokens = plRTParser(safeString, memoryTracker); plstring_t* rawTokens = tokens.pointer; printf("'%s','%s','%s'\n", rawTokens[0].data.pointer, rawTokens[1].data.pointer, rawTokens[2].data.pointer); // Outputs "'variable','=','"Hello, World!"'" plRTFreeParsedString(tokens);

plRTExtractContents

Section 6.4


Extracts the contents of a string surrounded by quotes or brackets.

Definition

void plRTExtractContents(plstring_t* string);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "variable = \"Hello, World!\""; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plptr_t tokens = plRTParser(safeString, memoryTracker); plstring_t* rawTokens = tokens.pointer; plRTExtractContent(&rawTokens[2]); printf("'%s','%s','%s'\n", rawTokens[0].data.pointer, rawTokens[1].data.pointer, rawTokens[2].data.pointer); // Outputs "'variable','=','Hello, World!'" plRTFreeParsedString(tokens);

Section 7: PortaLinux Markup Language Parser API


This API implements the official parser for the PortaLinux Markup Language. It is recommended to become familiar with the plmltoken_t structure, the plmlval_t union, and the plmltype_t enumerator.

plMLParse

Section 7.1


Parses a line of PortaLinux Markup Language, and returns a parsed token. An instance of the memory tracker is required.

Definition

plmltoken_t plMLParse(plstring_t string, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "variable = \"Hello, World!\""; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plmltoken_t token = plMLParse(safeString, memoryTracker); printf("Name: '%s', Value: '%s'\n", token.name.data.pointer, token.value.string.pointer); // Outputs "Name: 'variable',Value: 'Hello, World!'"

plMLFreeToken

Section 7.2


Frees up a parsed token.

Definition

void plMLFreeParsedToken(plmltoken_t string);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); char string[64] = "variable = \"Hello, World!\""; plstring_t safeString = { .data = { .pointer = string, .size = strlen(string) }, .mt = NULL, .isplChar = false }; plmltoken_t token = plMLParse(safeString, memoryTracker); printf("Name: '%s', Value: '%s'\n", token.name.data.pointer, token.value.string.pointer); // Outputs "Name: 'variable',Value: 'Hello, World!'" plMLFreeParsedToken(token);

plMLGenerateTokenStr

Section 7.3


Generates a line of PortaLinux Markup Language from a token structure. Returns a string of parsable PLML in a plstring_t

Definition

void plMLFreeParsedToken(plmltoken_t string);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plmltoken_t token = { .name = plRTStrFromCStr("variable", NULL), .type = PLML_TYPE_INT, .value.decimal = 8080, .mt = NULL }; plstring_t unparsedString = plMLGenerateTokenStr(token, memoryTracker); printf("%s\n", token.data.pointer); // Outputs "variable = "Hello, World!""

Section 8: Logging API and Miscellaneous POSIX-Dependent Functions


This is not really an API, and it's more so a collection of Runtime functions that don't fit anywhere else and the only thing they share in common is that they depend on POSIX functions. The Logging API was created during the release candidate period of release 1.00. Due to this API needing POSIX, some more functions were imported from pl-srv, which already was fully POSIX-dependent.

plRTSetSignal

Section 8.1


Sets the signal handler for the given signal. The function it sets the handler to is called signalHandler and it must be defined whenever this function is active.

NOTICE: In order to use this function, you must define signalHandler (See Example Usage below)

Definition

void plRTSetSignal(int signal);

Example Usage

#include <plrt.h> plmt_t* memoryTracker; void signalHandler(int signal){ printf("Signal detected! Terminating...\n"); plMTStop(memoryTracker); exit(0); } int main(int argc, char argv[]){ memoryTracker = plMTInit(1024 * 1024); plRTSetSignal(SIGTERM); // See Linux manpage signal.h(0P) for signal constants while(true){ /* Some lengthy work going on in here, long enough for the possibility of an interrupt being sent no longer being 0% */ } }

plRTSpawn

Section 8.2


Spawns a process, basically the equivalent of running fork() and then execv(). The args argument must contain a plstring_t array.

Definition

int plRTSetSignal(plptr_t args);

Example Usage

plstring_t* execArgs[3] = { plRTStrFromCStr("/bin/sh", NULL), plRTStrFromCStr("echo", NULL), plRTStrFromCStr("Hello, World!", NULL) }; plptr_t ptrToArgs = { .pointer = execArgs, .size = 3 }; pid_t processID = plRTSpawn(ptrToArgs);

plRTGetDirents

Section 8.3


Gets file entries of a directory. Returns an array of directory entries (struct dirent. See readdir(3)).

Definition

plptr_t plRTGetDirents(char* path, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plptr_t direntList = plRTGetDirents("/path/to/dir", memoryTracker);

plRTSortDirents

Section 8.4


Sorts a list of directory entries.

Definition

void plRTGetDirents(plptr direntArray);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plptr_t direntList = plRTGetDirents("/path/to/dir", memoryTracker); plRTSortDirents(direntList);

plRTLogStart

Section 8.5


Initializes the PortaLinux Runtime Logger. Returns a file handle to the log file. Log files are stored in /var/log or ~/.cache depending on the process' user ID.

Definition

plfile_t* plRTLogStart(char* prefix, plmt_t* mt);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* logFile = plRTLogStart("example", memoryTracker);

plRTLog

Section 8.6


Writes a log message to the log file given. The urgency of the message is determined by the loglevel (See plloglevel_t).

Definition

void plRTLog(plfile_t* logfile,plloglevel_t loglevel , plstring_t string);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* logFile = plRTLogStart("example", memoryTracker); plRTLog(logFile, LOG_INFO, plRTStrFromCStr("Hello, World!", NULL));

plRTLogStop

Section 8.7


Writes a final log message to the log file given before closing it.

Definition

void plRTLogStop(plfile_t* logfile);

Example Usage

plmt_t* memoryTracker = plMTInit(1024 * 1024); plfile_t* logFile = plRTLogStart("example", memoryTracker); plRTLog(logFile, LOG_INFO, plRTStrFromCStr("Hello, World!", NULL)); plRTLogStop(logFile);