]> Frank Brehm's Git Trees - my-stuff/py-logrotate.git/commitdiff
Kompression außer externer Kompression fertig
authorFrank Brehm <frank@brehm-online.com>
Sat, 2 Jul 2011 13:27:56 +0000 (13:27 +0000)
committerFrank Brehm <frank@brehm-online.com>
Sat, 2 Jul 2011 13:27:56 +0000 (13:27 +0000)
git-svn-id: http://svn.brehm-online.com/svn/my-stuff/python/PyLogrotate/trunk@272 ec8d2aa5-1599-4edb-8739-2b3a1bc399aa

LogRotateConfig.py
LogRotateHandler.py
test/apache2

index 41947a83f0338f088d14380977a0032609b2c7e5..ea3e9d451915f288c864217d9cfe7bff498f3587 100755 (executable)
@@ -567,8 +567,8 @@ class LogrotateConfigurationReader(object):
         '''
         Checks the availability of the given compress command.
 
-        'internal_gzip' and 'internal_bzip2' are accepted as valid compress
-        commands for compressing with the appropriate python modules.
+        'internal_zip, 'internal_gzip' and 'internal_bzip2' are accepted as
+        valid compress commands for compressing with the appropriate python modules.
 
         @param command: command to validate (absolute or relative for
                         searching in standard search path)
@@ -582,6 +582,10 @@ class LogrotateConfigurationReader(object):
         _ = self.t.lgettext
         path_list = self._get_std_search_path(True)
 
+        match = re.search(r'^\s*internal[\-_\s]?zip\s*', command, re.IGNORECASE)
+        if match:
+            return 'internal_zip'
+
         match = re.search(r'^\s*internal[\-_\s]?gzip\s*', command, re.IGNORECASE)
         if match:
             return 'internal_gzip'
@@ -824,6 +828,8 @@ class LogrotateConfigurationReader(object):
                     if not self.new_log['compressext']:
                         if self.new_log['compresscmd'] == 'internal_gzip':
                             self.new_log['compressext'] = '.gz'
+                        elif self.new_log['compresscmd'] == 'internal_zip':
+                            self.new_log['compressext'] = '.zip'
                         elif self.new_log['compresscmd'] == 'internal_bzip2':
                             self.new_log['compressext'] = '.bz2'
                         else:
index ead7c7940b127dad795b5bf5deb823cd062a9d54..14b332ffd3ab5a4e62d13a641c3c8e4f6b8334d4 100755 (executable)
@@ -31,6 +31,7 @@ from datetime import datetime, timedelta
 import time
 import gzip
 import bz2
+import zipfile
 
 from LogRotateConfig import LogrotateConfigurationError
 from LogRotateConfig import LogrotateConfigurationReader
@@ -745,7 +746,7 @@ class LogrotateHandler(object):
 
         if definition['copytruncate'] or definition['copy']:
             # Copying logfile to target
-            msg = _("Copying file '%(from)s' => '%(to)'.") \
+            msg = _("Copying file '%(from)s' => '%(to)s'.") \
                     % {'from': file_from, 'to': file_to }
             self.logger.info(msg)
             if not self.test:
@@ -1175,7 +1176,8 @@ class LogrotateHandler(object):
                 self.logger.debug(msg)
             found_files = glob.glob(pattern) 
             for oldfile in found_files:
-                if os.path.samefile(oldfile, logfile):
+                oldfile = os.path.abspath(oldfile)
+                if oldfile == logfile:
                     continue
                 statinfo = os.stat(oldfile)
                 result[oldfile] = statinfo.st_mtime
@@ -1749,6 +1751,8 @@ class LogrotateHandler(object):
                 self._compress_internal_gzip(logfile, target)
             elif command == 'internal_bzip2':
                 self._compress_internal_bzip2(logfile, target)
+            elif command == 'internal_zip':
+                self._compress_internal_zip(logfile, target)
             else:
                 self._compress_external(logfile, target, command, compress_opts)
 
@@ -1760,7 +1764,7 @@ class LogrotateHandler(object):
         Compression of the given source file to the target file
         with an external command.
 
-        It raises a LogrotateHandlerError on some errors.
+        It raises a LogrotateHandlerError on uncoverable errors.
 
         @param source: the source file to compress
         @type source:  str
@@ -1788,6 +1792,199 @@ class LogrotateHandler(object):
                     % {'source': source, 'target': target, 'cmd': command}
             self.logger.debug(msg)
 
+    #------------------------------------------------------------
+    def _copy_file_metadata(self, target, source=None, statinfo=None):
+        '''
+        Copy all metadata (owner, permissions, timestamps a.s.o) from
+        a source file onto a target file.
+        The target file must be exists.
+        Either an existing source file (parameter 'source') or the
+        statinfo of a former existing file (parameter 'statinfo') must
+        be given.
+
+        It raises a LogrotateHandlerError on uncoverable errors.
+
+        @param target: filename of an existing target file or directory
+        @type target:  str
+        @param source: filename of an existing source file or directory
+                       or None, if statinfo was given,
+                       has precedence before a given statinfo
+        @type source:  str or None
+        @param statinfo: stat object from os.stat() or None, if source was given
+        @type statinfo:  stat-object or None
+
+        @return: success or not
+        @rtype:  bool
+        '''
+
+        _ = self.t.lgettext
+
+        if source is None and statinfo is None:
+            msg = _("Neither 'target' nor 'statinfo' was given on calling _copy_file_metadata().")
+            raise LogrotateHandlerError(msg)
+            return False
+
+        if not os.path.exists(target):
+            msg = _("File or directory '%s' doesn't exists.") % (target)
+            if self.test:
+                self.logger.info(msg)
+                return True
+            self.logger.error(msg)
+            return False
+
+        new_statinfo = statinfo
+        old_statinfo = os.stat(target)
+
+        msg = _("Copying all file metadata to target '%s' ...") % (target)
+        self.logger.info(msg)
+
+        if source is not None:
+
+            # a source object was given
+
+            if not os.path.exists(source):
+                msg = _("File or directory '%s' doesn't exists.") % (source)
+                self.logger.error(msg)
+                return False
+
+            new_statinfo = os.stat(source)
+
+            # Copying permissions and timestamps from source to target
+            if self.verbose > 1:
+                msg = _("Copying permissions and timestamps from source '%(src)s' to target '%(target)s'.") \
+                        % {'src': source, 'target': target}
+                self.logger.debug(msg)
+            if not self.test:
+                shutil.copystat(source, target)
+
+        else:
+
+            # a source statinfo was given
+
+            atime = new_statinfo.st_atime
+            mtime = new_statinfo.st_mtime
+            mode  = new_statinfo.st_mode
+
+            # Setting atime and mtime
+            if self.verbose > 1:
+                msg = _("Setting atime and mtime of target '%s'.") % (target)
+                self.logger.debug(msg)
+            if not self.test:
+                try:
+                    os.utime(target, (atime, mtime))
+                except OSError, e:
+                    msg = _("Error on setting times on target file '%(target)s': %(err)s") \
+                            % {'target': target, 'err': e.strerror}
+                    self.logger.warning(msg)
+                    return False
+
+            # Setting permissions
+            old_mode = old_statinfo.st_mode
+            if mode != old_mode:
+                if self.verbose > 1:
+                    msg = _("Setting permissions of '%(target)s' to %(mode)4o.") \
+                            % {'target': target, 'mode': new_mode}
+                    self.logger.info(msg)
+                if not self.test:
+                    try:
+                        os.chmod(target, mode)
+                    except OSError, e:
+                        msg = _("Error on chmod of '%(target)s': %(err)s") \
+                                % {'target': target, 'err': e.strerror}
+                        self.logger.warning(msg)
+                        return False
+
+        # Copying ownership from source to target
+        new_uid = new_statinfo.st_uid
+        new_gid = new_statinfo.st_gid
+        old_uid = old_statinfo.st_uid
+        old_gid = old_statinfo.st_gid
+
+        if (old_uid != new_uid) or (old_gid != new_gid):
+            if self.verbose > 1:
+                msg = _("Copying ownership from source to target.")
+                self.logger.debug(msg)
+            myuid = os.geteuid()
+            if myuid != 0:
+                msg = _("Only root may execute chown().")
+                if self.test:
+                    self.logger.info(msg)
+                    return True
+                else:
+                    self.logger.warning(msg)
+                    return False
+            if not self.test:
+                try:
+                    os.chown(target, old_uid, old_gid)
+                except OSError, e:
+                    msg = _("Error on chown of '%(file)s': %(err)s") \
+                            % {'file': target, 'err': e.strerror}
+                    self.logger.warning(msg)
+                    return False
+
+        return True
+
+    #------------------------------------------------------------
+    def _compress_internal_zip(self, source, target):
+        '''
+        Compression of the given source file to the target file
+        with the Python module zipfile.
+
+        It raises a LogrotateHandlerError on some errors.
+
+        @param source: the source file to compress
+        @type source:  str
+        @param target: the filename of the compressed file.
+        @type target:  str
+
+        @return: success or not
+        @rtype:  bool
+        '''
+
+        _ = self.t.lgettext
+
+        if self.verbose > 1:
+            msg = _("Compressing source '%(source)s' to target'%(target)s' with module zipfile.") \
+                    % {'source': source, 'target': target}
+            self.logger.debug(msg)
+
+        if not self.test:
+
+            # open target for writing
+            f_out = None
+            try:
+                f_out = zipfile.ZipFile(
+                            file=target,
+                            mode='w',
+                            compression=zipfile.ZIP_DEFLATED
+                )
+            except IOError, e:
+                msg = _("Error on open file '%(file)s' on writing: %(err)s") \
+                        % {'file': target, 'err': str(e)}
+                self.logger.error(msg)
+                return False
+
+            basename = os.path.basename(source)
+            f_out.write(source, basename)
+            f_out.close()
+
+        self._copy_file_metadata(source=source, target=target)
+
+        # And last, but not least, delete uncompressed file
+        if self.verbose > 1:
+            msg = _("Deleting uncompressed file '%s' ...") % (source)
+            self.logger.debug(msg)
+
+        if not self.test:
+            try:
+                os.remove(source)
+            except OSError, e:
+                msg = _("Error removing uncompressed file '%(file)s': %(msg)") \
+                        % {'file': source, 'msg': str(e) }
+                self.logger.error(msg)
+                return False
+
+        return True
 
     #------------------------------------------------------------
     def _compress_internal_gzip(self, source, target):
@@ -1844,32 +2041,7 @@ class LogrotateHandler(object):
             f_out.close()
             f_in.close()
 
-        # Copying permissions and timestamps from source to target
-        if self.verbose > 1:
-            msg = _("Copying permissions and timestamps from source to target.")
-            self.logger.debug(msg)
-        if not test_mode:
-            shutil.copystat(source, target)
-
-        # Copying ownership from source to target
-        statinfo = os.stat(source)
-        old_uid = statinfo.st_uid
-        old_gid = statinfo.st_gid
-        statinfo = os.stat(target)
-        new_uid = statinfo.st_uid
-        new_gid = statinfo.st_gid
-
-        if (old_uid != new_uid) or (old_gid != new_gid):
-            if self.verbose > 1:
-                msg = _("Copying ownershipfrom source to target.")
-                self.logger.debug(msg)
-            if not test_mode:
-                try:
-                    os.chown(target, old_uid, old_gid)
-                except OSError, e:
-                    msg = _("Error on chown of '%(file)s': %(err)s") \
-                            % {'file': target, 'err': e.strerror}
-                    self.logger.warning(msg)
+        self._copy_file_metadata(source=source, target=target)
 
         # And last, but not least, delete uncompressed file
         if self.verbose > 1:
@@ -1942,32 +2114,7 @@ class LogrotateHandler(object):
             f_out.close()
             f_in.close()
 
-        # Copying permissions and timestamps from source to target
-        if self.verbose > 1:
-            msg = _("Copying permissions and timestamps from source to target.")
-            self.logger.debug(msg)
-        if not test_mode:
-            shutil.copystat(source, target)
-
-        # Copying ownership from source to target
-        statinfo = os.stat(source)
-        old_uid = statinfo.st_uid
-        old_gid = statinfo.st_gid
-        statinfo = os.stat(target)
-        new_uid = statinfo.st_uid
-        new_gid = statinfo.st_gid
-
-        if (old_uid != new_uid) or (old_gid != new_gid):
-            if self.verbose > 1:
-                msg = _("Copying ownershipfrom source to target.")
-                self.logger.debug(msg)
-            if not test_mode:
-                try:
-                    os.chown(target, old_uid, old_gid)
-                except OSError, e:
-                    msg = _("Error on chown of '%(file)s': %(err)s") \
-                            % {'file': target, 'err': e.strerror}
-                    self.logger.warning(msg)
+        self._copy_file_metadata(source=source, target=target)
 
         # And last, but not least, delete uncompressed file
         if self.verbose > 1:
index e3d0880220097d01f27cb4c277a527f8b671a5d3..2d728088668433d234ef59ba45996c2e43a924a9 100644 (file)
@@ -11,6 +11,7 @@ endscript
 
 /home/frank/devel/Python/PyLogrotate/test/log/access_log {
     compress
+    create
     missingok
     notifempty
     sharedscripts
@@ -27,7 +28,8 @@ endscript
 
 /home/frank/devel/Python/PyLogrotate/test/log/error_log {
     compress
-    compresscmd internal_bzip2
+    compresscmd internal_zip
+    copytruncate
     nomissingok
     notifempty
     sharedscripts
@@ -44,6 +46,7 @@ endscript
 
 /home/frank/devel/Python/PyLogrotate/test/log/*.log {
     compress
+    create
     missingok
     notifempty
     sharedscripts