Hello community,

here is the log from the commit of package logrotate for openSUSE:Factory 
checked in at 2015-07-05 17:57:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/logrotate (Old)
 and      /work/SRC/openSUSE:Factory/.logrotate.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "logrotate"

Changes:
--------
--- /work/SRC/openSUSE:Factory/logrotate/logrotate.changes      2015-05-22 
16:32:31.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.logrotate.new/logrotate.changes 2015-07-05 
17:57:33.000000000 +0200
@@ -1,0 +2,22 @@
+Mon Jun 22 12:53:44 UTC 2015 - kstreit...@suse.com
+
+- update to 3.9.1
+  * 3.9.1
+    - Fix off-by-one error which can lead to crash when copytruncate
+      is used.
+  * 3.9.0
+    - Fix crash when using long dateformat. [nmerdan]
+    - Add support for %H dateformat. [czchen]
+    - Fix regression introduced in 3.8.9 when when rotating multiple
+      logs when one of them is missing.
+    - In the debug mode, do not skip the code-path which handles the
+      case when the last rotation does not exist. [Sergey Vidishev]
+    - Show more precise description when "log does not need rotating".
+    - Add new -l option to log verbose output to file. The file is
+      overwritten on every logrotate execution.
+    - Allow rotation of sparse files with copytruncate.
+  * update logrotate-addextension.patch
+- use spec-cleaner
+- remove unused PreReq tags 
+
+-------------------------------------------------------------------

Old:
----
  logrotate-3.8.9.tar.gz

New:
----
  logrotate-3.9.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ logrotate.spec ++++++
--- /var/tmp/diff_new_pack.MQlKxd/_old  2015-07-05 17:57:34.000000000 +0200
+++ /var/tmp/diff_new_pack.MQlKxd/_new  2015-07-05 17:57:34.000000000 +0200
@@ -16,14 +16,13 @@
 #
 
 
-Url:            https://fedorahosted.org/releases/l/o/logrotate
-
 Name:           logrotate
-Version:        3.8.9
+Version:        3.9.1
 Release:        0
 Summary:        Rotate, compress, remove, and mail system log files
 License:        GPL-2.0+
 Group:          System/Base
+Url:            https://fedorahosted.org/releases/l/o/logrotate
 Source:         
https://fedorahosted.org/releases/l/o/%{name}/%{name}-%{version}.tar.gz
 Source100:      %{name}-rpmlintrc
 Source101:      %{name}.service
@@ -39,9 +38,6 @@
 BuildRequires:  libselinux-devel
 BuildRequires:  popt-devel
 BuildRequires:  pkgconfig(systemd) >= 197
-PreReq:         %fillup_prereq
-PreReq:         /bin/mv
-PreReq:         /bin/rm
 Requires:       xz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 %{?systemd_requires}
@@ -64,12 +60,12 @@
 %patch5 -p1
 
 %build
-make %{?_smp_mflags} CC="%__cc" RPM_OPT_FLAGS="%{optflags}" \
+make %{?_smp_mflags} CC="gcc" RPM_OPT_FLAGS="%{optflags}" \
    WITH_SELINUX=yes \
    WITH_ACL=yes
 
 %check
-make test
+make %{?_smp_mflags} test
 
 %install
 make PREFIX=%{buildroot} install
@@ -77,8 +73,8 @@
 mkdir -p %{buildroot}%{_prefix}/sbin
 install -m 644 examples/logrotate-default 
%{buildroot}%{_sysconfdir}/logrotate.conf
 install -m 644 examples/logrotate.wtmp 
%{buildroot}%{_sysconfdir}/logrotate.d/wtmp
-install -D -m 0644 %{S:101} %{buildroot}%{_unitdir}/%{name}.service
-install -D -m 0644 %{S:102} %{buildroot}%{_unitdir}/%{name}.timer
+install -D -m 0644 %{SOURCE101} %{buildroot}%{_unitdir}/%{name}.service
+install -D -m 0644 %{SOURCE102} %{buildroot}%{_unitdir}/%{name}.timer
 
 %pre
 #only the timer can be enabled/disabled/masked !
@@ -86,9 +82,9 @@
 
 %post
 %{remove_and_set MAX_DAYS_FOR_LOG_FILES}
-if [ -f /etc/logrotate.d/aaa_base ] ; then
+if [ -f %{_sysconfdir}/logrotate.d/aaa_base ] ; then
    echo "Saving old logrotate system configuration"
-   mv -v /etc/logrotate.d/aaa_base /etc/logrotate.d.aaa_base.save
+   mv -v %{_sysconfdir}/logrotate.d/aaa_base 
%{_sysconfdir}/logrotate.d.aaa_base.save
 fi
 
 %service_add_post %{name}.service %{name}.timer
@@ -106,7 +102,7 @@
 %{_mandir}/man8/logrotate.8*
 %{_mandir}/man5/logrotate.conf.5*
 %config %{_sysconfdir}/logrotate.conf
-%config(noreplace)/etc/logrotate.d/wtmp
+%config(noreplace)%{_sysconfdir}/logrotate.d/wtmp
 %{_unitdir}/%{name}.service
 %{_unitdir}/%{name}.timer
 

++++++ logrotate-3.8.9.tar.gz -> logrotate-3.9.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/CHANGES new/logrotate-3.9.1/CHANGES
--- old/logrotate-3.8.9/CHANGES 2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/CHANGES 2015-04-03 09:39:35.000000000 +0200
@@ -1,3 +1,17 @@
+3.9.0 -> 3.9.1
+       - Fix off-by-one error which can lead to crash when copytruncate is 
used.
+3.8.9 -> 3.9.0
+       - Fix crash when using long dateformat. [nmerdan]
+       - Add support for %H dateformat. [czchen]
+       - Fix regression introduced in 3.8.9 when when rotating multiple
+         logs when one of them is missing.
+       - In the debug mode, do not skip the code-path which handles the case 
when
+         the last rotation does not exist. [Sergey Vidishev]
+       - Show more precise description when "log does not need rotating".\
+       - Add new -l option to log verbose output to file. The file is 
overwritten
+         on every logrotate execution.
+       - Allow rotation of sparse files with copytruncate.
+
 3.8.8 -> 3.8.9
        - Add new directive "createolddir" and "nocreateolddir". These 
directives
          can be used to create the directory specified by olddir with 
particular
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/Makefile new/logrotate-3.9.1/Makefile
--- old/logrotate-3.8.9/Makefile        2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/Makefile        2015-04-03 09:39:35.000000000 +0200
@@ -1,7 +1,7 @@
 VERSION = $(shell awk '/Version:/ { print $$2 }' logrotate.spec)
 OS_NAME = $(shell uname -s)
 LFS = $(shell echo `getconf LFS_CFLAGS 2>/dev/null`)
-CFLAGS = -Wall -D_GNU_SOURCE -D$(OS_NAME) -DVERSION=\"$(VERSION)\" 
-DHAVE_STRPTIME=1 -DHAVE_QSORT $(RPM_OPT_FLAGS) $(LFS)
+CFLAGS = -Wall -D_GNU_SOURCE -D$(OS_NAME) -DVERSION=\"$(VERSION)\" 
-DHAVE_STRPTIME=1 -DHAVE_QSORT -DHAVE_STRUCT_STAT_ST_BLOCKS 
-DHAVE_STRUCT_STAT_ST_BLKSIZE $(RPM_OPT_FLAGS) $(LFS)
 PROG = logrotate
 MAN = logrotate.8
 MAN5 = logrotate.conf.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/configure.ac 
new/logrotate-3.9.1/configure.ac
--- old/logrotate-3.8.9/configure.ac    2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/configure.ac    2015-04-03 09:39:35.000000000 +0200
@@ -1,4 +1,4 @@
-AC_INIT([logrotate],[3.8.9])
+AC_INIT([logrotate],[3.9.1])
 
 AM_INIT_AUTOMAKE
 AC_DEFINE(_GNU_SOURCE)
@@ -7,6 +7,8 @@
 
 AC_PROG_CC
 AC_PROG_CC_STDC
+AC_STRUCT_ST_BLKSIZE
+AC_STRUCT_ST_BLOCKS
 
 AC_CHECK_LIB([popt],[poptParseArgvString],,
   AC_MSG_ERROR([libpopt required but not found]))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/log.c new/logrotate-3.9.1/log.c
--- old/logrotate-3.8.9/log.c   2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/log.c   2015-04-03 09:39:35.000000000 +0200
@@ -37,75 +37,48 @@
     flags &= ~newFlags;
 }
 
-#if 0
-void log(int fd, char *format, ...)
+static void log_once(FILE *where, int level, char *format, va_list args)
 {
-    int i = 0;
-    char *buf = NULL;
-    va_list args;
-    int size;
-
-    va_start(args, format);
-
-    do {
-       i += 1000;
-       if (buf)
-           free(buf);
-       buf = malloc(i);
-       size = vsnprintf(buf, i, format, args);
-    } while (size >= i);
-
-    write(fd, buf, size);
-
-    free(buf);
-
-    va_end(args);
-}
-#endif
-
-void message(int level, char *format, ...)
-{
-    va_list args;
-    FILE *where = NULL;
-    int showTime = 0;
-
-    if (errorFile == NULL)
-       errorFile = stderr;
-    if (messageFile == NULL)
-       messageFile = stderr;
-    where = errorFile;
-
-    if (level >= logLevel) {
-       va_start(args, format);
+       int showTime = 0;
 
        switch (level) {
        case MESS_DEBUG:
-           where = messageFile;
-           showTime = 1;
-           break;
-
+               showTime = 1;
+               break;
        case MESS_NORMAL:
        case MESS_VERBOSE:
-           where = messageFile;
-           break;
-
+               break;
        default:
-           if (flags & LOG_TIMES)
+               if (flags & LOG_TIMES)
                fprintf(where, "%ld: ", (long) time(NULL));
-           fprintf(errorFile, "error: ");
-           break;
+               fprintf(where, "error: ");
+               break;
        }
 
        if (showTime && (flags & LOG_TIMES)) {
-           fprintf(where, "%ld:", (long) time(NULL));
+               fprintf(where, "%ld:", (long) time(NULL));
        }
 
        vfprintf(where, format, args);
        fflush(where);
 
-       va_end(args);
-
        if (level == MESS_FATAL)
-           exit(1);
+               exit(1);
+}
+
+void message(int level, char *format, ...)
+{
+    va_list args;
+    
+    if (level >= logLevel) {
+       va_start(args, format);
+       log_once(stderr, level, format, args);
+       va_end(args);
+    }
+    
+    if (messageFile != NULL) {
+       va_start(args, format);
+       log_once(messageFile, level, format, args);
+       va_end(args);
     }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/log.h new/logrotate-3.9.1/log.h
--- old/logrotate-3.8.9/log.h   2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/log.h   2015-04-03 09:39:35.000000000 +0200
@@ -18,9 +18,6 @@
 #else
 ;
 #endif
-#if 0
-void log(int fd, char *format, ...);
-#endif
 void logSetErrorFile(FILE * f);
 void logSetMessageFile(FILE * f);
 void logSetFlags(int flags);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/logrotate.8 
new/logrotate-3.9.1/logrotate.8
--- old/logrotate-3.8.9/logrotate.8     2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/logrotate.8     2015-04-03 09:39:35.000000000 +0200
@@ -48,6 +48,12 @@
 correctly.
 
 .TP
+\fB\-l <log_file>\fR
+Tells \fBlogrotate\fR to log verbose output into the log_file. The verbose
+output logged to that file is the same as when running \fBlogrotate\fR with
+\fB-v\fR switch. The log file is overwritten on every logrotate execution.
+
+.TP
 \fB\-m\fR, \fB\-\-mail <command>\fR
 Tells \fBlogrotate\fR which command to use when mailing logs. This
 command should accept two arguments: 1) the subject of the message, and
@@ -239,10 +245,11 @@
 .TP
 \fBdateformat\fR \fIformat_string\fR
 Specify the extension for \fBdateext\fR using the notation similar to
-\fBstrftime\fR(3) function. Only %Y %m %d and %s specifiers are allowed.
-The default value is \-%Y%m%d. Note that also the character separating log
-name from the extension is part of the dateformat string. The system clock
-must be set past Sep 9th 2001 for %s to work correctly.
+\fBstrftime\fR(3) function. Only %Y %m %d %H and %s specifiers are allowed.
+The default value is \-%Y%m%d except hourly, which uses \-%Y%m%d%H as default
+value.  Note that also the character separating log name from the extension is
+part of the dateformat string. The system clock must be set past Sep 9th 2001
+for %s to work correctly.
 Note that the datestamps generated by this format must be lexically sortable
 (i.e., first the year, then the month then the day. e.g., 2001/12/01 is ok,
 but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/logrotate.c 
new/logrotate-3.9.1/logrotate.c
--- old/logrotate-3.8.9/logrotate.c     2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/logrotate.c     2015-04-03 09:39:35.000000000 +0200
@@ -20,6 +20,7 @@
 #include <locale.h>
 #include <sys/types.h>
 #include <utime.h>
+#include <stdint.h>
 
 #if defined(SunOS)
 #include <limits.h>
@@ -72,8 +73,6 @@
 #define DOEXIT exit
 #endif
 
-#define ERROR_STOP_ROTATION 1
-#define ERROR_CONTINUE_ROTATION 2
 
 struct logState {
     char *fn;
@@ -740,12 +739,133 @@
     return 0;
 }
 
+/* Use a heuristic to determine whether stat buffer SB comes from a file
+   with sparse blocks.  If the file has fewer blocks than would normally
+   be needed for a file of its size, then at least one of the blocks in
+   the file is a hole.  In that case, return true.  */
+static int is_probably_sparse(struct stat const *sb)
+{
+#if defined(HAVE_STRUCT_STAT_ST_BLOCKS) && defined(HAVE_STRUCT_STAT_ST_BLKSIZE)
+       return (S_ISREG (sb->st_mode)
+          && sb->st_blocks < sb->st_size / sb->st_blksize);
+#else
+       return 0;
+#endif
+}
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+/* Return whether the buffer consists entirely of NULs.
+   Note the word after the buffer must be non NUL. */
+
+static inline int is_nul (void const *buf, size_t bufsize)
+{
+  char const *cbuf = buf;
+  char const *cp = buf;
+
+  /* Find the first nonzero *byte*, or the sentinel.  */
+  while (*cp++ == 0)
+    continue;
+
+  return cbuf + bufsize < cp;
+}
+
+static size_t full_write(int fd, const void *buf, size_t count)
+{
+  size_t total = 0;
+  const char *ptr = (const char *) buf;
+
+  while (count > 0)
+    {
+      size_t n_rw;
+       for (;;)
+       {
+               n_rw = write (fd, buf, count);
+               if (errno == EINTR)
+                       continue;
+               else
+                       break;
+       }
+       if (n_rw == (size_t) -1)
+               break;
+       if (n_rw == 0)
+               break;
+       total += n_rw;
+       ptr += n_rw;
+       count -= n_rw;
+    }
+
+  return total;
+}
+
+static int sparse_copy(int src_fd, int dest_fd, struct stat *sb,
+                      const char *saveLog, const char *currLog)
+{
+       int make_holes = is_probably_sparse(sb);
+       size_t max_n_read = SIZE_MAX;
+       int last_write_made_hole = 0;
+       off_t total_n_read = 0;
+       char buf[BUFSIZ + 1];
+
+       while (max_n_read) {
+               int make_hole = 0;
+
+               ssize_t n_read = read (src_fd, buf, MIN (max_n_read, BUFSIZ));
+               if (n_read < 0) {
+                       if (errno == EINTR) {
+                               continue;
+                       }
+                       message(MESS_ERROR, "error reading %s: %s\n",
+                               currLog, strerror(errno));
+                       return 0;
+               }
+
+               if (n_read == 0)
+                       break;
+
+               max_n_read -= n_read;
+               total_n_read += n_read;
+
+               if (make_holes) {
+                       /* Sentinel required by is_nul().  */
+                       buf[n_read] = '\1';
+
+                       if ((make_hole = is_nul(buf, n_read))) {
+                               if (lseek (dest_fd, n_read, SEEK_CUR) < 0) {
+                                       message(MESS_ERROR, "error seeking %s: 
%s\n",
+                                               saveLog, strerror(errno));
+                                       return 0;
+                               }
+                       }
+               }
+
+               if (!make_hole) {
+                       size_t n = n_read;
+                       if (full_write (dest_fd, buf, n) != n) {
+                               message(MESS_ERROR, "error writing to %s: %s\n",
+                                       saveLog, strerror(errno));
+                               return 0;
+                       }
+               }
+
+               last_write_made_hole = make_hole;
+       }
+
+       if (last_write_made_hole) {
+               if (ftruncate(dest_fd, total_n_read) < 0) {
+                       message(MESS_ERROR, "error ftruncate %s: %s\n",
+                       saveLog, strerror(errno));
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
 static int copyTruncate(char *currLog, char *saveLog, struct stat *sb,
                        int flags)
 {
-    char buf[BUFSIZ];
     int fdcurr = -1, fdsave = -1;
-    ssize_t cnt;
 
     message(MESS_DEBUG, "copying %s to %s\n", currLog, saveLog);
 
@@ -753,7 +873,7 @@
        if ((fdcurr = open(currLog, ((flags & LOG_FLAG_COPY) ? O_RDONLY : 
O_RDWR) | O_NOFOLLOW)) < 0) {
            message(MESS_ERROR, "error opening %s: %s\n", currLog,
                    strerror(errno));
-           return ERROR_CONTINUE_ROTATION;
+           return 1;
        }
 #ifdef WITH_SELINUX
        if (selinux_enabled) {
@@ -822,21 +942,10 @@
            return 1;
        }
 
-       while ((cnt = read(fdcurr, buf, sizeof(buf))) > 0) {
-           if (write(fdsave, buf, cnt) != cnt) {
-               message(MESS_ERROR, "error writing to %s: %s\n",
-                       saveLog, strerror(errno));
+       if (sparse_copy(fdcurr, fdsave, sb, saveLog, currLog) != 1) {
                close(fdcurr);
                close(fdsave);
                return 1;
-           }
-       }
-       if (cnt != 0) {
-           message(MESS_ERROR, "error reading %s: %s\n",
-                   currLog, strerror(errno));
-           close(fdcurr);
-           close(fdsave);
-           return 1;
        }
     }
 
@@ -928,8 +1037,15 @@
        /* user forced rotation of logs from command line */
        state->doRotate = 1;   
     }
+    else if (log->maxsize && sb.st_size > log->maxsize) {
+        state->doRotate = 1;
+    }
     else if (log->criterium == ROT_SIZE) {
        state->doRotate = (sb.st_size >= log->threshhold);
+       if (!state->doRotate) {
+       message(MESS_DEBUG, "  log does not need rotating "
+               "(log size is below the 'size' threshold)\n");
+       }
     } else if (mktime(&state->lastRotated) - mktime(&now) > (25 * 3600)) {
         /* 25 hours allows for DST changes as well as geographical moves */
        message(MESS_ERROR,
@@ -952,49 +1068,90 @@
                               ((mktime(&now) -
                                 mktime(&state->lastRotated)) >
                                (7 * 24 * 3600)));
+           if (!state->doRotate) {
+           message(MESS_DEBUG, "  log does not need rotating "
+                   "(log has been rotated at %d-%d-%d %d:%d, "
+                   "that is not week ago yet)\n", state->lastRotated.tm_year,
+                   state->lastRotated.tm_mon, state->lastRotated.tm_mday,
+                   state->lastRotated.tm_hour, state->lastRotated.tm_min);
+           }
            break;
        case ROT_HOURLY:
            state->doRotate = ((now.tm_hour != state->lastRotated.tm_hour) ||
                            (now.tm_mday != state->lastRotated.tm_mday) ||
                            (now.tm_mon != state->lastRotated.tm_mon) ||
                            (now.tm_year != state->lastRotated.tm_year));
+           if (!state->doRotate) {
+           message(MESS_DEBUG, "  log does not need rotating "
+                   "(log has been rotated at %d-%d-%d %d:%d, "
+                   "that is not hour ago yet)\n", state->lastRotated.tm_year,
+                   state->lastRotated.tm_mon, state->lastRotated.tm_mday,
+                   state->lastRotated.tm_hour, state->lastRotated.tm_min);
+           }
            break;
        case ROT_DAYS:
            /* FIXME: only days=1 is implemented!! */
            state->doRotate = ((now.tm_mday != state->lastRotated.tm_mday) ||
                            (now.tm_mon != state->lastRotated.tm_mon) ||
                            (now.tm_year != state->lastRotated.tm_year));
+           if (!state->doRotate) {
+           message(MESS_DEBUG, "  log does not need rotating "
+                   "(log has been rotated at %d-%d-%d %d:%d, "
+                   "that is not day ago yet)\n", state->lastRotated.tm_year,
+                   state->lastRotated.tm_mon, state->lastRotated.tm_mday,
+                   state->lastRotated.tm_hour, state->lastRotated.tm_min);
+           }
            break;
        case ROT_MONTHLY:
            /* rotate if the logs haven't been rotated this month or
               this year */
            state->doRotate = ((now.tm_mon != state->lastRotated.tm_mon) ||
                            (now.tm_year != state->lastRotated.tm_year));
+           if (!state->doRotate) {
+           message(MESS_DEBUG, "  log does not need rotating "
+                   "(log has been rotated at %d-%d-%d %d:%d, "
+                   "that is not month ago yet)\n", state->lastRotated.tm_year,
+                   state->lastRotated.tm_mon, state->lastRotated.tm_mday,
+                   state->lastRotated.tm_hour, state->lastRotated.tm_min);
+           }
            break;
        case ROT_YEARLY:
            /* rotate if the logs haven't been rotated this year */
            state->doRotate = (now.tm_year != state->lastRotated.tm_year);
+           if (!state->doRotate) {
+           message(MESS_DEBUG, "  log does not need rotating "
+                   "(log has been rotated at %d-%d-%d %d:%d, "
+                   "that is not year ago yet)\n", state->lastRotated.tm_year,
+                   state->lastRotated.tm_mon, state->lastRotated.tm_mday,
+                   state->lastRotated.tm_hour, state->lastRotated.tm_min);
+           }
            break;
        default:
            /* ack! */
            state->doRotate = 0;
            break;
        }
-       if (log->minsize && sb.st_size < log->minsize)
+       if (log->minsize && sb.st_size < log->minsize) {
            state->doRotate = 0;
+           message(MESS_DEBUG, "  log does not need rotating "
+                   "('misinze' directive is used and the log "
+                   "size is smaller than the minsize value");
+       }
+    }
+    else if (!state->doRotate) {
+       message(MESS_DEBUG, "  log does not need rotating "
+               "(log has been already rotated)");
     }
-
-    if (log->maxsize && sb.st_size > log->maxsize)
-        state->doRotate = 1;
 
     /* The notifempty flag overrides the normal criteria */
-    if (!(log->flags & LOG_FLAG_IFEMPTY) && !sb.st_size)
+    if (state->doRotate && !(log->flags & LOG_FLAG_IFEMPTY) && !sb.st_size) {
        state->doRotate = 0;
+       message(MESS_DEBUG, "  log does not need rotating "
+               "(log is empty)");
+    }
 
     if (state->doRotate) {
        message(MESS_DEBUG, "  log needs rotating\n");
-    } else {
-       message(MESS_DEBUG, "  log does not need rotating\n");
     }
 
     return 0;
@@ -1099,6 +1256,7 @@
                                                j += 10; /* 
strlen("[0-9][0-9]") */
                                        case 'm':
                                        case 'd':
+                                       case 'H':
                                                strncat(dext_pattern, 
"[0-9][0-9]",
                                                                
sizeof(dext_pattern) - strlen(dext_pattern) - 1);
                                                j += 10;
@@ -1250,9 +1408,10 @@
        }
     }
 
+    /* adding 2 due to / and \0 being added by snprintf */
     rotNames->firstRotated =
        malloc(strlen(rotNames->dirName) + strlen(rotNames->baseName) +
-              strlen(fileext) + strlen(compext) + 30);
+              strlen(fileext) + strlen(compext) + DATEEXT_LEN + 2 );
 
     if (log->flags & LOG_FLAG_DATEEXT) {
        /* glob for compressed files with our pattern
@@ -1411,10 +1570,9 @@
        }
 
     /* if the last rotation doesn't exist, that's okay */
-    if (!debug && rotNames->disposeName
-       && access(rotNames->disposeName, F_OK)) {
+    if (rotNames->disposeName && access(rotNames->disposeName, F_OK)) {
        message(MESS_DEBUG,
-               "log %s doesn't exist -- won't try to " "dispose of it\n",
+               "log %s doesn't exist -- won't try to dispose of it\n",
                rotNames->disposeName);
        free(rotNames->disposeName);
        rotNames->disposeName = NULL;
@@ -1501,7 +1659,7 @@
                        if (!ACL_NOT_WELL_SUPPORTED(errno)) {
                                message(MESS_ERROR, "getting file ACL %s: %s\n",
                                        log->files[logNum], strerror(errno));
-                               hasErrors |= 1;
+                               hasErrors = 1;
                        }
                }
 #endif /* WITH_ACL */
@@ -1517,12 +1675,7 @@
                        message(MESS_ERROR, "failed to rename %s to %s: %s\n",
                                log->files[logNum], tmpFilename,
                                strerror(errno));
-                               if (errno == ENOENT) {
-                                       hasErrors |= ERROR_CONTINUE_ROTATION;
-                               }
-                               else {
-                                       hasErrors |= 1;
-                               }
+                               hasErrors = 1;
                        }
                }
                else {
@@ -1533,7 +1686,7 @@
                                message(MESS_ERROR, "failed to rename %s to %s: 
%s\n",
                                        log->files[logNum], tmpFilename,
                                        strerror(errno));
-                                       hasErrors |= 1;
+                                       hasErrors = 1;
                        }
            }
 
@@ -1587,7 +1740,7 @@
                        }
 #endif
                        if (fd < 0)
-                               hasErrors |= 1;
+                               hasErrors = 1;
                        else {
                                close(fd);
                        }
@@ -1605,7 +1758,7 @@
        if (!hasErrors
            && log->flags & (LOG_FLAG_COPYTRUNCATE | LOG_FLAG_COPY)
                && !(log->flags & LOG_FLAG_TMPFILENAME)) {
-           hasErrors |=
+           hasErrors =
                copyTruncate(log->files[logNum], rotNames->finalName,
                             &state->sb, log->flags);
        }
@@ -1680,7 +1833,6 @@
     int i, j;
     int hasErrors = 0;
     int logHasErrors[log->numFiles];
-       int logHasScriptErrors[log->numFiles];
     int numRotated = 0;
     struct logState **state;
     struct logNames **rotNames;
@@ -1752,7 +1904,6 @@
     for (i = 0; i < log->numFiles; i++) {
        logHasErrors[i] = findNeedRotating(log, i, force);
        hasErrors |= logHasErrors[i];
-       logHasScriptErrors[i] = 0;
 
        /* sure is a lot of findStating going on .. */
        if ((findState(log->files[i]))->doRotate)
@@ -1821,8 +1972,7 @@
                                "error running non-shared prerotate script "
                                "for %s of '%s'\n", log->files[j], 
log->pattern);
                    }
-                   logHasScriptErrors[j] = 1;
-                       logHasErrors[j] = 1;
+                   logHasErrors[j] = 1;
                    hasErrors = 1;
                }
            }
@@ -1831,7 +1981,8 @@
        for (i = j;
             ((log->flags & LOG_FLAG_SHAREDSCRIPTS) && i < log->numFiles)
             || (!(log->flags & LOG_FLAG_SHAREDSCRIPTS) && i == j); i++) {
-           if (!logHasScriptErrors[i] && !(logHasErrors[i] & 
ERROR_STOP_ROTATION)) {
+           if (! ( (logHasErrors[i] && !(log->flags & LOG_FLAG_SHAREDSCRIPTS))
+                  || (hasErrors && (log->flags & LOG_FLAG_SHAREDSCRIPTS)) ) ) {
                logHasErrors[i] |=
                    rotateSingleLog(log, i, state[i], rotNames[i]);
                hasErrors |= logHasErrors[i];
@@ -1840,7 +1991,7 @@
 
        if (log->post
                && (!(
-                       (((logHasErrors[j] & ERROR_STOP_ROTATION) || 
!state[j]->doRotate) && !(log->flags & LOG_FLAG_SHAREDSCRIPTS))
+                       ((logHasErrors[j] || !state[j]->doRotate) && 
!(log->flags & LOG_FLAG_SHAREDSCRIPTS))
                        || (hasErrors && (log->flags & LOG_FLAG_SHAREDSCRIPTS))
                ))
        ) {
@@ -1859,8 +2010,7 @@
                                "error running non-shared postrotate script "
                                "for %s of '%s'\n", log->files[j], 
log->pattern);
                    }
-                   logHasScriptErrors[j] = 1;
-                       logHasErrors[j] = 1;
+                   logHasErrors[j] = 1;
                    hasErrors = 1;
                }
            }
@@ -1869,7 +2019,8 @@
        for (i = j;
             ((log->flags & LOG_FLAG_SHAREDSCRIPTS) && i < log->numFiles)
             || (!(log->flags & LOG_FLAG_SHAREDSCRIPTS) && i == j); i++) {
-               if (!logHasScriptErrors[i] && !(logHasErrors[i] & 
ERROR_STOP_ROTATION)) {
+           if (! ( (logHasErrors[i] && !(log->flags & LOG_FLAG_SHAREDSCRIPTS))
+                  || (hasErrors && (log->flags & LOG_FLAG_SHAREDSCRIPTS)) ) ) {
                logHasErrors[i] |=
                    postrotateSingleLog(log, i, state[i], rotNames[i]);
                hasErrors |= logHasErrors[i];
@@ -2273,6 +2424,8 @@
 {
     int force = 0;
     char *stateFile = STATEFILE;
+    char *logFile = NULL;
+    FILE *logFd = 0;
     int rc = 0;
     int arg;
     const char **files;
@@ -2290,6 +2443,7 @@
         "Path of state file",
         "statefile"},
        {"verbose", 'v', 0, 0, 'v', "Display messages during rotation"},
+       {"log", 'l', POPT_ARG_STRING, &logFile, 'l', "Log file"},
        {"version", '\0', POPT_ARG_NONE, NULL, 'V', "Display version 
information"},
        POPT_AUTOHELP {0, 0, 0, 0, 0}
     };
@@ -2309,6 +2463,15 @@
        case 'v':
            logSetLevel(MESS_DEBUG);
            break;
+       case 'l':
+           logFd = fopen(logFile, "w");
+           if (!logFd) {
+               message(MESS_ERROR, "error opening log file %s: %s\n",
+                       logFile, strerror(errno));
+               break;
+           }
+           logSetMessageFile(logFd);
+           break;
        case 'V':
            fprintf(stderr, "logrotate %s\n", VERSION);
            poptFreeContext(optCon);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/logrotate.spec 
new/logrotate-3.9.1/logrotate.spec
--- old/logrotate-3.8.9/logrotate.spec  2015-02-13 07:11:21.000000000 +0100
+++ new/logrotate-3.9.1/logrotate.spec  2015-04-03 09:39:35.000000000 +0200
@@ -1,6 +1,6 @@
 Summary: Rotates, compresses, removes and mails system log files
 Name: logrotate
-Version: 3.8.9
+Version: 3.9.1
 Release: 1
 License: GPL+
 Group: System Environment/Base
@@ -52,6 +52,12 @@
 %attr(0644, root, root) %verify(not size md5 mtime) %config(noreplace) 
%{_localstatedir}/lib/logrotate.status
 
 %changelog
+* Fri Apr 03 2015 Jan Kaluza <jkal...@redhat.com> 3.9.1-1
+- new upstream version
+
+* Fri Apr 03 2015 Jan Kaluza <jkal...@redhat.com> 3.9.0-1
+- new upstream version
+
 * Fri Feb 13 2015 Jan Kaluza <jkal...@redhat.com> 3.8.9-1
 - new upstream version
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/test/test 
new/logrotate-3.9.1/test/test
--- old/logrotate-3.8.9/test/test       2015-02-13 07:11:20.000000000 +0100
+++ new/logrotate-3.9.1/test/test       2015-04-03 09:39:35.000000000 +0200
@@ -539,7 +539,7 @@
 # ------------------------------- Test 17 ------------------------------------
 preptest test.log 17 1 0
 # log with 1 byte should not be rotated
-$RLR test-config.17 2>error.log
+$RLR test-config.17 -l logrotate.log 2>error.log
 
 grep "unexpected } (missing previous '{')" error.log >/dev/null
 if [ $? != 0 ]; then
@@ -549,6 +549,14 @@
 
 rm error.log
 
+grep "reading config file test-config.17" logrotate.log >/dev/null
+if [ $? != 0 ]; then
+       echo "There is no log output in logrotate.log"
+       exit 3
+fi
+
+rm -f logrotate.log
+
 checkoutput <<EOF
 test.log 0 zero
 EOF
@@ -809,24 +817,28 @@
 getfacl test.log|grep "user:nobody:rwx" >/dev/null
 if [ $? != 0 ]; then
        echo "test.log must have user:nobody:rwx ACL"
+       getfacl test.log
        exit 3
 fi
 
 getfacl test.log|grep "group::---" >/dev/null
 if [ $? != 0 ]; then
        echo "test.log must have group::--- ACL"
+       getfacl test.log
        exit 3
 fi
 
 getfacl test.log.1|grep "user:nobody:rwx" >/dev/null
 if [ $? != 0 ]; then
        echo "test.log.1 must have user:nobody:rwx ACL"
+       getfacl test.log.1
        exit 3
 fi
 
 getfacl test.log.1|grep "group::---" >/dev/null
 if [ $? != 0 ]; then
        echo "test.log.1 must have group::--- ACL"
+       getfacl test.log.1
        exit 3
 fi
 
@@ -1124,7 +1136,7 @@
 
 # ------------------------------- Test 45 ------------------------------------
 # Test that prerotate and postrotate scripts are not called when sharedscripts
-# is defined and one rotation fails. File test.log should still be rotated.
+# is defined and one rotation fails
 preptest test.log 45 1
 
 touch scriptout
@@ -1139,8 +1151,7 @@
 rm -f error.log
 
 checkoutput <<EOF
-test.log 0
-test.log.1 0 zero
+test.log 0 zero
 scriptout 0 
 EOF
 
@@ -1494,21 +1505,111 @@
 cleanup 60
 
 # ------------------------------- Test 60 ------------------------------------
-# Rotation should continue even when first log is removed during rotation
-preptest test.log 60 1
-echo test2 > test2.log
+# Test we log debug output using -l option when passed.
+preptest test.log 61 1 0
+
+$RLR test-config.61 --force -l ./logrotate.log
 
-$RLR test-config.60 2>error.log
+DATESTRING=$(/bin/date +%Y-%m-%d-%H)
 
-grep "error opening" error.log >/dev/null
+grep "reading config file test-config.61" logrotate.log >/dev/null
 if [ $? != 0 ]; then
-       echo "No error printed, but there should be one."
+       echo "There is no log output in logrotate.log"
        exit 3
 fi
 
+rm -f logrotate.log
+
 checkoutput <<EOF
-test2.log 0
-test2.log.1 0 test2
+test.log 0
+test.log.$DATESTRING 0 zero
+EOF
+
+cleanup 61
+
+# ------------------------------- Test 61 ------------------------------------
+preptest test.log 61 1 0
+
+$RLR test-config.61 --force
+
+DATESTRING=$(/bin/date +%Y-%m-%d-%H)
+
+checkoutput <<EOF
+test.log 0
+test.log.$DATESTRING 0 zero
+EOF
+
+cleanup 62
+
+# ------------------------------- Test 62 ------------------------------------
+# Rotate sparse file
+preptest test.log 24 1 0
+
+echo -n zero > test.log
+truncate -s 10M test.log
+echo x >> test.log
+
+cp test.log test.example
+
+SIZE_SPARSE_OLD=$(du test.log|awk '{print $1}')
+SIZE_OLD=$(du --apparent-size test.log|awk '{print $1}')
+$RLR test-config.24 --force
+SIZE_NEW=$(du --apparent-size test.log.1|awk '{print $1}')
+SIZE_SPARSE_NEW=$(du test.log.1|awk '{print $1}')
+
+if [ $SIZE_OLD != $SIZE_NEW ]; then
+       echo "Bad apparent size of sparse logs"
+       echo "test.log: $SIZE_OLD"
+       echo "test.log.1: $SIZE_NEW"
+       exit 3
+fi
+
+if [ $SIZE_SPARSE_OLD -gt 100 ] || [ $SIZE_SPARSE_NEW -gt 100 ]; then
+       echo "Bad size of sparse logs"
+       echo "test.log: $SIZE_SPARSE_OLD"
+       echo "test.log.1: $SIZE_SPARSE_NEW"
+       exit 3
+fi
+
+checkoutput <<EOF
+test.log 0
+test.log.1 0 zerox
+EOF
+
+cleanup 63
+
+# ------------------------------- Test 63 ------------------------------------
+# Rotate sparse file, no data should be lost when hole is in the end of file
+preptest test.log 24 1 0
+
+echo -n zero > test.log
+truncate -s 10M test.log
+
+cp test.log test.example
+
+SIZE_SPARSE_OLD=$(du test.log|awk '{print $1}')
+SIZE_OLD=$(du --apparent-size test.log|awk '{print $1}')
+$RLR test-config.24 --force
+SIZE_NEW=$(du --apparent-size test.log.1|awk '{print $1}')
+SIZE_SPARSE_NEW=$(du test.log.1|awk '{print $1}')
+
+if [ $SIZE_OLD != $SIZE_NEW ]; then
+    echo "Bad apparent size of sparse logs"
+    echo "test.log: $SIZE_OLD"
+    echo "test.log.1: $SIZE_NEW"
+    exit 3
+fi
+
+if [ $SIZE_SPARSE_OLD -gt 100 ] || [ $SIZE_SPARSE_NEW -gt 100 ]; then
+    echo "Bad size of sparse logs"
+    echo "test.log: $SIZE_SPARSE_OLD"
+    echo "test.log.1: $SIZE_SPARSE_NEW"
+    exit 3
+fi
+
+checkoutput <<EOF
+test.log 0
+test.log.1 0 zero
 EOF
 
 cleanup
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/test/test-config.60.in 
new/logrotate-3.9.1/test/test-config.60.in
--- old/logrotate-3.8.9/test/test-config.60.in  2015-02-13 07:11:20.000000000 
+0100
+++ new/logrotate-3.9.1/test/test-config.60.in  1970-01-01 01:00:00.000000000 
+0100
@@ -1,13 +0,0 @@
-create
-
-&DIR&/test.log &DIR&/test2.log {
-    size 1
-    rotate 5
-    sharedscripts
-    copytruncate
-    prerotate
-               if [ -e test.log ]; then 
-                       rm test.log
-               fi
-    endscript
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logrotate-3.8.9/test/test-config.61.in 
new/logrotate-3.9.1/test/test-config.61.in
--- old/logrotate-3.8.9/test/test-config.61.in  1970-01-01 01:00:00.000000000 
+0100
+++ new/logrotate-3.9.1/test/test-config.61.in  2015-04-03 09:39:35.000000000 
+0200
@@ -0,0 +1,8 @@
+create
+
+&DIR&/test.log {
+    daily
+    dateext
+    dateformat .%Y-%m-%d-%H
+    rotate 1
+}

++++++ logrotate-addextension.patch ++++++
--- /var/tmp/diff_new_pack.MQlKxd/_old  2015-07-05 17:57:34.000000000 +0200
+++ /var/tmp/diff_new_pack.MQlKxd/_new  2015-07-05 17:57:34.000000000 +0200
@@ -1,9 +1,9 @@
 Index: test/test
 ===================================================================
---- test/test.orig     2013-10-10 10:43:36.000000000 +0200
-+++ test/test  2013-11-07 21:46:37.112487860 +0100
-@@ -1511,4 +1511,27 @@
- test2.log.1 0 test2
+--- test/test.orig
++++ test/test
+@@ -1599,4 +1599,27 @@ test.log 0
+ test.log.1 0 zero
  EOF
  
 +# check rotation with extension appended to the filename
@@ -32,9 +32,9 @@
  cleanup
 Index: config.c
 ===================================================================
---- config.c.orig      2013-07-25 14:13:02.780567373 +0200
-+++ config.c   2013-07-25 14:13:04.196582364 +0200
-@@ -530,6 +530,7 @@ int readAllConfigPaths(const char **path
+--- config.c.orig
++++ config.c
+@@ -637,6 +637,7 @@ int readAllConfigPaths(const char **path
                .preremove = NULL,
                .logAddress = NULL,
                .extension = NULL,
@@ -42,7 +42,7 @@
                .compress_prog = NULL,
                .uncompress_prog = NULL,
                .compress_ext = NULL,
-@@ -1217,6 +1218,19 @@ static int readConfigFile(const char *co
+@@ -1220,6 +1221,19 @@ static int readConfigFile(const char *co
                                        message(MESS_DEBUG, "extension is now 
%s\n",
                                                newlog->extension);
  
@@ -64,9 +64,9 @@
  
 Index: logrotate.8
 ===================================================================
---- logrotate.8.orig   2013-07-25 14:13:02.780567373 +0200
-+++ logrotate.8        2013-07-25 14:13:04.196582364 +0200
-@@ -265,6 +265,15 @@ configured to be run by cron daily. You
+--- logrotate.8.orig
++++ logrotate.8
+@@ -283,6 +283,15 @@ configured to be run by cron daily. You
  and run \fIlogrotate\fR hourly to be able to really rotate logs hourly.
  
  .TP
@@ -84,9 +84,9 @@
  option (\fBifempty\fR is the default).
 Index: logrotate.c
 ===================================================================
---- logrotate.c.orig   2013-07-25 14:13:02.781567384 +0200
-+++ logrotate.c        2013-07-25 14:13:04.196582364 +0200
-@@ -964,6 +964,24 @@ int prerotateSingleLog(struct logInfo *l
+--- logrotate.c.orig
++++ logrotate.c
+@@ -1216,6 +1216,24 @@ int prerotateSingleLog(struct logInfo *l
  
      rotNames->baseName = strdup(ourBaseName(log->files[logNum]));
  
@@ -113,9 +113,9 @@
                (rotNames->
 Index: logrotate.h
 ===================================================================
---- logrotate.h.orig   2013-07-25 14:13:02.781567384 +0200
-+++ logrotate.h        2013-07-25 14:13:04.196582364 +0200
-@@ -44,6 +44,7 @@ struct logInfo {
+--- logrotate.h.orig
++++ logrotate.h
+@@ -54,6 +54,7 @@ struct logInfo {
      char *pre, *post, *first, *last, *preremove;
      char *logAddress;
      char *extension;
@@ -125,8 +125,8 @@
      char *compress_ext;
 Index: test/test-config.100.in
 ===================================================================
---- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ test/test-config.100.in    2013-07-25 14:13:04.196582364 +0200
+--- /dev/null
++++ test/test-config.100.in
 @@ -0,0 +1,7 @@
 +create
 +
@@ -137,8 +137,8 @@
 +}
 Index: test/test-config.101.in
 ===================================================================
---- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ test/test-config.101.in    2013-07-25 14:13:04.196582364 +0200
+--- /dev/null
++++ test/test-config.101.in
 @@ -0,0 +1,7 @@
 +create
 +


Reply via email to