#include #include #include #include #include #include #include #include #include #include "cJSON/cJSON.h" #define bool unsigned char #ifdef USE_JEMALLOC const char *je_malloc_conf = "narenas:2,lg_chunk:20,stats_print:false"; #include #else #define je_malloc(size) malloc(size) #define je_calloc(nmemb, size) calloc((nmemb), (size)) #define je_realloc(ptr, size) realloc((ptr), (size)) #define je_free(ptr) free((ptr)) #endif unsigned narenas = 4; #define DEBUG 0 #define jemalloc 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 opts_struct{ int recursion; int json; }; struct opts_struct opts; 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; #include "file.h" #include "args_parser.h" void dir_list_struct_init(struct dir_list_struct* dir_list_struct){ dir_list_struct->top = NULL; dir_list_struct->file = NULL; dir_list_struct->next = NULL; } void meta_data_init(struct metadata* metadata){ metadata->name = NULL; metadata->dir_list = NULL; metadata->top = NULL; metadata->jamp = NULL; } // Функция для получения размера файла 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 = je_malloc(sizeof(struct metadata)); meta_data_init(mata); 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 = je_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); DEBUG_PRINT("%i\n", errno); /* if (errno == 2){ printf("Нет такого файла или каталога!\n"); //printf("%s\n", strerror(errno)); printf("file: %s\n", mata->name); } else if (errno == 22){ printf("Недопустимый аргумент!\n"); //printf("%s\n", strerror(errno)); printf("file: %s\n", mata->name); } */ if (errno == 13){ printf("Отказ в доступе!\n"); //printf("%s\n", strerror(errno)); } else{ entry = readdir(dp); } //printf("TEST: %s\n", mata->name); DEBUG_PRINT("TEST: %s\n", mata->name); struct dir_list_struct* put_2; //printf("%s\n", strerror(errno)); 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 = je_malloc(strlen(mata->name) + (strlen(entry->d_name)) + 2); //snprintf(putaa, path_len, "%s/%s", mata->name, entry->d_name); //char* putaa = malloc(sizeof(mata->name) + sizeof(entry->d_name) + sizeof(char)); DEBUG_PRINT("putaa готов! \n"); sprintf(putaa, "%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 = je_malloc(sizeof(struct dir_list_struct)); dir_list_struct_init(put_2); DEBUG_PRINT("put_2 1 готов!\n"); mata->dir_list = put_2; AAA = 0; } else{ put_2->next = je_malloc(sizeof(struct dir_list_struct)); dir_list_struct_init(put_2->next); 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) { // II LLM 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)); printf("%s\t%li\t%s\n", output, list->file->size, list->file->name); 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[]){ //mallctl("opt.narenas", NULL, NULL, &narenas, sizeof(narenas)); 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 = je_malloc(sizeof(stack_element)); meta_data_init(mata); mata->name = path; mata->tipe_dir = 1; scanning(mata); scan_dir(mata); /* struct metadata * mata = je_malloc(sizeof(stack_element)); nanaaa_2(mata); printf("AAAA0: %s\n", mata->name); printf("AAAA1: %s\n", mata->dir_list->file->name); printf("tipe_dir: %i\n", mata->dir_list->file->tipe_dir); printf("size: %li\n", mata->dir_list->file->size); if (mata->dir_list->next == NULL) printf("SUKA\n"); printf("AAAA2: %s\n", mata->dir_list->next->file->name); //printf("AAAA2: %s\n", mata->dir_list->file->dir_list->file->name); */ 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"); //file_weit(mata); nanaaa(mata); return 0; }