WebDisk_C/main.c

457 lines
14 KiB
C
Raw Permalink 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"
#ifdef USE_JEMALLOC
const char *je_malloc_conf = "narenas:2,lg_chunk:20,stats_print:false";
#include <jemalloc/jemalloc.h>
#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))
#include <stdint.h>
#endif
unsigned narenas = 4;
#define bool unsigned char
#define DEBUG 1
#define jemalloc 1
#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;
char* dir;
};
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");
}
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){
DEBUG_PRINT("int_depth: %i\n", int_depth);
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;
}
void reid_dir(struct metadata * mata){
meta_data_init(mata);
mata->name = opts.dir;
mata->tipe_dir = 1;
scanning(mata);
scan_dir(mata);
nanaaa(mata);
}
void read_file(struct metadata * mata){
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");
else{
printf("AAAA2: %s\n", mata->dir_list->next->file->name);
//printf("AAAA2: %s\n", mata->dir_list->file->dir_list->file->name);
}
//printf("AAAA1: %s\n", mata->dir_list->next->file->name);
}
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));
opts.json=0;
args_pars(&argc, argv);
/*
Options opts;
if (!parse_args(argc, argv, &opts)) {
return 1;
}
*/
printf("Путь: %s\n", opts.dir);
printf("Флаг -j: %s\n", opts.json ? "да" : "нет");
if (opts.recursion) {
printf("Флаг -r: да, значение: %d\n", opts.recursion);
} else {
printf("Флаг -r: нет\n");
}
js_logok = opts.json;
int_depth = opts.recursion;
path = opts.dir;
struct metadata * mata = je_malloc(sizeof(stack_element));
if (opts.dir) reid_dir(mata);
else read_file(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");
//file_weit(mata);
//nanaaa(mata);
return 0;
}