Само задание звучит так:
Отсортировать в заданном каталоге (аргумент 1 командной строки) и во всех его подкаталогах файлы по следующим критериям (аргумент 2 командной строки, задаётся в виде целого числа):1 – по размеру файла, 2 – по имени файла. Записать без сохранения структуры каталогов отсортированные файлы общим списком, в новый каталог (аргумент 3 командной строки). В связи с индексированием файлов в каталогах для файловых систем ext 2,3,4 перед запуском программы необходимо временно отключить опцию индексирования файловой системы следующим образом:
sudo tune2fs –O ^dir_index /dev/sdaXY
Проверить результат, используя, ls -l –f.
Программа работает, но файлы получаются скопированные битые(скриншот приложил ниже), проверил индексирование, дело не в нём, в чём может быть проблема?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
/*
* Отсортировать в заданном каталоге (аргумент 1 командной строки) и во всех его подкаталогах файлы по следующим критериям
* (аргумент 2 командной строки, задаётся в виде целого числа): 1 – по размеру файла, 2 – по имени файла.
* Записать без сохранения структуры каталогов отсортированные файлы общим списком, в новый каталог (аргумент 3 командной строки).
* В связи с индексированием файлов в каталогах для файловых систем ext 2,3,4 перед запуском программы необходимо временно отключить
* опцию индексирования файловой системы следующим образом: sudo tune2fs –O ^dir_index /dev/sdaXY
*/
// Структура файла: путь, название, размер
typedef struct {
char path[PATH_MAX];
char name[FILENAME_MAX];
int size;
} file_t;
// Список файлов
file_t *f_list;
int f_list_len = 0;
int (*cmpFunc)(file_t file1, file_t file2);
// Сравнение файлов по размеру
int cmpSize(file_t file1, file_t file2) {
return ((file1.size - file2.size) < 0);
}
// Сравнение файлов по имени
int cmpName(file_t file1, file_t file2) {
return (strcmp(file1.name, file2.name) > 0);
}
// Для перехода к подкаталогу
char* addSlash(char* path) {
if (path[strlen(path) - 1] != '/')
strcat(path, "/");
return path;
}
// Чтение данных из директории и запись данных в список для хранения
int getFiles(char *dir_name) {
DIR *directory;
if ((directory = opendir(dir_name)) == NULL) {
fprintf(stderr, "Error when trying to open the directory: %s\n", dir_name);
return 0;
}
struct dirent *dir_item;
while((dir_item = readdir(directory)) != NULL) {
char next_item[PATH_MAX];
strcpy(next_item, dir_name);
strcat(next_item, dir_item->d_name);
if(strcmp(".", dir_item->d_name) == 0 || strcmp("..", dir_item->d_name) == 0)
continue;
struct stat statbuf;
lstat(next_item, &statbuf);
if(S_ISDIR(statbuf.st_mode)) {
getFiles(addSlash(next_item));
} else if(S_ISREG(statbuf.st_mode)) {
file_t file_tmp;
strcpy(file_tmp.name, dir_item->d_name);
strcpy(file_tmp.path, next_item);
file_tmp.size = (int) statbuf.st_size;
f_list = realloc(f_list, (++f_list_len)*sizeof(file_t));
f_list[f_list_len - 1] = file_tmp;
}
}
if (closedir(directory)) {
fprintf(stderr, "Error when trying to close the directory: %s\n", dir_name);
return 0;
}
}
// Сортировка файлов по размеру или имени
void fListSort(int sortOption) {
if (sortOption == 1)
cmpFunc = cmpSize;
else
cmpFunc = cmpName;
int i, j;
for (i = 0; i < f_list_len; i++) {
for (j = 0; j < f_list_len - i - 1; j++) {
if (cmpFunc(f_list[j], f_list[j+1])) {
file_t file_tmp = f_list[j];
f_list[j] = f_list[j+1];
f_list[j+1] = file_tmp;
}
}
}
}
// Запись файлов в новый каталог
int writeFiles(char *dir_name) {
DIR *directory;
if ((directory = opendir(dir_name)) == NULL) {
fprintf(stderr, "Error when trying to open the directory: %s\n", dir_name);
return 0;
}
int i, j;
for(i = 0; i < f_list_len; i++) {
j = i;
while (j++ < f_list_len && !strcmp(f_list[i].name, f_list[j].name)) {
char add_index[5];
sprintf(add_index," (%d)", j-i);
strcat(f_list[j].name, add_index);
}
char dist_file[PATH_MAX];
strcpy(dist_file, dir_name);
strcat(dist_file, f_list[i].name);
if (symlink(f_list[i].path, dist_file) == -1) {
fprintf(stderr, "%s: File exists\n", dist_file);
}
}
if (closedir(directory)) {
fprintf(stderr, "Error when trying to close the directory: %s\n", dir_name);
return 0;
}
}
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Wrong number of arguments! You should enter 3 parameters:\n");
fprintf(stderr, "First argument - source directory\n");
fprintf(stderr, "Second argument - sort option\n");
fprintf(stderr, "Third argument - destination directory\n");
return 0;
}
char sortOption;
sortOption = atoi(argv[2]);
if (sortOption != 1 && sortOption != 2) {
fprintf(stderr,"Wrong sort option! Must be: 1 or 2\n");
return 0;
}
char dirSrc[PATH_MAX];
strcpy(dirSrc, argv[1]);
getFiles(addSlash(dirSrc));
fListSort(sortOption);
char dirDest[PATH_MAX];
realpath(argv[3], dirDest);
writeFiles(addSlash(dirDest));
return 0;
}