Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • cb48b80315702528ff49d9fd10933d792ffde533
  • master par défaut protégée
  • rust-playlist-sync
  • rust
  • fix-qt-deprecated-qvariant-type
  • fix-mpris-qtwindow-race-condition
  • rust-appimage-wayland
  • windows-build-rebased
  • v2.5 protégée
  • v2.4 protégée
  • v2.3-1 protégée
  • v2.3 protégée
  • v2.2 protégée
  • v2.1 protégée
  • v2.0 protégée
  • v1.8-3 protégée
  • v1.8-2 protégée
  • v1.8-1 protégée
  • v1.8 protégée
  • v1.7 protégée
  • v1.6 protégée
  • v1.5 protégée
  • v1.4 protégée
  • v1.3 protégée
  • v1.2 protégée
  • v1.1 protégée
  • v1.0 protégée
27 résultats

write.c

Blame
  • write.c 8,54 Kio
    #define _POSIX_C_SOURCE 200809L
    #define _DEFAULT_SOURCE
    
    #include <lektor/mkv.h>
    #include <pcre.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <limits.h>
    #include <dirent.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    
    static const char *METADATA_TEMPLATE =
        "   <?xml version=\"1.0\" encoding=\"UTF-8\"?>  "
        "   <Tags>                                      "
        "   <Tag>                                       "
        "     <Targets>                                 "
        "       <TargetTypeValue>70</TargetTypeValue>   "
        "     </Targets>                                "
        "     <Simple>                                  "
        "       <Name>TITLE</Name>                      "
        "       <String>%s</String>                     "
        "     </Simple>                                 "
        "   </Tag>                                      "
        "   <Tag>                                       "
        "     <Simple>                                  "
        "       <Name>TITLE</Name>                      "
        "       <String>%s</String>                     "
        "     </Simple>                                 "
        "     <Simple>                                  "
        "       <Name>CONTENT_TYPE</Name>               "
        "       <String>%s</String>                     "
        "     </Simple>                                 "
        "     <Simple>                                  "
        "       <Name>ADDRESS</Name>                    "
        "       <String>%s</String>                     "
        "     </Simple>                                 "
        "     <Simple>                                  "
        "       <Name>ARTIST</Name>                     "
        "       <String>%s</String>                     "
        "     </Simple>                                 "
        "     <Simple>                                  "
        "       <Name>GENRE</Name>                      "
        "       <String>%s</String>                     "
        "     </Simple>                                 "
        "     <Simple>                                  "
        "       <Name>TRACK</Name>                      "
        "       <String>%d</String>                     "
        "     </Simple>                                 "
        "   </Tag>                                      "
        "   </Tags>                                     ";
    
    static bool
    mkvpropedit__(const char *const args[])
    {
        pid_t pid;
        int wstatus, status, fd;
    
        if ((pid = fork()) == 0) {
            if ((fd = open("/dev/null", O_WRONLY | O_TRUNC)) < 0) {
                fprintf(stderr, " ! call_mkvpropedit: can't to open /dev/null in O_WRONLY O_TRUNC\n");
                return false;
            }
    
            if (dup2(fd, 1) < 0) {
                fprintf(stderr, " ! call_mkvpropedit: failed to duplicate /dev/null to stdout\n");
                return false;
            }
    
            execv(args[0], (char *const *) args);
            exit(EXIT_FAILURE);
        }
    
        else if (pid < 0) {
            fprintf(stderr, " ! metadata_write: failed to fork: %s\n", strerror(errno));
            return false;
        }
    
        else {
            do {
                if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
                    fprintf(stderr, " ! metadata_write: Failed to wait children: %s\n",
                            strerror(errno));
                    return false;
                }
            } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
    
            if ((status = WEXITSTATUS(wstatus))) {
                fprintf(stderr, " ! metadata_write: children failed with status %d", status);
                return false;
            }
        }
    
        return true;
    }
    
    int
    kara_metadata_write(struct kara_metadata *mdt, const char *filename, const char *mkvpropedit)
    {
        char tmpfilepath[PATH_MAX];
        char *const metadafilepath = &tmpfilepath[4];
        const char *const args1[] = { mkvpropedit, "-t", "all:", filename, NULL };
        const char *const args2[] = { mkvpropedit, "-t", tmpfilepath, filename, NULL };
        int fd;
        bool sta = false;
    
        memset(tmpfilepath, 0, PATH_MAX);
        strncat(tmpfilepath, "all:/tmp/lektor.metadata.XXXXXX", PATH_MAX - 1);
    
        if ((fd = mkstemp(metadafilepath)) < 0) {
            fprintf(stderr, " ! metadata_write: failed to create temporary file: %s\n",
                    strerror(errno));
            goto error;
        }
    
        if (dprintf(fd, METADATA_TEMPLATE, mdt->source_name, mdt->song_name, mdt->category,
                    mdt->language, mdt->author_name, mdt->song_type, mdt->song_number) < 0) {
            fprintf(stderr, " ! metadata_write: failed to write to temporary file: %s\n",
                    metadafilepath);
            goto error;
        }
    
        if (!mkvpropedit__(args1) || !mkvpropedit__(args2))
            goto error;
    
        sta = true;
    error:
        close(fd);
        unlink(metadafilepath);
        return sta;
    }
    
    static bool
    metadata_from_path(char *const mkvfile, struct kara_metadata *meta)
    {
        pcre *regex = NULL;
        pcre_extra *pcre_extra = NULL;
        bool sta = false;
        const int sub_str_vec_len = 30;
        int pcre_error_offset, pcre_exec_ret, sub_str_vec[sub_str_vec_len], i, num;
        char num_str[LEKTOR_TAG_MAX];
        const char *substr;
        char *copy_to;
    
        static const char *rgx =
            "^\\/(?:.+)\\/(vo|va|amv|cdg|autres|vocaloid)\\/"
            "(jp|fr|en|ru|sp|it|ch|latin|multi|undefined)\\/(.+)\\/"
            "(.+) - (OP|ED|IS|AMV|VOCA|PV|MV|LIVE)(\\d*) - (.+)\\.mkv$";
        const char *pcre_error_str = NULL;
    
        if ((regex = pcre_compile(rgx, 0, &pcre_error_str, &pcre_error_offset, NULL)) == NULL) {
            fprintf(stderr, " ! metadata_from_path: failed to compile regex\n");
            return false;
        }
    
        pcre_extra = pcre_study(regex, 0, &pcre_error_str);
    
        if (pcre_error_str != NULL) {
            fprintf(stderr, " ! metadata_from_path: failed to study regex: %s\n", pcre_error_str);
            goto error;
        }
    
        memset(meta, 0, sizeof(struct kara_metadata));
        memset(num_str, 0, LEKTOR_TAG_MAX * sizeof(char));
        pcre_exec_ret = pcre_exec(regex, pcre_extra, mkvfile, strlen(mkvfile), 0, 0,
                                  sub_str_vec, sub_str_vec_len);
    
        if (pcre_exec_ret < 0) {
            fprintf(stderr, " ! metadata_from_path: PCRE error\n");
            goto error;
        }
    
        if (pcre_exec_ret == 0) {
            // To much -> error in our case //
            fprintf(stderr, " ! metadata_from_path: To much matches found for file: %s\n", mkvfile);
            goto error;
        }
    
        for (i = 1; i < pcre_exec_ret; ++i) {
            pcre_get_substring(mkvfile, sub_str_vec, pcre_exec_ret, i, &substr);
    
            if (i == 1)
                copy_to = meta->song_type;
            else if (i == 2)
                copy_to = meta->language;
            else if (i == 3)
                copy_to = meta->author_name;
            else if (i == 4)
                copy_to = meta->source_name;
            else if (i == 5)
                copy_to = meta->category;
            else if (i == 6)
                copy_to = num_str;
            else if (i == 7)
                copy_to = meta->song_name;
            else {
                pcre_free_substring(substr);
                goto error;
            }
    
            snprintf(copy_to, LEKTOR_TAG_MAX, "%s", substr);
            pcre_free_substring(substr);
        }
    
        meta->song_number = ((num = atoi(num_str)) <= 0) ? 1 : num;
        sta = true;
    error:
        pcre_free(regex);
    
        if (pcre_extra != NULL) {
    #ifdef PCRE_CONFIG_JIT
            pcre_free_study(pcre_extra);
    #else
            pcre_free(pcre_extra);
    #endif
        }
    
        return sta;
    }
    
    int
    metadata_set_directory(const char *kara_dir, const char *mkvpropedit)
    {
        DIR *d;
        struct dirent *dir;
        char path[PATH_MAX];
        struct kara_metadata meta;
    
        memset(path, 0, PATH_MAX * sizeof(char));
        d = opendir(kara_dir);
    
        if (!d) {
            fprintf(stderr, " ! metadata_set_directory: Failed to open directory '%s': %s\n",
                    kara_dir, strerror(errno));
            return 1;
        }
    
        while (NULL != (dir = readdir(d))) {
            strncpy(path, kara_dir, PATH_MAX - 1);
            strncat(path, "/", PATH_MAX - 1);
            strncat(path, dir->d_name, PATH_MAX - 1);
    
            if (dir->d_type == DT_REG &&
                metadata_from_path(path, &meta) &&
                kara_metadata_write(&meta, path, mkvpropedit))
                continue;
            else if (dir->d_type == DT_DIR &&
                     strcmp(dir->d_name, ".") != 0 &&
                     strcmp(dir->d_name, "..") != 0)
                metadata_set_directory(path, mkvpropedit);
        }
    
        fprintf(stderr, " * metadata_set_directory: Passed directory '%s'\n", kara_dir);
        closedir(d);
        return false;
    }
    
    int
    metadata_set_file(char *karapath, const char *mkvpropedit)
    {
        struct kara_metadata meta;
    
        return metadata_from_path(karapath, &meta) &&
               kara_metadata_write(&meta, karapath, mkvpropedit);
    }