|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dirent.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
#include <json-c/json.h>
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#define MAX_FILES 20000
|
|
#define MAX_PATH 4096
|
|
|
|
static const char *extensions[] = {".c", ".cpp", ".h", ".py", ".java", ".js", ".mk", ".html", "Makefile", ".css", ".json", ".cs", ".csproj", ".sln", ".toml",".rs"};
|
|
static size_t ext_count = sizeof(extensions) / sizeof(extensions[0]); // Updated count to reflect the new number of extensions
|
|
|
|
|
|
|
|
typedef struct {
|
|
char name[MAX_PATH];
|
|
char modification_date[20];
|
|
char creation_date[20];
|
|
char type[10];
|
|
size_t size_bytes;
|
|
} FileInfo;
|
|
|
|
FileInfo file_list[MAX_FILES];
|
|
size_t file_count = 0;
|
|
|
|
int is_valid_extension(const char *filename, const char *extensions[], size_t ext_count) {
|
|
const char *dot = strrchr(filename, '.');
|
|
if(!dot){
|
|
dot = filename;
|
|
}
|
|
for (size_t i = 0; i < ext_count; i++) {
|
|
if (strcmp(dot, extensions[i]) == 0) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int is_ignored_directory(const char *dir_name) {
|
|
const char *ignored_dirs[] = {"env", ".venv", "node_modules", "venv", "virtualenv"};
|
|
for (size_t i = 0; i < sizeof(ignored_dirs) / sizeof(ignored_dirs[0]); i++) {
|
|
if (strcmp(dir_name, ignored_dirs[i]) == 0) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void get_file_info(const char *path) {
|
|
struct stat file_stat;
|
|
if (stat(path, &file_stat) == 0) {
|
|
FileInfo info;
|
|
strncpy(info.name, path, MAX_PATH - 1); // Copy with one less to leave space for null terminator
|
|
info.name[MAX_PATH - 1] = '\0'; // Ensure null termination
|
|
strftime(info.modification_date, sizeof(info.modification_date), "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_mtime));
|
|
strftime(info.creation_date, sizeof(info.creation_date), "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_ctime));
|
|
strncpy(info.type, S_ISDIR(file_stat.st_mode) ? "directory" : "file", 10);
|
|
info.type[9] = '\0'; // Ensure null termination
|
|
info.size_bytes = file_stat.st_size;
|
|
file_list[file_count++] = info;
|
|
}
|
|
}
|
|
|
|
char* index_directory(const char *dir_path) {
|
|
DIR *dir = opendir(dir_path);
|
|
struct dirent *entry;
|
|
if (dir == NULL) {
|
|
perror("Failed to open directory");
|
|
return NULL;
|
|
}
|
|
|
|
json_object *jarray = json_object_new_array();
|
|
|
|
while ((entry = readdir(dir)) != NULL) {
|
|
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
|
|
if (entry->d_name[0] == '.' || is_ignored_directory(entry->d_name)) {
|
|
continue;
|
|
}
|
|
char full_path[MAX_PATH];
|
|
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
|
|
if (entry->d_type == DT_DIR) {
|
|
char *subdir_json = index_directory(full_path);
|
|
if (subdir_json) {
|
|
json_object *jsubdir = json_object_new_string(subdir_json);
|
|
json_object_array_add(jarray, jsubdir);
|
|
free(subdir_json);
|
|
}
|
|
} else if (is_valid_extension(entry->d_name, extensions, ext_count)) {
|
|
get_file_info(full_path);
|
|
json_object *jfile = json_object_new_object();
|
|
json_object_object_add(jfile, "file_name", json_object_new_string(file_list[file_count - 1].name));
|
|
json_object_object_add(jfile, "modification_date", json_object_new_string(file_list[file_count - 1].modification_date));
|
|
json_object_object_add(jfile, "creation_date", json_object_new_string(file_list[file_count - 1].creation_date));
|
|
json_object_object_add(jfile, "type", json_object_new_string(file_list[file_count - 1].type));
|
|
json_object_object_add(jfile, "size_bytes", json_object_new_int64(file_list[file_count - 1].size_bytes));
|
|
|
|
// Read the file contents
|
|
FILE *fp = fopen(file_list[file_count - 1].name, "r");
|
|
if (fp != NULL) {
|
|
fseek(fp, 0, SEEK_END);
|
|
long length = ftell(fp);
|
|
fseek(fp, 0, SEEK_SET);
|
|
char *content = malloc(length + 1);
|
|
if (content) {
|
|
size_t bytesRead = fread(content, 1, length, fp);
|
|
if (bytesRead != length) {
|
|
free(content);
|
|
content = NULL;
|
|
json_object_object_add(jfile, "file_current_content_data", json_object_new_string("Error reading file"));
|
|
} else {
|
|
content[length] = '\0'; // Null-terminate the string
|
|
json_object_object_add(jfile, "file_current_content_data", json_object_new_string(content));
|
|
}
|
|
free(content);
|
|
}
|
|
fclose(fp);
|
|
} else {
|
|
json_object_object_add(jfile, "content", json_object_new_string("Unable to read file"));
|
|
}
|
|
|
|
json_object_array_add(jarray, jfile);
|
|
}
|
|
}
|
|
}
|
|
closedir(dir);
|
|
|
|
char *result = strdup(json_object_to_json_string(jarray));
|
|
json_object_put(jarray);
|
|
return result;
|
|
}
|