Загрузка данных


// myls.c — упрощенный аналог ls -l
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>      // Для getpwuid()
#include <grp.h>      // Для getgrgid()
#include <time.h>     // Для strftime()
#include <errno.h>
#include <dirent.h>   // Для opendir(), readdir()

#define MAX_PATH 4096

// Макрос для обработки ошибок
#define err_sys(msg) do { \
    fprintf(stderr, "%s: %s\n", msg, strerror(errno)); \
    exit(1); \
} while(0)

// Функция для преобразования режима файла в строку прав (например, -rw-r--r--)
void mode_to_string(mode_t mode, char *str) {
    // Тип файла
    switch (mode & S_IFMT) {
        case S_IFDIR:  str[0] = 'd'; break;  // Директория
        case S_IFCHR:  str[0] = 'c'; break;  // Символьное устройство
        case S_IFBLK:  str[0] = 'b'; break;  // Блочное устройство
        case S_IFREG:  str[0] = '-'; break;  // Обычный файл
        case S_IFIFO:  str[0] = 'p'; break;  // FIFO (именованный канал)
        case S_IFLNK:  str[0] = 'l'; break;  // Символическая ссылка
        case S_IFSOCK: str[0] = 's'; break;  // Сокет
        default:       str[0] = '?'; break;
    }
    
    // Права владельца (user)
    str[1] = (mode & S_IRUSR) ? 'r' : '-';
    str[2] = (mode & S_IWUSR) ? 'w' : '-';
    str[3] = (mode & S_IXUSR) ? 'x' : '-';
    
    // Права группы (group)
    str[4] = (mode & S_IRGRP) ? 'r' : '-';
    str[5] = (mode & S_IWGRP) ? 'w' : '-';
    str[6] = (mode & S_IXGRP) ? 'x' : '-';
    
    // Права остальных (others)
    str[7] = (mode & S_IROTH) ? 'r' : '-';
    str[8] = (mode & S_IWOTH) ? 'w' : '-';
    str[9] = (mode & S_IXOTH) ? 'x' : '-';
    
    str[10] = '\0';
}

// Функция для форматирования времени
void format_time(time_t t, char *buf, size_t size) {
    struct tm *tm_info = localtime(&t);
    strftime(buf, size, "%b %d %H:%M", tm_info);
}

// Функция для отображения информации об одном файле
void print_file_info(const char *pathname) {
    struct stat statbuf;
    char mode_str[11];
    char time_str[64];
    struct passwd *pwd;
    struct group *grp;
    
    // Используем lstat для корректной работы с символическими ссылками
    if (lstat(pathname, &statbuf) == -1) {
        fprintf(stderr, "Не удалось получить информацию о %s: %s\n", 
                pathname, strerror(errno));
        return;
    }
    
    // Преобразуем режим в строку прав
    mode_to_string(statbuf.st_mode, mode_str);
    
    // Форматируем время последней модификации
    format_time(statbuf.st_mtime, time_str, sizeof(time_str));
    
    // Получаем имя владельца по UID
    pwd = getpwuid(statbuf.st_uid);
    const char *username = pwd ? pwd->pw_name : "?";
    
    // Получаем имя группы по GID
    grp = getgrgid(statbuf.st_gid);
    const char *groupname = grp ? grp->gr_name : "?";
    
    // Вывод в формате ls -l
    printf("%s %3ld %s %s %8ld %s %s\n",
           mode_str,                    // Права доступа
           (long)statbuf.st_nlink,      // Количество ссылок
           username,                    // Владелец
           groupname,                   // Группа
           (long)statbuf.st_size,       // Размер в байтах
           time_str,                    // Время модификации
           pathname);                   // Имя файла
}

// Функция для обработки директории
void list_directory(const char *dirname) {
    DIR *dir;
    struct dirent *entry;
    char fullpath[MAX_PATH];
    
    dir = opendir(dirname);
    if (dir == NULL) {
        fprintf(stderr, "Не удалось открыть директорию %s: %s\n",
                dirname, strerror(errno));
        return;
    }
    
    // Читаем все записи в директории
    while ((entry = readdir(dir)) != NULL) {
        // Пропускаем . и ..
        if (strcmp(entry->d_name, ".") == 0 || 
            strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        
        // Формируем полный путь
        snprintf(fullpath, sizeof(fullpath), "%s/%s", dirname, entry->d_name);
        print_file_info(fullpath);
    }
    
    closedir(dir);
}

int main(int argc, char *argv[]) {
    // Если аргументов нет — используем текущую директорию
    if (argc == 1) {
        list_directory(".");
    } else {
        // Обрабатываем каждый аргумент
        for (int i = 1; i < argc; i++) {
            struct stat statbuf;
            
            // Проверяем, является ли путь директорией
            if (lstat(argv[i], &statbuf) == -1) {
                fprintf(stderr, "Не удалось получить информацию о %s: %s\n",
                        argv[i], strerror(errno));
                continue;
            }
            
            if (S_ISDIR(statbuf.st_mode)) {
                // Это директория — перечисляем её содержимое
                printf("%s:\n", argv[i]);
                list_directory(argv[i]);
                printf("\n");
            } else {
                // Это файл — выводим информацию о нём
                print_file_info(argv[i]);
            }
        }
    }
    
    return 0;
}