#define _POSIX_C_SOURCE 200809L #include /* read, write, unlinkat, … */ #include /* openat, O_* */ #include /* fstat, struct stat */ #include /* DIR, fdopendir, readdir, … */ #include /* strlen, memcmp */ #include #include #include /* Naprogramujte proceduru ‹find›, která obdrží: * * • ‹root_fd› je popisovač otevřeného adresáře, * • ‹suffix› je přípona jména hledaného odkazu. * * a která prohledá podstrom začínající v ‹root_fd› a nalezne * všechny odkazy, které mají tvar ‹*.suffix› – tzn. začínají * libovolným řetězcem, pokračují tečkou a končí řetězcem předaném * v parametru ‹suffix›. Počet nalezených odkazů vrátí. Nastane-li * při prohledávání chyba, výsledkem bude -1. */ int count_suffix( int root_fd, const char *suffix ); /* ┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄┄┄┄ následují testy ┄┄┄┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄ */ static void unlink_if_exists( int dir, const char *name ) { if ( unlinkat( dir, name, 0 ) == -1 && errno != ENOENT ) err( 2, "unlinking %s", name ); } static void close_or_warn( int fd, const char *name ) { if ( close( fd ) == -1 ) warn( "closing %s", name ); } static int mkdir_or_die( int dir_fd, const char *name ) { int fd; if ( mkdirat( dir_fd, name, 0777 ) == -1 && errno != EEXIST ) err( 1, "creating directory %s", name ); if ( ( fd = openat( dir_fd, name, O_DIRECTORY ) ) == -1 ) err( 1, "opening newly created directory %s", name ); return fd; } static int create_file( int dir_fd, const char *name ) { unlink_if_exists( dir_fd, name ); int fd; if ( ( fd = openat( dir_fd, name, O_CREAT | O_TRUNC | O_RDWR, 0666 ) ) == -1 ) err( 2, "creating %s", name ); return fd; } static void write_file( int dir, const char *name, const char *str ) { int fd = create_file( dir, name ); if ( write( fd, str, strlen( str ) ) == -1 ) err( 2, "writing file %s", name ); close_or_warn( fd, name ); } int main() { int work_fd = mkdir_or_die( AT_FDCWD, "zt.p5_root" ); int subd_fd = mkdir_or_die( work_fd, "subdir" ); write_file( work_fd, "foo.txt", "x" ); write_file( subd_fd, "bar.csv", "y" ); unlink_if_exists( subd_fd, "foo" ); assert( count_suffix( work_fd, "txt" ) == 1 ); assert( count_suffix( work_fd, "csv" ) == 1 ); write_file( subd_fd, "foo.csv", "" ); assert( count_suffix( work_fd, "txt" ) == 1 ); assert( count_suffix( work_fd, "csv" ) == 2 ); write_file( work_fd, "foo.csv", "" ); assert( count_suffix( work_fd, "txt" ) == 1 ); assert( count_suffix( work_fd, "csv" ) == 3 ); close_or_warn( subd_fd, "zt.p5_root/subdir" ); close_or_warn( work_fd, "zt.p5_root" ); return 0; }