mirror of
https://gitlab.com/80486DX2-66/gists
synced 2025-01-11 21:02:03 +05:30
add reverse-ramdisk.c
This commit is contained in:
commit
4984016201
218
c-programming/reverse-ramdisk.c
Normal file
218
c-programming/reverse-ramdisk.c
Normal file
@ -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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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
|
Loading…
x
Reference in New Issue
Block a user