Server IP : 195.201.23.43 / Your IP : 18.216.116.226 Web Server : Apache System : Linux webserver2.vercom.be 5.4.0-192-generic #212-Ubuntu SMP Fri Jul 5 09:47:39 UTC 2024 x86_64 User : kdecoratie ( 1041) PHP Version : 7.1.33-63+ubuntu20.04.1+deb.sury.org+1 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /sbin/ |
Upload File : |
#!/usr/bin/python3 # #Copyright (c) 2006, 2007, Olivier Sessink #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * The names of its contributors may not be used to endorse or # promote products derived from this software without specific # prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS #"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS #FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, #BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; #LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT #LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN #ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #POSSIBILITY OF SUCH DAMAGE. # from __future__ import print_function import sys if sys.version_info > (3, 0): #Python 3 from configparser import ConfigParser else: #Python 2 from ConfigParser import ConfigParser import os import string from stat import * import getopt import stat INIPREFIX='/etc/jailkit' LIBDIR='/usr/share/jailkit' sys.path.append(LIBDIR) import jk_lib def comparecontent(fileA, fileB): try: fA=open(fileA, 'rb') fB=open(fileB, 'rb') cont = 1 retval = 1 while (cont==1 and retval==1): bufA = fA.read(4096) bufB = fB.read(4096) if (bufA != bufB): retval = 0 if (len(bufA)==0): cont = 0 fA.close() fB.close() return retval except IOError: return 0 def comparemetadata(fileA, fileB, onlyifAisnewer=1, sbA=None, sbB=None): if (sbA==None): sbA = os.lstat(fileA) if (sbB==None): sbB = os.lstat(fileB) if (sbA[stat.ST_MTIME] > sbB[stat.ST_MTIME]): if (sbA[stat.ST_SIZE] != sbB[stat.ST_SIZE]): return 0 if (stat.S_ISLNK(sbA[stat.ST_MODE]) != stat.S_ISLNK(sbB[stat.ST_MODE])): return 0 if (stat.S_ISLNK(sbA[stat.ST_MODE])): if (os.readlink(fileA) != os.readlink(fileB)): return 0 return 1 def need_update(original, injail, origstatbuf=None): try : if (comparemetadata(original, injail,sbA=origstatbuf)==1): if (comparecontent(original, injail)==1): return 0 return 1 except OSError as e: errno, _ = e.args # files that do not have an original file obviously cannot be updated # but they need cleaning if (errno == 2): return 2 return 0 def find2update(jail, dir, skips, config, files2update=[],files2clean=[]): if (config['verbose'] == 1): print('scanning '+jail+dir) for file in os.listdir(jail+dir): # print('test if '+dir+file+' or '+jail+dir+file+' exists in ',skips) if ((dir+file in skips) or (jail+dir+file in skips)): print('skip '+jail+dir+file) else: try: sbuf = os.lstat(dir+file) if (stat.S_ISDIR(sbuf[stat.ST_MODE])): files2update, files2clean = find2update(jail, dir+file+'/', skips, config, files2update, files2clean) elif (stat.S_ISREG(sbuf[stat.ST_MODE])): if (config['verbose'] == 1): print('checking '+jail+dir+file+'') ret = need_update(dir+file, jail+dir+file, origstatbuf=sbuf) if (ret == 1): files2update.append(dir+file) elif (ret == 2): files2clean.append(dir+file) except OSError as e: errno, strerror = e.args if (errno == 2): if (os.path.isdir(jail+dir+file)): files2update, files2clean = find2update(jail, dir+file+'/', skips, config, files2update, files2clean) files2clean.append(dir+file) else: sys.stderr.write('ERROR: while checking if '+jail+dir+file+' needs to be updated: '+strerror+'\n') return files2update,files2clean def updatejail(jail, dirs, skips, config): jaillen = len(jail) allfiles = [] allcleans = [] for dir in dirs: if (dir[:jaillen] == jail): dir = dir[jaillen:] if (dir[-1:] != '/'): dir += '/' dirnoslash = dir[:-1] #print('test if '+dirnoslash+' or '+jail+dirnoslash+' exists in ',skips) if ((dirnoslash in skips) or (jail+dirnoslash in skips)): print('skip '+jail+dir) else: files = [] cleans = [] cdirs = [] try: files,cleans = find2update(jail, dir, skips, config, [],[]) except OSError as e: _, strerror = e.args sys.stderr.write('ERROR: while scanning dir '+jail+dir+': '+strerror+'\n') for file in files: if (config['dry-run'] == 1): allfiles.append(file) else: print('removing outdated file '+jail+file) try: os.unlink(jail+file) allfiles.append(file) except: sys.stderr.write('ERROR: failed to remove outdated file '+jail+file+'\n') for file in cleans: if (config['dry-run'] == 1): allcleans.append(file) else: if (os.path.isdir(jail+file)): cdirs.append(file) else: print('removing deprecated file '+jail+file) try: os.unlink(jail+file) allcleans.append(file) except: sys.stderr.write('ERROR: failed to remove deprecated file '+jail+file+'\n') for cdir in cdirs: if (config['dry-run'] == 1): allcleans.append(cdir) else: print('removing deprecated directory '+jail+file) try: os.rmdir(jail+cdir) allcleans.append(cdir) except: sys.stderr.write('ERROR: failed to remove deprecated directory '+jail+file+'\n') if (config['dry-run'] == 1): for file in allfiles: print('will update outdated file '+jail+file) for file in allcleans: print('will remove deprecated file '+jail+file) else: handled = jk_lib.copy_binaries_and_libs(jail,allfiles, 0, config['verbose'], try_hardlink=config['hardlink']) if (len(handled)>0): jk_lib.gen_library_cache(jail) def usage(): print('') print("Usage: "+sys.argv[0]+" [OPTIONS] [DIRECTORIES]") print('-h|--help : this message') print('-v|--verbose : give verbose output') print('-c|--configsection=: use options specified in section of config file') print('-j|--jail= : the jail to update') print('-d|--dry-run : show what will be done') print('-s|--skip= : skip file, option can be used multiple times') print('-k|--hardlink : use hardlinks if possible') print('') print('if no directories are specified, jk_update will scan /bin /usr /lib and /opt') print('') def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hvdj:s:kc:', ['help', 'verbose', 'dry-run', 'jail=', 'skip=', 'hardlink', 'configsection=']) except getopt.GetoptError: usage() sys.exit(1) config = {} config['verbose'] = 0 config['dry-run'] = 0 jail = None configsection = None dirs = [] skips = [] for o, a in opts: if o in ("-c", "--configsection"): configsection = a if o in ("-h", "--help"): usage() sys.exit() elif o in ("-v", "--verbose"): config['verbose'] = 1 elif o in ("-d", "--dry-run"): config['dry-run'] = 1 elif o in ("-s", "--skip"): # the name in skips will never have a slash, whether it is a file or a dir if (os.path.isdir(a) and (a[-1:] == '/')): tmp = a[:-1] else: tmp = a skips.append(tmp) elif o in ("-j", "--jail"): jail = a elif o in ("-k", "--hardlink"): config['hardlink'] = 1 if (jail != None and configsection != None): sys.stderr.write('ERROR: cannot specify both a jail and a configsection\n') sys.exit(21) if (jail == None and configsection == None): sys.stderr.write('ERROR: must at least specify a jail or a configsection using\n -j or --jail or -c or --configsection\n\n') sys.exit(1) if (len(args)>0): dirs = args if (configsection != None): cfile = INIPREFIX+'/jk_update.ini' jail = configsection cfg = ConfigParser() cfg.read(cfile) if (not cfg.has_section(configsection)): sys.stderr.write('ERROR: configfile '+cfile+' does not have a section called '+configsection+'\n') sys.exit(1) tmp = jk_lib.config_get_option_as_list(cfg,configsection,'skips') for entry in tmp: skips.append(entry) if (not config.has_key('hardlink') and cfg.has_option(configsection,'hardlink')): try: tmp = int(cfg.get(section,'hardlink')) config['hardlink'] = tmp except: pass tmp = jk_lib.config_get_option_as_list(cfg,configsection,'directories') for entry in tmp: dirs.append(entry) if (not config.has_key('hardlink')): config['hardlink'] = 0 if (jail[-1:]=='/'): jail = jail[:-1] if (dirs == None or len(dirs)==0): dirs = ['/bin/', '/lib/', '/usr/', '/opt/'] # all directories in 'skips' should be without slash newskips = [] for entry in skips: if (entry[-1] == '/'): newskips.append(entry[:-1]) else: newskips.append(entry) skips = newskips updatejail(jail, dirs, skips, config) if __name__ == "__main__": main()Private