Coverage Report

Created: 2026-06-15 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/zipcompressaction.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *    http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include <log4cxx/rolling/zipcompressaction.h>
19
#include <apr_thread_proc.h>
20
#include <apr_strings.h>
21
#include <log4cxx/helpers/exception.h>
22
#include <log4cxx/helpers/transcoder.h>
23
#include <log4cxx/private/action_priv.h>
24
#include <log4cxx/helpers/loglog.h>
25
26
using namespace LOG4CXX_NS;
27
using namespace LOG4CXX_NS::rolling;
28
using namespace LOG4CXX_NS::helpers;
29
30
0
#define priv static_cast<ZipCompressActionPrivate*>(m_priv.get())
31
32
struct ZipCompressAction::ZipCompressActionPrivate : public ActionPrivate
33
{
34
  ZipCompressActionPrivate
35
    ( const File& toRename
36
    , const File& renameTo
37
    , bool deleteSource
38
    )
39
0
    : ActionPrivate{ LOG4CXX_STR("zip") }
40
0
    , source(toRename)
41
0
    , destination(renameTo)
42
0
    , deleteSource(deleteSource)
43
0
    {}
44
45
  const File source;
46
  const File destination;
47
  bool deleteSource;
48
  bool throwIOExceptionOnForkFailure = true;
49
};
50
51
IMPLEMENT_LOG4CXX_OBJECT(ZipCompressAction)
52
53
ZipCompressAction::ZipCompressAction(const File& src,
54
  const File& dest,
55
  bool del)
56
0
  : Action(std::make_unique<ZipCompressActionPrivate>(
57
0
        src, dest, del))
58
0
{
59
0
}
Unexecuted instantiation: log4cxx::rolling::ZipCompressAction::ZipCompressAction(log4cxx::File const&, log4cxx::File const&, bool)
Unexecuted instantiation: log4cxx::rolling::ZipCompressAction::ZipCompressAction(log4cxx::File const&, log4cxx::File const&, bool)
60
61
bool ZipCompressAction::execute( LOG4CXX_EXECUTE_ACTION_FORMAL_PARAMETERS ) const
62
0
{
63
0
  if (!priv->source.exists())
64
0
  {
65
0
    return false;
66
0
  }
67
0
  helpers::Pool tempPool;
68
0
  apr_pool_t* aprpool = tempPool.getAPRPool();
69
0
  apr_procattr_t* attr;
70
0
  apr_status_t stat = apr_procattr_create(&attr, aprpool);
71
72
0
  if (stat != APR_SUCCESS)
73
0
  {
74
0
    throw IOException(stat);
75
0
  }
76
77
0
  stat = apr_procattr_io_set(attr, APR_NO_PIPE, APR_NO_PIPE, APR_FULL_BLOCK);
78
79
0
  if (stat != APR_SUCCESS)
80
0
  {
81
0
    throw IOException(stat);
82
0
  }
83
84
0
  stat = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH);
85
86
0
  if (stat != APR_SUCCESS)
87
0
  {
88
0
    throw IOException(stat);
89
0
  }
90
91
  //
92
  // redirect the child's error stream to this processes' error stream
93
  //
94
0
  apr_file_t* child_err;
95
0
  stat = apr_file_open_stderr(&child_err, aprpool);
96
97
0
  if (stat == APR_SUCCESS)
98
0
  {
99
0
    stat =  apr_procattr_child_err_set(attr, child_err, NULL);
100
101
0
    if (stat != APR_SUCCESS)
102
0
    {
103
0
      throw IOException(stat);
104
0
    }
105
0
  }
106
107
0
  const char* args[5];
108
0
  int i = 0;
109
110
0
  args[i++] = "zip";
111
0
  args[i++] = "-q";
112
0
  args[i++] = priv->destination.getAPRPath();
113
0
  args[i++] = priv->source.getAPRPath();
114
0
  args[i++] = NULL;
115
116
0
  if (priv->destination.exists())
117
0
  {
118
0
    priv->destination.deleteFile();
119
0
  }
120
121
0
  apr_proc_t pid;
122
0
  stat = apr_proc_create(&pid, "zip", args, NULL, attr, aprpool);
123
124
0
  if (stat != APR_SUCCESS)
125
0
  {
126
0
    LogLog::warn(LOG4CXX_STR("Failed to fork zip during log rotation; leaving log file uncompressed"));
127
0
    if (priv->throwIOExceptionOnForkFailure)
128
0
      throw IOException(LOG4CXX_STR("zip"), stat);
129
    /* If we fail here (to create the zip child process),
130
     * skip the compression and consider the rotation to be
131
     * otherwise successful. The caller has already rotated
132
     * the log file (`source` here refers to the
133
     * uncompressed, rotated path, and `destination` the
134
     * same path with `.zip` appended). Remove the empty
135
     * destination file and leave source as-is.
136
     */
137
0
    return true;
138
0
  }
139
140
0
  int exitCode;
141
0
  apr_exit_why_e reason;
142
0
  apr_proc_wait(&pid, &exitCode, &reason, APR_WAIT);
143
144
0
  if (exitCode != 0)
145
0
  {
146
0
    throw SubProcessFailure(LOG4CXX_STR("zip"), exitCode, reason);
147
0
  }
148
149
0
  if (priv->deleteSource)
150
0
  {
151
0
    priv->source.deleteFile();
152
0
  }
153
154
0
  return true;
155
0
}
156
157
0
void ZipCompressAction::setThrowIOExceptionOnForkFailure(bool throwIO){
158
0
  priv->throwIOExceptionOnForkFailure = throwIO;
159
0
}