Read "Ordinary Linux Programming" at an in-house study session ~ 10.11 Exercises ~

** I'm new to C. .. .. ** **

environment

Ubuntu


$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

gcc


$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.3.0-16ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --with-as=/usr/bin/x86_64-linux-gnu-as --with-ld=/usr/bin/x86_64-linux-gnu-ld --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)

Exercises

1 Make something like a find command

practice.c


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>

static void traverse(char *path);

int
main(int argc, char *argv[])
{
    int i;

    if (argc < 2) {
        fprintf(stderr, "%s: no argments\n", argv[0]);
        exit(1);
    }
    for (i = 1; i < argc; i++) {
        traverse(argv[i]);
    }
    exit(0);
}

static void
traverse(char *path)
{
    DIR *d = opendir(path);
    struct dirent *ent;
    struct stat st;
    char next[1024];

    while (ent = readdir(d)) {
        lstat(ent->d_name, &st); //TODO error handling
        if (S_ISDIR(st.st_mode)) {
            if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {continue;}
            strcpy(next, path); //I haven't done TODO
            strcat(next, "/");
            strcat(next, ent->d_name);
            traverse(next);
        }
        printf("%s/%s\n", path, ent->d_name);
    }
}

2 from open to close

practice2.c


$ cat practice2.c
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>

int
main(int argc, char *argv[])
{
    DIR *d;
    struct dirent *ent;
    char *path, *path_b;
    FILE *f;
    char *file, *file_b;

    path = "./hoge";
    path_b = "./hoge2";
    file = "file";
    file_b = "file2";

    d = opendir(path);
    f = fopen(file, "a");

    sleep(10);
    rename(path, path_b);
    unlink(path_b);
    closedir(d);

    rename(file, file_b);
    unlink(file_b);
    fclose(f);
}

====
$ strace ./practice
execve("./practice", ["./practice"], 0x7ffff30e83a0 /* 17 vars */) = 0
brk(NULL)                               = 0x7fffcb5c0000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=25480, ...}) = 0
mmap(NULL, 25480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0f80c6e000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0f80c60000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0f80600000
mprotect(0x7f0f807e7000, 2097152, PROT_NONE) = 0
mmap(0x7f0f809e7000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f0f809e7000
mmap(0x7f0f809ed000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0f809ed000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f0f80c614c0) = 0
mprotect(0x7f0f809e7000, 16384, PROT_READ) = 0
mprotect(0x7f0f81000000, 4096, PROT_READ) = 0
mprotect(0x7f0f80c27000, 4096, PROT_READ) = 0
munmap(0x7f0f80c6e000, 25480)           = 0
openat(AT_FDCWD, "./hoge", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0777, st_size=512, ...}) = 0
brk(NULL)                               = 0x7fffcb5c0000
brk(0x7fffcb5e1000)                     = 0x7fffcb5e1000
openat(AT_FDCWD, "file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 4
lseek(4, 0, SEEK_END)                   = 0
nanosleep({tv_sec=10, tv_nsec=0}, ^Z
[1]+  Stopped                 strace ./practice #Suspend, delete, resume ...
$ rm file
$ rmdir hoge/
$ fg
strace ./practice
{tv_sec=8, tv_nsec=773949000}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=4, si_uid=1000} ---
restart_syscall(<... resuming interrupted nanosleep ...>) = 0
rename("./hoge", "./hoge2")             = -1 ENOENT (No such file or directory)
unlink("./hoge2")                       = -1 ENOENT (No such file or directory)
close(3)                                = 0
rename("file", "file2")                 = -1 ENOENT (No such file or directory)
unlink("file2")                         = -1 ENOENT (No such file or directory)
close(4)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
#only this?

3 Make something like "mkdir -p"

practice3.c


#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>

static int *mkdir_p(char *path);

int
main(int argc, char *argv[])
{
    int i;
    char* tp;
    char dir_stac[1024];

    if (argc < 2) {
        fprintf(stderr, "%s: no arguments\n", argv[0]);
        exit(1);
    }
    for (i = 1; i < argc; i++) {
        tp = strtok(argv[i], "/");
        strcpy(dir_stac, tp);
        mkdir_p(dir_stac);
        while(tp = strtok(NULL, "/") ) {
            strcat(dir_stac, "/");
            strcat(dir_stac, tp);
            mkdir_p(dir_stac);
        }
    }
    exit(0);
}

static int
*mkdir_p(char *path)
{
    if (mkdir(path, 0777) < 0) {
        perror(path);
    }
}

Recommended Posts

Read "Ordinary Linux Programming" at an in-house study session ~ 10.11 Exercises ~
Read "Ordinary Linux Programming" at an in-house study session
I tried studying on the WEB server side at an in-house Python study session
We held an in-house study session on mob programming with the theme of FizzBuzz.
Linux study session 2nd: File operation
Read Normal Linux Programming (Part 1 Only)
Matters examined at the August 2017 study session