static int compressLogFile(const char *name, const struct logInfo *log, const struct stat *sb)
{
    char *compressedName;
    int inFile;
    int outFile;
    int status;
    int compressPipe[2];
    char *prevCtx;
    pid_t pid;

    message(MESS_DEBUG, "compressing log with: %s\n", log->compress_prog);
    if (debug)
        return 0;

    if ((inFile = open_logfile(name, log, log->flags & LOG_FLAG_SHRED)) < 0) {
        message(MESS_ERROR, "unable to open %s (%s) for compression: %s\n",
            name, (log->flags & LOG_FLAG_SHRED) ? "read-write" : "read-only", strerror(errno));
        return 1;
    }

    if (setSecCtx(inFile, name, &prevCtx) != 0) {
        /* error msg already printed */
        close(inFile);
        return 1;
    }

#ifdef WITH_ACL
    if ((prev_acl = acl_get_fd(inFile)) == NULL) {
        if (is_acl_well_supported(errno)) {
            message(MESS_ERROR, "getting file ACL %s: %s\n",
                    name, strerror(errno));
            restoreSecCtx(&prevCtx);
            close(inFile);
            return 1;
        }
    }
#endif

    if (asprintf(&compressedName, "%s%s", name, log->compress_ext) < 0) {
        message_OOM();
        close(inFile);
        return 1;
    }

    outFile =
        createOutputFile(compressedName, O_RDWR, sb, prev_acl, 0);
    restoreSecCtx(&prevCtx);
#ifdef WITH_ACL
    if (prev_acl) {
        acl_free(prev_acl);
        prev_acl = NULL;
    }
#endif
    if (outFile < 0) {
        close(inFile);
        free(compressedName);
        return 1;
    }

    /* pipe used to capture stderr of the compress process */
    if (pipe(compressPipe) < 0) {
        message(MESS_ERROR, "error opening pipe for compress: %s\n",
                strerror(errno));
        close(inFile);
        close(outFile);
        free(compressedName);
        return 1;
    }

    pid = fork();

    if (pid == -1) {
        message(MESS_ERROR, "cannot fork: %s\n", strerror(errno));
        close(inFile);
        close(outFile);
        close(compressPipe[1]);
        close(compressPipe[0]);
        free(compressedName);
        return 1;
    }

    if (pid == 0) {
        const char **fullCommand;
        int i;

        /* close read end of pipe in the child process */
        close(compressPipe[0]);
        free(compressedName);

        movefd(inFile, STDIN_FILENO);
        movefd(outFile, STDOUT_FILENO);

        if (switch_user_permanently(log) != 0) {
            exit(1);
        }

        movefd(compressPipe[1], STDERR_FILENO);

        /* export name of file to compress for custom compress scripts */
        {
                char *envInFilename;
                if (asprintf(&envInFilename, "LOGROTATE_COMPRESSED_FILENAME=%s", name) < 0) {
                    message_OOM();
                    exit(1);
                }
                putenv(envInFilename);
                /* do not free envInFilename, cause putenv(3) might not create a copy */
        }

        fullCommand = malloc(sizeof(*fullCommand) * ((size_t)log->compress_options_count + 2));
        if (!fullCommand) {
            message_OOM();
            exit(1);
        }

        fullCommand[0] = log->compress_prog;
        for (i = 0; i < log->compress_options_count; i++)
            fullCommand[i + 1] = log->compress_options_list[i];
        fullCommand[log->compress_options_count + 1] = NULL;

        execvp(fullCommand[0], (void *) fullCommand);
        message(MESS_ERROR, "cannot execute compress command '%s': %s\n", fullCommand[0], strerror(errno));
        exit(1);
    }

    /* close write end of pipe in the parent process */
    close(compressPipe[1]);

    {
        int error_printed = 0;

        for (;;) {
            char buff[4096];
            ssize_t n_read = read(compressPipe[0], buff, sizeof(buff) - 1);

            if (n_read < 0) {
                if (errno == EINTR)
                    continue;
                else
                    break;
            }

            if (n_read == 0)
                break;

            if (!error_printed) {
                error_printed = 1;
                message(MESS_ERROR, "Compressing program wrote following message "
                        "to stderr when compressing log %s:\n", name);
            }
            buff[n_read] = '\0';
            fprintf(stderr, "%s", buff);
        }
    }

    close(compressPipe[0]);
    wait(&status);

    fsync(outFile);
    close(outFile);

    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
        message(MESS_ERROR, "failed to compress log %s\n", name);
        close(inFile);
        unlink(compressedName);
        free(compressedName);
        return 1;
    }

    setAtimeMtime(compressedName, sb);

    free(compressedName);

    if (shred_file(inFile, name, log)) {
        close(inFile);
        return 1;
    }

    close(inFile);

    return 0;
}
static int compressLogFile(const char *name, const struct logInfo *log, const struct stat *sb)
{
    char *compressedName;
    int inFile;
    int outFile;
    int status;
    int compressPipe[2];
    char *prevCtx;
    pid_t pid;

    message(MESS_DEBUG, "compressing log with: %s\n", log->compress_prog);
    if (debug)
        return 0;

    if ((inFile = open_logfile(name, log, log->flags & LOG_FLAG_SHRED)) < 0) {
        message(MESS_ERROR, "unable to open %s (%s) for compression: %s\n",
            name, (log->flags & LOG_FLAG_SHRED) ? "read-write" : "read-only", strerror(errno));
        return 1;
    }

    if (setSecCtx(inFile, name, &prevCtx) != 0) {
         
        close(inFile);
        return 1;
    }

#ifdef WITH_ACL
    if ((prev_acl = acl_get_fd(inFile)) == NULL) {
        if (is_acl_well_supported(errno)) {
            message(MESS_ERROR, "getting file ACL %s: %s\n",
                    name, strerror(errno));
            restoreSecCtx(&prevCtx);
            close(inFile);
            return 1;
        }
    }
#endif

    if (asprintf(&compressedName, "%s%s", name, log->compress_ext) < 0) {
        message_OOM();
        close(inFile);
        return 1;
    }

    outFile =
        createOutputFile(compressedName, O_RDWR, sb, prev_acl, 0);
    restoreSecCtx(&prevCtx);
#ifdef WITH_ACL
    if (prev_acl) {
        acl_free(prev_acl);
        prev_acl = NULL;
    }
#endif
    if (outFile < 0) {
        close(inFile);
        free(compressedName);
        return 1;
    }

     
    if (pipe(compressPipe) < 0) {
        message(MESS_ERROR, "error opening pipe for compress: %s\n",
                strerror(errno));
        close(inFile);
        close(outFile);
        free(compressedName);
        return 1;
    }

    pid = fork();

    if (pid == -1) {
        message(MESS_ERROR, "cannot fork: %s\n", strerror(errno));
        close(inFile);
        close(outFile);
        close(compressPipe[1]);
        close(compressPipe[0]);
        free(compressedName);
        return 1;
    }

    if (pid == 0) {
        const char **fullCommand;
        int i;

         
        close(compressPipe[0]);
        free(compressedName);

        movefd(inFile, STDIN_FILENO);
        movefd(outFile, STDOUT_FILENO);

        if (switch_user_permanently(log) != 0) {
            exit(1);
        }

        movefd(compressPipe[1], STDERR_FILENO);

         
        {
                char *envInFilename;
                if (asprintf(&envInFilename, "LOGROTATE_COMPRESSED_FILENAME=%s", name) < 0) {
                    message_OOM();
                    exit(1);
                }
                putenv(envInFilename);
                 
        }

        fullCommand = malloc(sizeof(*fullCommand) * ((size_t)log->compress_options_count + 2));
        if (!fullCommand) {
            message_OOM();
            exit(1);
        }

        fullCommand[0] = log->compress_prog;
        for (i = 0; i < log->compress_options_count; i++)
            fullCommand[i + 1] = log->compress_options_list[i];
        fullCommand[log->compress_options_count + 1] = NULL;

        execvp(fullCommand[0], (void *) fullCommand);
        message(MESS_ERROR, "cannot execute compress command '%s': %s\n", fullCommand[0], strerror(errno));
        exit(1);
    }

     
    close(compressPipe[1]);

    {
        int error_printed = 0;

        for (;;) {
            char buff[4096];
            ssize_t n_read = read(compressPipe[0], buff, sizeof(buff) - 1);

            if (n_read < 0) {
                if (errno == EINTR)
                    continue;
                else
                    break;
            }

            if (n_read == 0)
                break;

            if (!error_printed) {
                error_printed = 1;
                message(MESS_ERROR, "Compressing program wrote following message "
                        "to stderr when compressing log %s:\n", name);
            }
            buff[n_read] = '\0';
            fprintf(stderr, "%s", buff);
        }
    }

    close(compressPipe[0]);
    wait(&status);

    fsync(outFile);
    close(outFile);

    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
        message(MESS_ERROR, "failed to compress log %s\n", name);
        close(inFile);
        unlink(compressedName);
        free(compressedName);
        return 1;
    }

    setAtimeMtime(compressedName, sb);

    free(compressedName);

    if (shred_file(inFile, name, log)) {
        close(inFile);
        return 1;
    }

    close(inFile);

    return 0;
}