|
@@ -331,92 +331,90 @@ class Archiver:
|
|
def _process(self, archive, cache, matcher, exclude_caches, exclude_if_present,
|
|
def _process(self, archive, cache, matcher, exclude_caches, exclude_if_present,
|
|
keep_tag_files, skip_inodes, path, restrict_dev,
|
|
keep_tag_files, skip_inodes, path, restrict_dev,
|
|
read_special=False, dry_run=False):
|
|
read_special=False, dry_run=False):
|
|
|
|
+ """
|
|
|
|
+ Process *path* recursively according to the various parameters.
|
|
|
|
+
|
|
|
|
+ This should only raise on critical errors. Per-item errors must be handled within this method.
|
|
|
|
+ """
|
|
if not matcher.match(path):
|
|
if not matcher.match(path):
|
|
return
|
|
return
|
|
|
|
|
|
try:
|
|
try:
|
|
- st = os.lstat(path)
|
|
|
|
- except OSError as e:
|
|
|
|
- self.print_warning('%s: %s', path, e)
|
|
|
|
- return
|
|
|
|
- if (st.st_ino, st.st_dev) in skip_inodes:
|
|
|
|
- return
|
|
|
|
- # Entering a new filesystem?
|
|
|
|
- if restrict_dev is not None and st.st_dev != restrict_dev:
|
|
|
|
- return
|
|
|
|
- status = None
|
|
|
|
- # Ignore if nodump flag is set
|
|
|
|
- if has_lchflags and (st.st_flags & stat.UF_NODUMP):
|
|
|
|
- return
|
|
|
|
- if stat.S_ISREG(st.st_mode):
|
|
|
|
- if not dry_run:
|
|
|
|
- try:
|
|
|
|
- status = archive.process_file(path, st, cache, self.ignore_inode)
|
|
|
|
- except BackupOSError as e:
|
|
|
|
- status = 'E'
|
|
|
|
- self.print_warning('%s: %s', path, e)
|
|
|
|
- elif stat.S_ISDIR(st.st_mode):
|
|
|
|
- tag_paths = dir_is_tagged(path, exclude_caches, exclude_if_present)
|
|
|
|
- if tag_paths:
|
|
|
|
- if keep_tag_files and not dry_run:
|
|
|
|
- archive.process_dir(path, st)
|
|
|
|
- for tag_path in tag_paths:
|
|
|
|
- self._process(archive, cache, matcher, exclude_caches, exclude_if_present,
|
|
|
|
- keep_tag_files, skip_inodes, tag_path, restrict_dev,
|
|
|
|
- read_special=read_special, dry_run=dry_run)
|
|
|
|
|
|
+ with backup_io():
|
|
|
|
+ st = os.lstat(path)
|
|
|
|
+ if (st.st_ino, st.st_dev) in skip_inodes:
|
|
return
|
|
return
|
|
- if not dry_run:
|
|
|
|
- status = archive.process_dir(path, st)
|
|
|
|
- try:
|
|
|
|
- entries = os.listdir(path)
|
|
|
|
- except OSError as e:
|
|
|
|
- status = 'E'
|
|
|
|
- self.print_warning('%s: %s', path, e)
|
|
|
|
- else:
|
|
|
|
|
|
+ # Entering a new filesystem?
|
|
|
|
+ if restrict_dev is not None and st.st_dev != restrict_dev:
|
|
|
|
+ return
|
|
|
|
+ status = None
|
|
|
|
+ # Ignore if nodump flag is set
|
|
|
|
+ if has_lchflags and (st.st_flags & stat.UF_NODUMP):
|
|
|
|
+ return
|
|
|
|
+ if stat.S_ISREG(st.st_mode):
|
|
|
|
+ if not dry_run:
|
|
|
|
+ status = archive.process_file(path, st, cache, self.ignore_inode)
|
|
|
|
+ elif stat.S_ISDIR(st.st_mode):
|
|
|
|
+ tag_paths = dir_is_tagged(path, exclude_caches, exclude_if_present)
|
|
|
|
+ if tag_paths:
|
|
|
|
+ if keep_tag_files and not dry_run:
|
|
|
|
+ archive.process_dir(path, st)
|
|
|
|
+ for tag_path in tag_paths:
|
|
|
|
+ self._process(archive, cache, matcher, exclude_caches, exclude_if_present,
|
|
|
|
+ keep_tag_files, skip_inodes, tag_path, restrict_dev,
|
|
|
|
+ read_special=read_special, dry_run=dry_run)
|
|
|
|
+ return
|
|
|
|
+ if not dry_run:
|
|
|
|
+ status = archive.process_dir(path, st)
|
|
|
|
+ with backup_io():
|
|
|
|
+ entries = os.listdir(path)
|
|
for filename in sorted(entries):
|
|
for filename in sorted(entries):
|
|
entry_path = os.path.normpath(os.path.join(path, filename))
|
|
entry_path = os.path.normpath(os.path.join(path, filename))
|
|
self._process(archive, cache, matcher, exclude_caches, exclude_if_present,
|
|
self._process(archive, cache, matcher, exclude_caches, exclude_if_present,
|
|
keep_tag_files, skip_inodes, entry_path, restrict_dev,
|
|
keep_tag_files, skip_inodes, entry_path, restrict_dev,
|
|
read_special=read_special, dry_run=dry_run)
|
|
read_special=read_special, dry_run=dry_run)
|
|
- elif stat.S_ISLNK(st.st_mode):
|
|
|
|
- if not dry_run:
|
|
|
|
- if not read_special:
|
|
|
|
- status = archive.process_symlink(path, st)
|
|
|
|
- else:
|
|
|
|
- try:
|
|
|
|
- st_target = os.stat(path)
|
|
|
|
- except OSError:
|
|
|
|
- special = False
|
|
|
|
|
|
+ elif stat.S_ISLNK(st.st_mode):
|
|
|
|
+ if not dry_run:
|
|
|
|
+ if not read_special:
|
|
|
|
+ status = archive.process_symlink(path, st)
|
|
else:
|
|
else:
|
|
- special = is_special(st_target.st_mode)
|
|
|
|
- if special:
|
|
|
|
- status = archive.process_file(path, st_target, cache)
|
|
|
|
|
|
+ try:
|
|
|
|
+ st_target = os.stat(path)
|
|
|
|
+ except OSError:
|
|
|
|
+ special = False
|
|
|
|
+ else:
|
|
|
|
+ special = is_special(st_target.st_mode)
|
|
|
|
+ if special:
|
|
|
|
+ status = archive.process_file(path, st_target, cache)
|
|
|
|
+ else:
|
|
|
|
+ status = archive.process_symlink(path, st)
|
|
|
|
+ elif stat.S_ISFIFO(st.st_mode):
|
|
|
|
+ if not dry_run:
|
|
|
|
+ if not read_special:
|
|
|
|
+ status = archive.process_fifo(path, st)
|
|
else:
|
|
else:
|
|
- status = archive.process_symlink(path, st)
|
|
|
|
- elif stat.S_ISFIFO(st.st_mode):
|
|
|
|
- if not dry_run:
|
|
|
|
- if not read_special:
|
|
|
|
- status = archive.process_fifo(path, st)
|
|
|
|
- else:
|
|
|
|
- status = archive.process_file(path, st, cache)
|
|
|
|
- elif stat.S_ISCHR(st.st_mode) or stat.S_ISBLK(st.st_mode):
|
|
|
|
- if not dry_run:
|
|
|
|
- if not read_special:
|
|
|
|
- status = archive.process_dev(path, st)
|
|
|
|
- else:
|
|
|
|
- status = archive.process_file(path, st, cache)
|
|
|
|
- elif stat.S_ISSOCK(st.st_mode):
|
|
|
|
- # Ignore unix sockets
|
|
|
|
- return
|
|
|
|
- elif stat.S_ISDOOR(st.st_mode):
|
|
|
|
- # Ignore Solaris doors
|
|
|
|
- return
|
|
|
|
- elif stat.S_ISPORT(st.st_mode):
|
|
|
|
- # Ignore Solaris event ports
|
|
|
|
- return
|
|
|
|
- else:
|
|
|
|
- self.print_warning('Unknown file type: %s', path)
|
|
|
|
- return
|
|
|
|
|
|
+ status = archive.process_file(path, st, cache)
|
|
|
|
+ elif stat.S_ISCHR(st.st_mode) or stat.S_ISBLK(st.st_mode):
|
|
|
|
+ if not dry_run:
|
|
|
|
+ if not read_special:
|
|
|
|
+ status = archive.process_dev(path, st)
|
|
|
|
+ else:
|
|
|
|
+ status = archive.process_file(path, st, cache)
|
|
|
|
+ elif stat.S_ISSOCK(st.st_mode):
|
|
|
|
+ # Ignore unix sockets
|
|
|
|
+ return
|
|
|
|
+ elif stat.S_ISDOOR(st.st_mode):
|
|
|
|
+ # Ignore Solaris doors
|
|
|
|
+ return
|
|
|
|
+ elif stat.S_ISPORT(st.st_mode):
|
|
|
|
+ # Ignore Solaris event ports
|
|
|
|
+ return
|
|
|
|
+ else:
|
|
|
|
+ self.print_warning('Unknown file type: %s', path)
|
|
|
|
+ return
|
|
|
|
+ except BackupOSError as e:
|
|
|
|
+ self.print_warning('%s: %s', path, e)
|
|
|
|
+ status = 'E'
|
|
# Status output
|
|
# Status output
|
|
if status is None:
|
|
if status is None:
|
|
if not dry_run:
|
|
if not dry_run:
|