Coverage Report

Created: 2025-07-01 06:08

/src/logging-log4cxx/src/main/cpp/zipcompressaction.cpp
Line
Count
Source (jump to first uncovered line)
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
7
#define priv static_cast<ZipCompressActionPrivate*>(m_priv.get())
31
32
struct ZipCompressAction::ZipCompressActionPrivate : public ActionPrivate
33
{
34
  ZipCompressActionPrivate( const File& toRename,
35
    const File& renameTo,
36
    bool deleteSource):
37
1
    source(toRename), destination(renameTo), deleteSource(deleteSource) {}
38
39
  const File source;
40
  const File destination;
41
  bool deleteSource;
42
  bool throwIOExceptionOnForkFailure = true;
43
};
44
45
IMPLEMENT_LOG4CXX_OBJECT(ZipCompressAction)
46
47
ZipCompressAction::ZipCompressAction(const File& src,
48
  const File& dest,
49
  bool del)
50
1
  : Action(std::make_unique<ZipCompressActionPrivate>(
51
1
        src, dest, del))
52
1
{
53
1
}
Unexecuted instantiation: log4cxx::rolling::ZipCompressAction::ZipCompressAction(log4cxx::File const&, log4cxx::File const&, bool)
log4cxx::rolling::ZipCompressAction::ZipCompressAction(log4cxx::File const&, log4cxx::File const&, bool)
Line
Count
Source
50
1
  : Action(std::make_unique<ZipCompressActionPrivate>(
51
1
        src, dest, del))
52
1
{
53
1
}
54
55
bool ZipCompressAction::execute(LOG4CXX_NS::helpers::Pool& p) const
56
1
{
57
1
  if (!priv->source.exists(p))
58
0
  {
59
0
    return false;
60
0
  }
61
62
1
  apr_pool_t* aprpool = p.getAPRPool();
63
1
  apr_procattr_t* attr;
64
1
  apr_status_t stat = apr_procattr_create(&attr, aprpool);
65
66
1
  if (stat != APR_SUCCESS)
67
0
  {
68
0
    throw IOException(stat);
69
0
  }
70
71
1
  stat = apr_procattr_io_set(attr, APR_NO_PIPE, APR_NO_PIPE, APR_FULL_BLOCK);
72
73
1
  if (stat != APR_SUCCESS)
74
0
  {
75
0
    throw IOException(stat);
76
0
  }
77
78
1
  stat = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH);
79
80
1
  if (stat != APR_SUCCESS)
81
0
  {
82
0
    throw IOException(stat);
83
0
  }
84
85
  //
86
  // redirect the child's error stream to this processes' error stream
87
  //
88
1
  apr_file_t* child_err;
89
1
  stat = apr_file_open_stderr(&child_err, aprpool);
90
91
1
  if (stat == APR_SUCCESS)
92
1
  {
93
1
    stat =  apr_procattr_child_err_set(attr, child_err, NULL);
94
95
1
    if (stat != APR_SUCCESS)
96
0
    {
97
0
      throw IOException(stat);
98
0
    }
99
1
  }
100
101
1
  const char** args = (const char**)
102
1
    apr_palloc(aprpool, 5 * sizeof(*args));
103
1
  int i = 0;
104
105
1
  args[i++] = "zip";
106
1
  args[i++] = "-q";
107
1
  args[i++] = Transcoder::encode(priv->destination.getPath(), p);
108
1
  args[i++] = Transcoder::encode(priv->source.getPath(), p);
109
1
  args[i++] = NULL;
110
111
1
  if (priv->destination.exists(p))
112
0
  {
113
0
    priv->destination.deleteFile(p);
114
0
  }
115
116
1
  apr_proc_t pid;
117
1
  stat = apr_proc_create(&pid, "zip", args, NULL, attr, aprpool);
118
119
1
  if (stat != APR_SUCCESS)
120
0
  {
121
0
    LogLog::warn(LOG4CXX_STR("Failed to fork zip during log rotation; leaving log file uncompressed"));
122
0
    if (priv->throwIOExceptionOnForkFailure)
123
0
      throw IOException(LOG4CXX_STR("zip"), stat);
124
    /* If we fail here (to create the zip child process),
125
     * skip the compression and consider the rotation to be
126
     * otherwise successful. The caller has already rotated
127
     * the log file (`source` here refers to the
128
     * uncompressed, rotated path, and `destination` the
129
     * same path with `.zip` appended). Remove the empty
130
     * destination file and leave source as-is.
131
     */
132
0
    return true;
133
0
  }
134
135
1
  int exitCode;
136
1
  apr_proc_wait(&pid, &exitCode, NULL, APR_WAIT);
137
138
1
  if (exitCode != APR_SUCCESS)
139
0
  {
140
0
    throw IOException(exitCode);
141
0
  }
142
143
1
  if (priv->deleteSource)
144
1
  {
145
1
    priv->source.deleteFile(p);
146
1
  }
147
148
1
  return true;
149
1
}
150
151
1
void ZipCompressAction::setThrowIOExceptionOnForkFailure(bool throwIO){
152
1
  priv->throwIOExceptionOnForkFailure = throwIO;
153
1
}