WebDisk_C/main.c

433 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#include <ctype.h>
#include <pthread.h>
#include "cJSON/cJSON.h"
#define bool unsigned char
#define DEBUG 0
#if defined(DEBUG) && DEBUG > 1
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, \
__FILE__, __LINE__, __func__, ##args)
#elif DEBUG == 1
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, "DEBUG: %d:%s(): " fmt, \
__LINE__, __func__, ##args)
#else
#define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
#endif
struct tred_pizdec{
char* name;
long int* size;
};
struct dir_list_struct{
struct metadata* top;
struct metadata* file;
struct dir_list_struct* next;
};
typedef struct metadata {
char* name;
bool tipe_dir;
long int size;
struct dir_list_struct* dir_list;
struct metadata* top;
struct dir_list_struct* jamp;
} stack_element;
// Функция для получения размера файла
long get_file_size(char* size) {
struct stat st;
DEBUG_PRINT("get_file_size START!\n");
DEBUG_PRINT("name: %s!\n", size);
if (stat(size, &st) == 0) {
return st.st_size;
}
return 0;
}
void* get_file_size_multi_tred(void *arg) {
struct tred_pizdec* mata = (struct tred_pizdec*) arg;
struct stat st;
DEBUG_PRINT("get_file_size START!\n");
DEBUG_PRINT("mata->name: %s!\n", mata->name);
if (stat(mata->name, &st) == 0) {
//return st.st_size;
*mata->size = st.st_size;
}
//DEBUG_PRINT("mata->size: %li!\n", *mata->size);
free(mata);
DEBUG_PRINT("СВОБОДА!!!\n");
return NULL;
}
void format_size(unsigned long long bytes, char *output, size_t output_size) {
const double KB = 1024.0;
const double MB = 1024.0 * KB;
const double GB = 1024.0 * MB;
const double TB = 1024.0 * GB;
if (bytes >= TB) {
snprintf(output, output_size, "%.2f TiB", bytes / TB);
} else if (bytes >= GB) {
snprintf(output, output_size, "%.2f GiB", bytes / GB);
} else if (bytes >= MB) {
snprintf(output, output_size, "%.2f MiB", bytes / MB);
} else if (bytes >= KB) {
snprintf(output, output_size, "%.2f KiB", bytes / KB);
} else {
snprintf(output, output_size, "%llu B", bytes);
}
}
struct metadata* metadata_create(bool tipe_dir,char* path, struct metadata* top){
DEBUG_PRINT("Пред mata malloc\n");
struct metadata* mata = malloc(sizeof(struct metadata));
DEBUG_PRINT("После mata malloc\n");
mata->name = path;
mata->tipe_dir = tipe_dir;
mata->top = top;
if (tipe_dir){
mata->size = 0;
}
else{
mata->name = path;
mata->size = mata->size;
//struct metadata* mata_2 = mata;
/*
struct tred_pizdec* mata_2 = malloc(sizeof(struct tred_pizdec));
mata_2->name = path;
mata_2->size = &mata->size;
pthread_t thread;
pthread_create(&thread, NULL, get_file_size_multi_tred, (void*)mata_2);
//pthread_join(thread, NULL);
*/
mata->size = get_file_size(path);
DEBUG_PRINT("Объём:%li - %s\n", mata->size, mata->name);
}
return mata;
}
void scanning(struct metadata *mata){
struct dirent *entry = NULL;
DIR *dp;
bool AAA = 1;
dp = opendir(mata->name);
//printf("TEST: %s\n", mata->name);
DEBUG_PRINT("TEST: %s\n", mata->name);
struct dir_list_struct* put_2;
DEBUG_PRINT("XXXXXXXXXXXXX_1!\n");
DEBUG_PRINT("One\n");
DEBUG_PRINT("%i\n", errno);
if (errno == 2){
printf("Нет такого файла или каталога!\n");
//printf("%s\n", strerror(errno));
}
if (errno == 22){
printf("Недопустимый аргумент!\n");
//printf("%s\n", strerror(errno));
}
if (errno == 13){
printf("Отказ в доступе!\n");
//printf("%s\n", strerror(errno));
}
else{
entry = readdir(dp);
}
DEBUG_PRINT("Two\n");
while(entry != NULL){
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0){
entry = readdir(dp);
continue;
}
DEBUG_PRINT("mata->name: %s\n", mata->name);
DEBUG_PRINT("entry->d_name: %s\n", entry->d_name);
DEBUG_PRINT("Сум обём: %li\n", (strlen(mata->name) * sizeof(char) + strlen(entry->d_name) * sizeof(char) + sizeof(char)));
DEBUG_PRINT("mata->name обём: %li\n",(strlen(mata->name) * sizeof(char)));
DEBUG_PRINT("entry->d_name обём: %li\n",(strlen(entry->d_name) * sizeof(char)));
char* putaa = malloc((strlen(mata->name) + 1) * sizeof(char) + (strlen(entry->d_name) + 1) * sizeof(char) + sizeof(char) *2);
//char* putaa = malloc(sizeof(mata->name) + sizeof(entry->d_name) + sizeof(char));
DEBUG_PRINT("putaa готов! \n");
sprintf(putaa, "%s%s%s",mata->name,"/",entry->d_name);
DEBUG_PRINT("putaa обединён! \n");
struct metadata* SAS;
if (entry->d_type == DT_DIR){
SAS = metadata_create(1, putaa, mata);
}
else{
SAS = metadata_create(0, putaa, mata);
}
DEBUG_PRINT("SAS готов! \n");
if (AAA){
put_2 = malloc(sizeof(struct dir_list_struct));
DEBUG_PRINT("put_2 1 готов! \n");
mata->dir_list = put_2;
AAA = 0;
}
else{
put_2->next = malloc(sizeof(struct dir_list_struct));
DEBUG_PRINT("put_2 2 готов! \n");
put_2 = put_2->next;
}
put_2->top = mata;
put_2->file = SAS;
entry = readdir(dp);
}
closedir(dp);
DEBUG_PRINT("XXXXXXXXXXXXXs_3!\n");
}
void sum_dir(struct metadata* meta_data){
DEBUG_PRINT("Пред вычисляю объём!\n");
meta_data->size = 0;
if (meta_data->dir_list == NULL) return;
DEBUG_PRINT("Вычисляю объём!\n");
struct dir_list_struct* list = meta_data->dir_list;
while (list != NULL){
meta_data->size += list->file->size;
list = list->next;
}
DEBUG_PRINT("Объём готов!\n");
}
// Функция для сохранения кеша на диск
void save_cache(struct metadata** cache, int cache_size) {
FILE* file = fopen("cache.dat", "wb");
if (file != NULL) {
for (int i = 0; i < cache_size; i++) {
fwrite(cache[i], sizeof(struct metadata), 1, file);
}
fclose(file);
}
}
// Функция для загрузки кеша с диска
void load_cache(struct metadata** cache, int* cache_size) {
FILE* file = fopen("cache.dat", "rb");
if (file != NULL) {
struct metadata info;
while (fread(&info, sizeof(struct metadata), 1, file) == 1) {
(*cache_size)++;
cache[*cache_size] = malloc(sizeof(struct metadata));
memcpy(cache[*cache_size], &info, sizeof(struct metadata));
}
fclose(file);
}
}
void json_create(cJSON *main_Array, char* name, long int volume, cJSON *content_Array){
cJSON *main_ob = cJSON_CreateObject();
cJSON_AddItemToArray(main_Array, main_ob);
cJSON *name_js = cJSON_CreateString(name);
cJSON_AddItemToObject(main_ob, "name", name_js);
cJSON *volume_js = cJSON_CreateNumber(volume);
cJSON_AddItemToObject(main_ob, "volume", volume_js);
cJSON_AddItemToObject(main_ob, "content", content_Array);
}
void scan_dir(struct metadata *mata){
struct metadata *meta_data, *meta_data_tmp;
meta_data = mata;
if (meta_data->dir_list == NULL)
meta_data->jamp = meta_data->dir_list;
struct dir_list_struct* global_dir_list = meta_data->dir_list;
while(1){
//printf("%s%s",global_dir_list->file->name ,"\n");
DEBUG_PRINT("Цикол!\n");
//else if (meta_data->jamp->next != NULL)
// global_dir_list = meta_data->jamp->next;
while(global_dir_list != NULL){
DEBUG_PRINT("%s" ,"while global_dir_list\n");
if (global_dir_list->file->tipe_dir){
DEBUG_PRINT("Выполняю прыжок вниз!\n");
scanning(global_dir_list->file);
DEBUG_PRINT("%s%s",global_dir_list->file->name ," AAA \n");
meta_data_tmp = global_dir_list->file;
DEBUG_PRINT("%s --- dd\n", global_dir_list->file->name);
meta_data_tmp->jamp = global_dir_list;
meta_data = meta_data_tmp;
global_dir_list = meta_data->dir_list;
break;
}
else{
DEBUG_PRINT("Нaйден файл: %s\n",global_dir_list->file->name);
global_dir_list = global_dir_list->next;
DEBUG_PRINT("Прыгаю вперёд!\n");
}
//if (){}
}
if (global_dir_list == NULL){
DEBUG_PRINT("Глобальный список закончен, прыгаю верх за контрольную точку!\n");
//if (meta_data->jamp->next == NULL) printf("XXXXXXXX!\n");
if (meta_data->jamp != NULL && meta_data->jamp->next != NULL ){
if(meta_data->tipe_dir) sum_dir(meta_data);
global_dir_list = meta_data->jamp->next;
meta_data = meta_data->jamp->next->file;
}
else{
DEBUG_PRINT("Контлоьные точки закончелись, поднимаюсь!\n");
if(meta_data->tipe_dir)sum_dir(meta_data);
if (meta_data->top == NULL){
DEBUG_PRINT("Подём отменён!\n");
break;
}
DEBUG_PRINT("Подём!\n");
meta_data = meta_data->top;
}
}
}
DEBUG_PRINT("Готово!\n");
}
typedef struct {
bool has_j;
bool has_r;
int r_value;
char path[1024];
} Options;
bool parse_args(int argc, char *argv[], Options *opts) {
opts->has_j = 0;
opts->has_r = 0;
opts->r_value = 0;
opts->path[0] = '\0';
for (int i = 1; i < argc; i++) {
char *arg = argv[i];
if (arg[0] == '-') {
// Обрабатываем каждый символ после '-'
for (int j = 1; arg[j] != '\0'; j++) {
if (arg[j] == 'j') {
opts->has_j = 1;
} else if (arg[j] == 'r') {
opts->has_r = 1;
// Проверка: есть ли сразу число после 'r'
if (isdigit((unsigned char)arg[j + 1])) {
opts->r_value = atoi(&arg[j + 1]);
break; // всё остальное — часть числа, не флаг
} else if (i + 1 < argc) {
// Иначе, число должно быть в следующем аргументе
opts->r_value = atoi(argv[++i]);
break;
} else {
fprintf(stderr, "Ошибка: -r требует числовой аргумент\n");
return 0;
}
} else {
fprintf(stderr, "Неизвестный флаг: -%c\n", arg[j]);
return 0;
}
}
} else {
// Первый аргумент без '-' — путь
if (opts->path[0] == '\0') {
strncpy(opts->path, arg, sizeof(opts->path) - 1);
opts->path[sizeof(opts->path) - 1] = '\0';
} else {
fprintf(stderr, "Ошибка: путь уже указан\n");
return 0;
}
}
}
if (opts->path[0] == '\0') {
fprintf(stderr, "Ошибка: путь не указан\n");
return 0;
}
return 1;
}
bool js_logok, int_depth=0;
cJSON *print_statistik(cJSON *main_Array, struct dir_list_struct* list, char* output, int i){
//cJSON *main_Array = cJSON_CreateArray();
cJSON *content_Array;
do{
format_size(list->file->size, output, sizeof(output));
DEBUG_PRINT("%s\t%li\t%s\n", output, list->file->size, list->file->name);
if (js_logok){
if (list->file->tipe_dir && (list->file->dir_list != NULL) && (int_depth != i)){
DEBUG_PRINT("Рекурсируем!\n");
DEBUG_PRINT("Каталог вниз: %s!\n", list->file->name);
DEBUG_PRINT("Глубина: %i!\n", i);
cJSON *main_Array_2 = cJSON_CreateArray();
content_Array = print_statistik(main_Array_2, list->file->dir_list, output, i + 1);
DEBUG_PRINT("AA: %s\n", cJSON_Print(content_Array));
DEBUG_PRINT("Верх!\n");
}
else{
DEBUG_PRINT("Конец рекурсии!\n");
content_Array = cJSON_CreateArray();
}
DEBUG_PRINT("json_create main_Array!\n");
DEBUG_PRINT("Имя: %s!\n", list->file->name);
DEBUG_PRINT("До: %s\n", cJSON_Print(main_Array));
json_create(main_Array, list->file->name, list->file->size, content_Array);
DEBUG_PRINT("После: %s\n", cJSON_Print(main_Array));
}
DEBUG_PRINT("прыгаем_1!\n");
list = list->next;
DEBUG_PRINT("прыгаем_2!\n");
}while(list != NULL);
return main_Array;
}
int main(int argc, char *argv[]){
char *path;
setlocale(LC_ALL, "");
//printf("Your locale is: %s\n", setlocale(LC_CTYPE, NULL));
Options opts;
if (!parse_args(argc, argv, &opts)) {
return 1;
}
printf("Путь: %s\n", opts.path);
printf("Флаг -j: %s\n", opts.has_j ? "да" : "нет");
if (opts.has_r) {
printf("Флаг -r: да, значение: %d\n", opts.r_value);
} else {
printf("Флаг -r: нет\n");
}
js_logok = opts.has_j;
int_depth= opts.r_value;
path = opts.path;
struct metadata * mata = malloc(sizeof(stack_element));
mata->name = path;
mata->tipe_dir = 1;
scanning(mata);
scan_dir(mata);
char output[64];
struct dir_list_struct* list = mata->dir_list;
cJSON *main_Array = cJSON_CreateArray();
main_Array = print_statistik(main_Array, list, output, 0);
//while(list->next != NULL);
//save_cache(mata, int cache_size)
DEBUG_PRINT("ПППП!\n");
char *string = cJSON_Print(main_Array);
DEBUG_PRINT("ччччч!\n");
printf("AA: %s\n", string);
printf("%s","bye.\n");
return 0;
}