Tryag File Manager
Home
||
Turbo Force
||
B-F Config_Cpanel
Current Path :
/
lib
/
python2.7
/
site-packages
/
slip
/
util
/
Or
Select Your Path :
Upload File :
New :
File
Dir
//lib/python2.7/site-packages/slip/util/files.py
# -*- coding: utf-8 -*- # # Copyright © 2009, 2010, 2012 Red Hat, Inc. # Authors: # Nils Philippsen <nils@redhat.com> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. """This module contains helper functions for dealing with files.""" __all__ = ["issamefile", "linkfile", "copyfile", "linkorcopyfile", "overwrite_safely"] import os import selinux import shutil import tempfile import errno BLOCKSIZE = 1024 def _issamefile(path1, path2): s1 = os.stat(path1) s2 = os.stat(path2) return os.path.samestat(s1, s2) def issamefile(path1, path2, catch_stat_exceptions=[]): """Check whether two paths point to the same file (i.e. are hardlinked).""" if catch_stat_exceptions == True: catch_stat_exceptions = Exception try: return _issamefile(path1, path2) except catch_stat_exceptions: return False def linkfile(srcpath, dstpath): """Hardlink srcpath to dstpath. Attempt to atomically replace dstpath if it exists.""" if issamefile(srcpath, dstpath, catch_stat_exceptions=OSError): return dstpath = os.path.abspath(dstpath) dstdname = os.path.dirname(dstpath) dstbname = os.path.basename(dstpath) hardlinked = False for attempt in xrange(tempfile.TMP_MAX): _dsttmp = tempfile.mktemp(prefix=dstbname + os.extsep, dir=dstdname) try: os.link(srcpath, _dsttmp) except OSError, e: if e.errno == errno.EEXIST: # try another name pass else: raise else: hardlinked = True break if hardlinked: os.rename(_dsttmp, dstpath) def copyfile(srcpath, dstpath, copy_mode_from_dst=True, run_restorecon=True): """Copy srcpath to dstpath. Abort operation if e.g. not enough space is available. Attempt to atomically replace dstpath if it exists.""" if issamefile(srcpath, dstpath, catch_stat_exceptions=OSError): return dstpath = os.path.abspath(dstpath) dstdname = os.path.dirname(dstpath) dstbname = os.path.basename(dstpath) srcfile = open(srcpath, "rb") dsttmpfile = tempfile.NamedTemporaryFile(prefix=dstbname + os.path.extsep, dir=dstdname, delete=False) mode_copied = False if copy_mode_from_dst: # attempt to copy mode from destination file (if it exists, # otherwise fall back to copying it from the source file below) try: shutil.copymode(dstpath, dsttmpfile.name) mode_copied = True except (shutil.Error, OSError): pass if not mode_copied: shutil.copymode(srcpath, dsttmpfile.name) data = None while data != "": data = srcfile.read(BLOCKSIZE) try: dsttmpfile.write(data) except: srcfile.close() dsttmpfile.close() os.unlink(dsttmpfile.name) raise srcfile.close() dsttmpfile.close() os.rename(dsttmpfile.name, dstpath) if run_restorecon and selinux.is_selinux_enabled() > 0: selinux.restorecon(dstpath) def linkorcopyfile(srcpath, dstpath, copy_mode_from_dst=True, run_restorecon=True): """First attempt to hardlink srcpath to dstpath, if hardlinking isn't possible, attempt copying srcpath to dstpath.""" try: linkfile(srcpath, dstpath) return except OSError, e: if e.errno not in (errno.EMLINK, errno.EPERM, errno.EXDEV): # don't bother copying raise else: # try copying pass copyfile(srcpath, dstpath, copy_mode_from_dst, run_restorecon) def symlink_atomically(srcpath, dstpath, force=False, preserve_context=True): """Create a symlink, optionally replacing dstpath atomically, optionally setting or preserving SELinux context.""" dstdname = os.path.dirname(dstpath) dstbname = os.path.basename(dstpath) run_restorecon = False ctx = None if preserve_context and selinux.is_selinux_enabled() <= 0: preserve_context = False else: try: ret, ctx = selinux.lgetfilecon(dstpath) if ret < 0: raise RuntimeError("getfilecon(%r) failed" % dstpath) except OSError, e: if e.errno == errno.ENOENT: run_restorecon = True else: raise if not force: os.symlink(srcpath, dstpath) if preserve_context: selinux.restorecon(dstpath) else: dsttmp = None for attempt in xrange(tempfile.TMP_MAX): _dsttmp = tempfile.mktemp(prefix=dstbname + os.extsep, dir=dstdname) try: os.symlink(srcpath, _dsttmp) except OSError, e: if e.errno == errno.EEXIST: # try again continue raise else: dsttmp = _dsttmp break if dsttmp is None: raise IOError(errno.EEXIST, "No suitable temporary symlink could be created.") if preserve_context and not run_restorecon: selinux.lsetfilecon(dsttmp, ctx) try: os.rename(dsttmp, dstpath) except: # clean up os.remove(dsttmp) raise if run_restorecon: selinux.restorecon(dstpath) def overwrite_safely(path, content, preserve_mode=True, preserve_context=True): """Safely overwrite a file by creating a temporary file in the same directory, writing it, moving it over the original file, eventually preserving file mode and SELinux context.""" path = os.path.realpath(path) dir_ = os.path.dirname(path) base = os.path.basename(path) fd = None f = None tmpname = None exists = os.path.exists(path) if preserve_context and selinux.is_selinux_enabled() <= 0: preserve_context = False try: fd, tmpname = tempfile.mkstemp(prefix=base + os.path.extsep, dir=dir_) if exists and preserve_mode: shutil.copymode(path, tmpname) if exists and preserve_context: ret, ctx = selinux.getfilecon(path) if ret < 0: raise RuntimeError("getfilecon(%r) failed" % path) f = os.fdopen(fd, "w") fd = None f.write(content) f.close() f = None os.rename(tmpname, path) if preserve_context: if exists: selinux.setfilecon(path, ctx) else: selinux.restorecon(path) finally: if f: f.close() elif fd: os.close(fd) if tmpname and os.path.isfile(tmpname): try: os.unlink(tmpname) except: pass