Przykładowe zadania 1, 2, 3, 4
Published on 20.10.2026 at 12:49
Last updated on 20.10.2026 at 12:49
Zadanie 1
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <limits.h>
#define ERR(source) (perror(source),\
fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
exit(EXIT_FAILURE))
void listDir(const char *path) {
DIR* dirp;
struct dirent* entry;
struct stat filestat;
if((dirp = opendir(path)) == NULL) {
ERR("opendir");
}
do {
errno = 0;
if ((entry = readdir(dirp)) != NULL) {
if (lstat(entry->d_name, &filestat)) {
ERR("lstat");
}
printf("%s %lld\n", entry->d_name, filestat.st_size);
}
} while(entry != NULL);
if (errno != 0) {
ERR("readdir");
}
if (closedir(dirp) == -1) {
ERR("closedir");
}
}
int main(int argc, char *argv[]) {
int c;
char *paths[argc];
char path[PATH_MAX];
int path_count = 0;
if (getcwd(path, PATH_MAX) == NULL)
ERR("getcwd");
while ((c = getopt(argc, argv, "p:")) != -1) {
switch (c) {
case 'p':
paths[path_count++] = optarg;
break;
case '?':
default:
fprintf(stderr, "Usage: %s -p <directory>\n", argv[0]);
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < path_count; i++) {
if (chdir(paths[i])) {
fprintf(stderr, "Error changing directory to %s\n", paths[i]);
ERR("chdir");
}
printf("SCIEZKA:\n%s\nLISTA PLIKÓW:\n", paths[i]);
listDir(".");
if (chdir(path)) {
ERR("chdir");
}
}
return EXIT_SUCCESS;
}Zadanie 2
#define _POSIX_C_SOURCE 200809L
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <time.h>
#include <string.h>
#define MAX_PATH PATH_MAX
#define ERR(source) (perror(source), fprintf(stderr, "%s:%d\n", __FILE__, __LINE__), exit(EXIT_FAILURE))
char* FILE_OUTPUT = "NO";
int FILE1 = 0;
int allowed_depth = 1;
int count4=0;
void usage(){
printf("p: MUSISZ PODAC SCIEZKE NORMALNA \n");
}
void listing(char* ch , char* restrict1[500] , int depth , FILE* fl){
//printf("%s\n",ch);
char* c = ch;
DIR* dir = opendir(ch);
FILE *f = fl;
if(dir == NULL){
usage();
return;
//ERR("opendir");
//exit(EXIT_FAILURE);
}
if(FILE1){
fprintf(f,"SCIEZKA:\n");
fprintf(f,"%s\n",c);
fprintf(f,"LISTA PLIKOW: \n");
}
else{
printf("SCIEZKA:\n");
printf("%s\n",c);
printf("LISTA PLIKOW: \n");
}
errno = 0;
struct dirent* dr = readdir(dir);
if(dr == NULL){
if(errno !=0){
perror("readdir");
exit(EXIT_FAILURE);
}
else{
printf("KONIEC ODCZYTU\n");
}
}
while(dr != NULL){
struct stat st;
char fullpath[PATH_MAX];
sprintf(fullpath, "%s/%s", ch, dr->d_name);
if(lstat (fullpath,&st)){
ERR("lstat");
exit(EXIT_FAILURE);
};
if (S_ISDIR(st.st_mode)) {
if (strcmp(dr->d_name, ".") != 0 &&
strcmp(dr->d_name, "..") != 0) {
if (depth < allowed_depth) {
listing(fullpath, restrict1, depth + 1,fl);
}
}
dr = readdir(dir);
continue;
}
const char *dot = strrchr(dr->d_name, '.');
if(count4>0){
if (dot == NULL) {
dr = readdir(dir);
continue;
}
int skip = 1;
for(int i = 0; i < count4; i++){
if(strcmp( dot+1 ,restrict1[i]) == 0){
skip = 0;
}
}
if(skip){
dr = readdir(dir);
continue;
}
}
if(!FILE1)printf("%s ",dr->d_name);
else{
fprintf(f,"%s ",dr->d_name);
}
if(!FILE1)printf("%ld\n",st.st_size);
else{
fprintf(f,"%ld\n",st.st_size);;
}
errno = 0;
dr = readdir(dir);
if(dr == NULL){
if(errno !=0){
perror("readdir");
exit(EXIT_FAILURE);
}
else{
printf("KONIEC ODCZYTU\n");
}
}
}
if(closedir(dir)){
exit(EXIT_FAILURE);
};
}
int main(int argc,char** argv){
//listing(".");
int i;
// DIR* dir = opendir("sopyyy");
// if(dir == NULL){
// printf("SDFSD\n");
// }
int count = 0;
int counto = 0;
int countr = 0;
char *s1[500];
char *restriction[500];
FILE* fl=NULL;
while( (i = getopt(argc,argv,"op:e:d:")) != -1){
if(i == 'p'){
char* s = optarg;
s1[count] = optarg;
count++;
}
else if (i == 'o'){
FILE1 = 1;
counto++;
char *env = getenv("L1_OUTPUTFILE");
if(env == NULL){
perror("stop");
}
if(counto>1){
fprintf(stderr,"ONLY ONE O");
return EXIT_FAILURE;
}
}
else if (i == 'e'){
restriction[countr] = optarg;
countr++;
count4 = countr;
}
else if(i == 'd'){
allowed_depth = strtol(optarg, (char **)NULL, 10);
}
else {
usage();
return EXIT_FAILURE;
}
}
if(FILE1){
char *env = getenv("L1_OUTPUTFILE");
if(env == NULL){
perror("stop");
return EXIT_FAILURE;
}
fl = fopen(env,"w+");
if(fl == NULL){
ERR("fopen");
}
}
for(int i = 0 ; i < count ;i++){
listing(s1[i],restriction,1,fl);
}
if(optind != argc){
printf("UWAGA nie odczytane wszystkie parametry");
}
// if(count == 0){
// listing(".");
// }
if(FILE1 && fclose(fl)){
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}Zadanie 3
#define _POSIX_C_SOURCE 200809L
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <time.h>
#include <string.h>
#define MAX_PATH PATH_MAX
#define ERR(source) (perror(source), fprintf(stderr, "%s:%d\n", __FILE__, __LINE__), exit(EXIT_FAILURE))
void install(char* s1 , char* s2, int size){
DIR* dir = opendir(".");
struct dirent* s;
while((s =readdir(dir))!=NULL){
if(strcmp(s->d_name,s1)==0){
perror("ALREADY EXISTS");
return;
}
}
FILE* f1 = fopen(s1,"a");
srand(time(NULL));
for(int i = 0; i < size;i++){
fprintf(f1, "%c", rand() % 26 + 'A');
}
fclose(f1);
FILE* f2 = fopen("requirements","a");
fprintf(f2,"%s %s\n",s1,s2);
fclose(f2);
closedir(dir);
}
void deleteq(char *s1){
int find = 0;
if(unlink(s1) && errno == ENOENT){
ERR("unlink");
}
char c1[500];
char c[500];
char sd1[500][500];
char ver[500][500];
int count = 0;
FILE* file = fopen("requirements","r+");
while(fscanf(file,"%s%s",c,c1) == 2){
if(strcmp(c,s1) != 0){
strcpy(sd1[count],c);
strcpy(ver[count],c1);
count++;
}
}
if(fclose(file)){
ERR("fclose");
}
file = fopen("requirements","w+");
fseek(file,0,SEEK_SET);
for(int j = 0 ; j < count ; j++){
fprintf(file,"%s %s\n",sd1[j],ver[j]);
}
if(fclose(file)){
perror("fclose");
exit(EXIT_FAILURE);
}
}
int main(int argc,char** argv){
int i = 0;
int path_size = 500;
char curr[500] = ".";
mode_t perm = 0777;
char path[500];
getcwd(path,500);
char* dirrectioins[500];
int count = 0;
while((i = getopt(argc,argv,"v:c:i:d:")) != -1){
if(i == 'c'){
char* c = optarg;
mkdir(c,perm);
chdir(c);
FILE* x = fopen("requirements","w+");
fclose(x);
}
else if(i == 'v'){
dirrectioins[count] = optarg;
count++;
}
else if (i == 'i') {
char path[500];
getcwd(path, 500);
char name[500];
char version[500];
char *sep = strstr(optarg, "==");
if (sep == NULL) {
fprintf(stderr, "Wrong package format\n");
return EXIT_FAILURE;
}
int len = sep - optarg;
strncpy(name, optarg, len);
name[len] = '\0';
strcpy(version, sep + 2);
for (int i = 0; i < count; i++) {
chdir(dirrectioins[i]);
install(name, version, 500);
chdir(path);
}
}
else if(i == 'd'){
char path[500];
getcwd(path,500);
for(int i=0;i<count;i++){
chdir(dirrectioins[i]);
deleteq(optarg);
chdir(path);
}
}
}
printf("%s\n","KONIEC");
return EXIT_SUCCESS;
}Zadanie 4
#define _POSIX_C_SOURCE 200809L
#include "etap-4.h"
#include <dirent.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#define ERR(source) (perror(source), fprintf(stderr, "%s:%d\n", __FILE__, __LINE__), exit(EXIT_FAILURE))
enum { MAX_TITLE = 64 };
/* Wynik jest nowym blokiem pamięci; wywołujący zwalnia go przez free(). */
char *join_paths(const char *path1, const char *path2)
{
size_t first = strlen(path1);
size_t second = strlen(path2);
int separator = first != 0 && path1[first - 1] != '/';
if (second > SIZE_MAX - 2 || first > SIZE_MAX - second - 2) {
errno = ENOMEM;
ERR("join_paths");
}
char *result = malloc(first + second + 2);
if (result == NULL)
ERR("malloc");
memcpy(result, path1, first);
if (separator)
result[first++] = '/';
memcpy(result + first, path2, second + 1);
return result;
}
void usage(const char *program)
{
fprintf(stderr, "USAGE: %s [database]\n", program);
exit(EXIT_FAILURE);
}
/* Czyta tytuł i gatunek. Wartości są obcinane do 64 bajtów, jak nazwy w indeksie. */
void seek_(const char *pathname, char title[MAX_TITLE + 1], char genre[MAX_TITLE + 1])
{
FILE *file = fopen(pathname, "r");
if (file == NULL)
ERR("fopen");
char *line = NULL;
size_t capacity = 0;
ssize_t length;
title[0] = '\0';
genre[0] = '\0';
while ((length = getline(&line, &capacity, file)) != -1) {
char *colon = strchr(line, ':');
if (colon == NULL)
continue;
size_t key_length = (size_t)(colon - line);
char *value = colon + 1;
size_t value_length = (size_t)(line + length - value);
while (value_length > 0 &&
(value[value_length - 1] == '\n' || value[value_length - 1] == '\r'))
value_length--;
if (value_length > MAX_TITLE)
value_length = MAX_TITLE;
char *destination = NULL;
if (key_length == 5 && memcmp(line, "title", 5) == 0)
destination = title;
else if (key_length == 5 && memcmp(line, "genre", 5) == 0)
destination = genre;
if (destination != NULL) {
memcpy(destination, value, value_length);
destination[value_length] = '\0';
}
}
if (ferror(file))
ERR("getline");
free(line);
if (fclose(file) == EOF)
ERR("fclose");
}
void seek_fgets(const char *pathname, char title[MAX_TITLE + 1], char genre[MAX_TITLE + 1])
{
FILE *file = fopen(pathname, "r");
if (file == NULL)
ERR("fopen");
char line[1024];
title[0] = '\0';
genre[0] = '\0';
while (fgets(line, sizeof(line), file) != NULL) {
int has_non_cr_suffix = 0;
if (strchr(line, '\n') == NULL) {
/* Discard the rest of this line, preserving trailing-CR semantics. */
int character;
while ((character = fgetc(file)) != EOF && character != '\n') {
if (character != '\r')
has_non_cr_suffix = 1;
}
}
char *colon = strchr(line, ':');
if (colon == NULL)
continue;
size_t key_length = (size_t)(colon - line);
char *value = colon + 1;
size_t value_length = strlen(value);
while (!has_non_cr_suffix && value_length > 0 &&
(value[value_length - 1] == '\n' || value[value_length - 1] == '\r'))
value_length--;
if (value_length > MAX_TITLE)
value_length = MAX_TITLE;
char *destination = NULL;
if (key_length == 5 && memcmp(line, "title", 5) == 0)
destination = title;
else if (key_length == 5 && memcmp(line, "genre", 5) == 0)
destination = genre;
if (destination != NULL) {
strncpy(destination, value, value_length);
destination[value_length] = '\0';
}
}
if (ferror(file))
ERR("fgets");
if (fclose(file) == EOF)
ERR("fclose");
}
void recursivesearch(const char *directory_path, const char *relative_path)
{
DIR *directory = opendir(directory_path);
if (directory == NULL)
ERR("opendir");
for (;;) {
errno = 0;
struct dirent *entry = readdir(directory);
if (entry == NULL) {
if (errno != 0)
ERR("readdir");
break;
}
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
char *source = join_paths(directory_path, entry->d_name);
char *relative = join_paths(relative_path, entry->d_name);
struct stat info;
if (lstat(source, &info) == -1)
ERR("lstat");
if (S_ISDIR(info.st_mode)) {
recursivesearch(source, relative);
} else if (S_ISREG(info.st_mode)) {
char title[MAX_TITLE + 1];
char genre[MAX_TITLE + 1];
seek_(source, title, genre);
char *visible_target = join_paths("../../library", relative);
char *visible_link = join_paths("index/by-visible-title", entry->d_name);
if (symlink(visible_target, visible_link) == -1)
ERR("symlink");
free(visible_target);
free(visible_link);
if (title[0] != '\0') {
if (strchr(title, '/') != NULL || !strcmp(title, ".") ||
!strcmp(title, "..")) {
fprintf(stderr, "Niepoprawny tytuł w pliku: %s\n", source);
exit(EXIT_FAILURE);
}
char *title_link = join_paths("index/by-title", title);
char *title_target = join_paths("../../library", relative);
if (symlink(title_target, title_link) == -1)
ERR("symlink");
free(title_link);
free(title_target);
if (genre[0] != '\0') {
if (strchr(genre, '/') != NULL || !strcmp(genre, ".") ||
!strcmp(genre, "..")) {
fprintf(stderr, "Niepoprawny gatunek w pliku: %s\n", source);
exit(EXIT_FAILURE);
}
char *genre_dir = join_paths("index/by-genre", genre);
if (mkdir(genre_dir, 0777) == -1 && errno != EEXIST)
ERR("mkdir");
char *genre_link = join_paths(genre_dir, title);
char *genre_target = join_paths("../../../library", relative);
if (symlink(genre_target, genre_link) == -1)
ERR("symlink");
free(genre_dir);
free(genre_link);
free(genre_target);
}
}
}
free(source);
free(relative);
}
if (closedir(directory) == -1)
ERR("closedir");
}
void Recursie_search(void)
{
if (mkdir("index", 0777) == -1)
ERR("mkdir index");
if (mkdir("index/by-visible-title", 0777) == -1)
ERR("mkdir by-visible-title");
if (mkdir("index/by-title", 0777) == -1)
ERR("mkdir by-title");
if (mkdir("index/by-genre", 0777) == -1)
ERR("mkdir by-genre");
recursivesearch("library", "");
}
int main(int argc, char **argv)
{
if (argc > 2)
usage(argv[0]);
struct stat library_info;
if (stat("library", &library_info) == -1)
ERR("stat library");
if (!S_ISDIR(library_info.st_mode)) {
fprintf(stderr, "library nie jest katalogiem\n");
return EXIT_FAILURE;
}
Recursie_search();
if (argc == 2)
return verify_database(argv[1], "index/by-title") == 0
? EXIT_SUCCESS : EXIT_FAILURE;
return EXIT_SUCCESS;
}#define _POSIX_C_SOURCE 200809L
#include "etap-4.h"
#include <errno.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
enum { TITLE_BYTES = 64, RECORD_BYTES = 68 };
_Static_assert(sizeof(uint32_t) == 4, "Rozmiar pola rozmiaru musi wynosic 4 bajty");
struct book_record {
uint32_t expected_size;
char title[TITLE_BYTES + 1];
};
/* readv() może zwrócić mniej bajtów niż żądano, także w środku rekordu. */
static int read_record(int fd, struct book_record *record)
{
size_t offset = 0;
memset(record, 0, sizeof(*record));
while (offset < RECORD_BYTES) {
struct iovec parts[2];
int count = 0;
if (offset < sizeof(record->expected_size)) {
parts[count].iov_base = (char *)&record->expected_size + offset;
parts[count].iov_len = sizeof(record->expected_size) - offset;
count++;
parts[count].iov_base = record->title;
parts[count].iov_len = TITLE_BYTES;
count++;
} else {
parts[count].iov_base = record->title + offset - sizeof(record->expected_size);
parts[count].iov_len = RECORD_BYTES - offset;
count++;
}
ssize_t n = readv(fd, parts, count);
if (n == -1) {
if (errno == EINTR)
continue;
return -1;
}
if (n == 0)
return -2; /* niepełny rekord, np. baza skrócona podczas czytania */
offset += (size_t)n;
}
record->title[TITLE_BYTES] = '\0';
return 0;
}
static int valid_title(const char title[TITLE_BYTES + 1])
{
size_t len = strnlen(title, TITLE_BYTES);
if (len == 0 || strchr(title, '/') || !strcmp(title, ".") || !strcmp(title, ".."))
return 0;
for (size_t i = len; i < TITLE_BYTES; i++) {
if (title[i] != '\0')
return 0; /* pole krótsze niż 64 bajty musi być dopełnione zerami */
}
return 1;
}
static char *index_path(const char *dir, const char *title)
{
size_t dir_len = strlen(dir);
size_t title_len = strlen(title);
if (title_len > SIZE_MAX - 2 || dir_len > SIZE_MAX - title_len - 2) {
errno = ENOMEM;
return NULL;
}
char *path = malloc(dir_len + title_len + 2);
if (path == NULL)
return NULL;
memcpy(path, dir, dir_len);
path[dir_len] = '/';
memcpy(path + dir_len + 1, title, title_len + 1);
return path;
}
int verify_database(const char *database_path, const char *by_title_dir)
{
int fd = open(database_path, O_RDONLY);
if (fd == -1) {
perror(database_path);
return -1;
}
struct stat database_stat;
if (fstat(fd, &database_stat) == -1) {
perror("fstat");
close(fd);
return -1;
}
if (!S_ISREG(database_stat.st_mode) || database_stat.st_size % RECORD_BYTES != 0) {
fprintf(stderr, "Niepoprawny format bazy: oczekiwano rekordów po %d bajtów\n",
RECORD_BYTES);
close(fd);
return -1;
}
int result = 0;
off_t records = database_stat.st_size / RECORD_BYTES;
for (off_t i = 0; i < records; i++) {
struct book_record book;
int read_result = read_record(fd, &book);
if (read_result != 0) {
if (read_result == -1)
perror("readv");
else
fprintf(stderr, "Niepełny rekord bazy na pozycji %jd\n", (intmax_t)i);
result = -1;
break;
}
if (!valid_title(book.title)) {
fprintf(stderr, "Niepoprawny tytuł w rekordzie %jd\n", (intmax_t)i);
result = -1;
break;
}
char *path = index_path(by_title_dir, book.title);
if (path == NULL) {
perror("malloc");
result = -1;
break;
}
struct stat book_stat;
if (stat(path, &book_stat) == -1) {
if (errno == ENOENT || errno == ENOTDIR) {
if (printf("Book \"%s\" is missing\n", book.title) < 0)
result = -1;
else if (result == 0)
result = 1;
} else {
perror(path);
result = -1;
}
} else if (!S_ISREG(book_stat.st_mode)) {
if (printf("Book \"%s\" is missing\n", book.title) < 0)
result = -1;
else if (result == 0)
result = 1;
} else if (book_stat.st_size != (off_t)book.expected_size) {
if (printf("Book \"%s\" size mismatch (%" PRIu32 " vs %jd)\n",
book.title, book.expected_size, (intmax_t)book_stat.st_size) < 0)
result = -1;
else if (result == 0)
result = 1;
}
free(path);
if (result == -1)
break;
}
if (close(fd) == -1) {
perror("close");
result = -1;
}
if (fflush(stdout) == EOF) {
perror("fflush");
result = -1;
}
return result;
}#ifndef SOP_L1_ETAP_4_H
#define SOP_L1_ETAP_4_H
/* Zwraca 0, gdy baza zgadza się z indeksem; 1 przy brakach lub różnicach,
* -1 przy błędzie odczytu albo niepoprawnym formacie bazy. */
int verify_database(const char *database_path, const char *by_title_dir);
#endif