commit 49840162015a0faaa7e82e96f0fcbd272ea13010 Author: Intel A80486DX2-66 Date: Wed Dec 27 17:35:59 2023 +0300 add reverse-ramdisk.c diff --git a/c-programming/reverse-ramdisk.c b/c-programming/reverse-ramdisk.c new file mode 100644 index 0000000..9563393 --- /dev/null +++ b/c-programming/reverse-ramdisk.c @@ -0,0 +1,218 @@ +/* +C programming idea: Handling temporary files like memory allocations (allocating -> creating empty file, using -> locking for R/W, freeing -> deleting). + +50% AI, 50% human (the code is tested and reviewed) + +GCC/Clang/TCC: Compile with -DTEST to set macro TEST as defined +*/ + +#include +#include +#include +#include +#include + +typedef struct { + int ID; + char* file_path; + FILE* file; +} TempFile; + +TempFile* temp_files = NULL; +size_t num_temp_files = 0; + +#define line_fail(x) do { \ + printf("failed on line %d\n", __LINE__ + x); \ +} while (0) + +int tf_alloc(size_t n, size_t type_size) { + // Create an empty file + char file_path[20]; + sprintf(file_path, "tf_%zu.tmp", num_temp_files); + FILE* file = fopen(file_path, "w+b"); + if (file == NULL) { + line_fail(-2); + return -1; + } + + // Allocate memory for the TempFile struct + TempFile* temp_file = (TempFile*)malloc(sizeof(TempFile)); + if (temp_file == NULL) { + line_fail(-2); + return -1; + } + + // Assign the ID and file path + temp_file->ID = num_temp_files; + temp_file->file_path = strdup(file_path); + temp_file->file = file; + + // Increase the number of temp files + num_temp_files++; + + // Reallocate memory for the temp_files array + temp_files = (TempFile*)realloc(temp_files, num_temp_files * sizeof(TempFile)); + if (temp_files == NULL) { + line_fail(-2); + return -1; + } + + // Add the temp file to the array + temp_files[num_temp_files - 1] = *temp_file; + + return temp_file->ID; +} + +int tf_free(int ID) { + // Find the temp file with the given ID + int index = -1; + for (int i = 0; i < num_temp_files; i++) + if (temp_files[i].ID == ID) { + index = i; + break; + } + + if (index == -1) + return -1; + + fclose(temp_files[index].file); + + // Delete the file + if (remove(temp_files[index].file_path) != 0) { + return -1; + } + + free(temp_files[index].file_path); + + // Shift the remaining temp files in the array + for (int i = index; i < num_temp_files - 1; i++) { + temp_files[i] = temp_files[i + 1]; + } + + // Decrease the number of temp files + num_temp_files--; + + // Reallocate memory for the temp_files array + temp_files = (TempFile*)realloc(temp_files, num_temp_files * sizeof(TempFile)); + if (temp_files == NULL && num_temp_files > 0) { + return -1; + } + + return 0; +} + +int tf_write(int ID, size_t offset, void* data, size_t data_size) { + // Find the temp file with the given ID + int index = -1; + for (int i = 0; i < num_temp_files; i++) { + if (temp_files[i].ID == ID) { + index = i; + break; + } + } + + if (index == -1) + return -1; + + // Open the file in append mode + FILE* file = temp_files[index].file; + if (file == NULL) + return -1; + + // Seek + fseek(file, offset, SEEK_SET); + + // Write the data to the file + size_t bytes_written = fwrite(data, 1, data_size, file); + + if (bytes_written != data_size) + return -1; + + return 0; +} + +int tf_read(int ID, size_t offset, void* dest, size_t data_size) { + // Find the temp file with the given ID + int index = -1; + for (int i = 0; i < num_temp_files; i++) { + if (temp_files[i].ID == ID) { + index = i; + break; + } + } + + if (index == -1) { + return -1; + } + + // Open the file in read mode + FILE* file = temp_files[index].file; + if (file == NULL) + return -1; + + // Read the data from the file + void* data = malloc(data_size); + if (data == NULL) { + fclose(file); + return -1; + } + + // Initialize the memory in the data buffer + memset(data, 0, data_size); + + fseek(file, offset, SEEK_SET); + size_t bytes_read = fread(data, 1, data_size, file); + + // Copy the data to the destination pointer + memcpy(dest, data, data_size); + + free(data); // Free the allocated memory + + if (bytes_read != data_size) { + errno = EIO; + return -1; + } + + printf("Read: ID = %d, data = %016" PRIXPTR ", size = %zu -> '", + ID, (uintptr_t)dest, data_size); + for (size_t i = 0; i < data_size; i++) + printf("0x%02" PRIX8 " ", *((uint8_t*)(dest + i))); + printf("'\n"); + return 0; +} + +#define retreat(s) do { \ + perror(s); \ + exit(EXIT_FAILURE); \ +} while (0) + +#ifdef TEST +int main() { + int ID = tf_alloc(4, sizeof(int)); + if (ID == -1) + retreat("tf_alloc"); + + int test_data[4] = {123, 456, 789, -123}; + + for (size_t i = 0; i < 4; i++) + if (tf_write(ID, i * sizeof(int), &test_data[i], sizeof(int)) == -1) + retreat("tf_write"); + + // round-trip + test_data[0] = 111; + test_data[1] = 222; + test_data[2] = 333; + test_data[3] = 444; + + for (size_t i = 0; i < 4; i++) + if (tf_read(ID, i * sizeof(int), &test_data[i], sizeof(int)) == -1) + retreat("tf_read"); + + printf("Values: %d %d %d %d\n", + test_data[0], test_data[1], test_data[2], test_data[3]); + + tf_free(ID); + + return 0; +} +#endif