A
A
Alertoso2022-03-11 16:17:25
linux
Alertoso, 2022-03-11 16:17:25

Why do I get broken files when copying files?

The task itself sounds like this:
Sort files in the given directory (command line argument 1) and all its subdirectories according to the following criteria (command line argument 2, specified as an integer): 1 - by file size, 2 - by file name. Write the sorted files in a common list without saving the directory structure to a new directory (argument 3 of the command line). Due to the indexing of files in directories for ext 2,3,4 filesystems, it is necessary to temporarily disable the filesystem indexing option before running the program as follows:
sudo tune2fs –O ^dir_index /dev/sdaXY
Check the result using ls -l –f.
The program works, but the files are copied broken (screenshot attached below), I checked the indexing, it's not about it, what could be the problem?

#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;
}

622b4bc8758dd254404869.jpeg

Answer the question

In order to leave comments, you need to log in

1 answer(s)
W
Wataru, 2022-03-11
@Alertoso

Carefully output somewhere the parameters you pass to the symlink creation function.
It looks like the problem is that you are passing relative rather than absolute paths as the target for the link.
When using the copy function, this may not be a problem.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question