IO functions
This commit is contained in:
parent
362b1b33d5
commit
d7792998ea
22
include/io.h
Normal file
22
include/io.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef IO_H
|
||||||
|
#define IO_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define STREQ(S1, S2) (strcmp(S1, S2) == 0)
|
||||||
|
|
||||||
|
typedef struct dirwalk dirwalk_t;
|
||||||
|
typedef struct {
|
||||||
|
FILE *fp;
|
||||||
|
bool reading;
|
||||||
|
char name[NAME_MAX + 1];
|
||||||
|
} dirwalk_result_t;
|
||||||
|
|
||||||
|
u64 get_file_length(FILE *fp);
|
||||||
|
void read_entire_file(void *dst, u64 length, FILE *fp);
|
||||||
|
dirwalk_result_t walk_dir(dirwalk_t **dirwalk, const char *filepath);
|
||||||
|
|
||||||
|
#endif // !IO_H
|
179
src/io.c
Normal file
179
src/io.c
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
#include "io.h"
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "path_utils.h"
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define MAX_DIR_DEPTH PATH_MAX
|
||||||
|
|
||||||
|
typedef struct stat stat_t;
|
||||||
|
typedef struct dirent dirent_t;
|
||||||
|
struct dirwalk {
|
||||||
|
u64 count;
|
||||||
|
FILE *current_file;
|
||||||
|
DIR *current_dir;
|
||||||
|
char dst[PATH_MAX];
|
||||||
|
DIR *directories[MAX_DIR_DEPTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
u64 get_file_length(FILE *fp) {
|
||||||
|
u64 current = ftell(fp);
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
|
||||||
|
u64 length = ftell(fp);
|
||||||
|
|
||||||
|
// Restore the cursor position to where it was
|
||||||
|
fseek(fp, current, SEEK_SET);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_entire_file(void *dst, u64 length, FILE *fp) {
|
||||||
|
u64 current = ftell(fp);
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
|
||||||
|
fread(dst, length, 1, fp);
|
||||||
|
|
||||||
|
fseek(fp, current, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
dirwalk_result_t walk_dir(dirwalk_t **dirwalk, const char *filepath) {
|
||||||
|
if (!(*dirwalk)) {
|
||||||
|
*dirwalk = (dirwalk_t *)malloc(sizeof(dirwalk_t));
|
||||||
|
if (!(*dirwalk)) {
|
||||||
|
return (dirwalk_result_t){0};
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((void *)(*dirwalk), 0, sizeof(dirwalk_t));
|
||||||
|
|
||||||
|
JOIN_PATH((*dirwalk)->dst, filepath);
|
||||||
|
|
||||||
|
(*dirwalk)->directories[0] = opendir((*dirwalk)->dst);
|
||||||
|
if (!((*dirwalk)->directories[0])) {
|
||||||
|
goto CLEANUP_WALK_DIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*dirwalk)->current_dir = (*dirwalk)->directories[0];
|
||||||
|
++((*dirwalk)->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*dirwalk)->current_file) {
|
||||||
|
fclose((*dirwalk)->current_file);
|
||||||
|
|
||||||
|
(*dirwalk)->current_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dirwalk_t *dw = *dirwalk;
|
||||||
|
|
||||||
|
char tmp[PATH_MAX] = {0};
|
||||||
|
|
||||||
|
dirent_t *ep = NULL;
|
||||||
|
stat_t dirstat = {0};
|
||||||
|
|
||||||
|
while ((ep = readdir(dw->current_dir))) {
|
||||||
|
if (STREQ(ep->d_name, ".") || STREQ(ep->d_name, "..")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ep->d_type) {
|
||||||
|
case DT_DIR: {
|
||||||
|
JOIN_PATH(dw->dst, ep->d_name);
|
||||||
|
|
||||||
|
dw->directories[(dw->count)++] = opendir(dw->dst);
|
||||||
|
|
||||||
|
dw->current_dir = dw->directories[dw->count - 1];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DT_REG: {
|
||||||
|
JOIN_PATH(tmp, dw->dst, ep->d_name);
|
||||||
|
|
||||||
|
dw->current_file = fopen(tmp, "rb");
|
||||||
|
|
||||||
|
dirwalk_result_t result = {0};
|
||||||
|
|
||||||
|
result.reading = true;
|
||||||
|
result.fp = dw->current_file;
|
||||||
|
strncpy(result.name, ep->d_name, NAME_MAX);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case DT_LNK: {
|
||||||
|
JOIN_PATH(tmp, dw->dst, ep->d_name);
|
||||||
|
|
||||||
|
u64 length = strlen(tmp);
|
||||||
|
|
||||||
|
stat(tmp, &dirstat);
|
||||||
|
|
||||||
|
if ((dirstat.st_mode & S_IFDIR) == S_IFDIR) {
|
||||||
|
memset(dw->dst, 0, length);
|
||||||
|
|
||||||
|
strncpy(dw->dst, tmp, length);
|
||||||
|
|
||||||
|
dw->directories[(dw->count)++] = opendir(dw->dst);
|
||||||
|
|
||||||
|
dw->current_dir = dw->directories[dw->count - 1];
|
||||||
|
} else if ((dirstat.st_mode & S_IFREG) == S_IFREG) {
|
||||||
|
dw->current_file = fopen(tmp, "rb");
|
||||||
|
|
||||||
|
dirwalk_result_t result = {0};
|
||||||
|
|
||||||
|
result.reading = true;
|
||||||
|
result.fp = dw->current_file;
|
||||||
|
strncpy(result.name, ep->d_name, NAME_MAX);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(tmp, 0, length);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dw->count > 1) {
|
||||||
|
closedir(dw->directories[--(dw->count)]);
|
||||||
|
dw->directories[dw->count] = NULL;
|
||||||
|
|
||||||
|
dw->current_dir = dw->directories[dw->count - 1];
|
||||||
|
|
||||||
|
u64 length = strlen(dw->dst);
|
||||||
|
|
||||||
|
strncpy(tmp, dw->dst, length);
|
||||||
|
|
||||||
|
memset(dw->dst, 0, length);
|
||||||
|
|
||||||
|
DIRNAME(dw->dst, tmp);
|
||||||
|
|
||||||
|
memset(tmp, 0, length);
|
||||||
|
|
||||||
|
dirwalk_result_t result = {0};
|
||||||
|
|
||||||
|
result.reading = true;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
dw->current_dir = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dw->directories[dw->count]);
|
||||||
|
|
||||||
|
CLEANUP_WALK_DIR:
|
||||||
|
free(*dirwalk);
|
||||||
|
*dirwalk = NULL;
|
||||||
|
|
||||||
|
dirwalk_result_t result = {0};
|
||||||
|
|
||||||
|
result.reading = false;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user