This file is indexed.

/usr/share/pyshared/duplicity/misc.py is in duplicity 0.6.18-0ubuntu3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2002 Ben Escoto <ben@emerose.org>
# Copyright 2007 Kenneth Loafman <kenneth@loafman.com>
#
# This file is part of duplicity.
#
# Duplicity 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.
#
# Duplicity 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 duplicity; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

"""Miscellaneous classes and methods"""

import os

from duplicity import log


class MiscError(Exception):
    """Signifies a miscellaneous error..."""
    pass


class FileVolumeWriter:
    """Split up an incoming fileobj into multiple volumes on disk

    This class can also be used as an iterator.  It returns the
    filenames of the files it writes.

    """
    volume_size = 50 * 1024 * 1024
    blocksize = 64 * 1024
    def __init__(self, infp, file_prefix):
        """FileVolumeWriter initializer

        infp is a file object opened for reading.  It will be closed
        at end.  file_prefix is the full path of the volumes that will
        be written.  If more than one is required, it will be appended
        with .1, .2, etc.

        """
        self.infp = infp
        self.prefix = file_prefix
        self.current_index = 1
        self.finished = None # set to true when completely done
        self.buffer = "" # holds data that belongs in next volume

    def get_initial_buf(self):
        """Get first value of buffer, from self.buffer or infp"""
        if self.buffer:
            buf = self.buffer
            self.buffer = ""
            return buf
        else:
            return self.infp.read(self.blocksize)

    def write_volume(self, outfp):
        """Write self.volume_size bytes from self.infp to outfp

        Return None if we have reached end of infp without reaching
        volume size, and false otherwise.

        """
        bytes_written, buf = 0, self.get_initial_buf()
        while len(buf) + bytes_written <= self.volume_size:
            if not buf:
                # reached end of input
                outfp.close()
                return None
            if len(buf) + bytes_written > self.volume_size:
                break
            outfp.write(buf)
            bytes_written += len(buf)
            buf = self.infp.read(self.blocksize)

        remainder = self.volume_size - bytes_written
        assert remainder < len(buf)
        outfp.write(buf[:remainder])
        outfp.close()
        self.buffer = buf[remainder:]
        return 1

    def next(self):
        """Write next file, return filename"""
        if self.finished:
            raise StopIteration

        filename = "%s.%d" % (self.prefix, self.current_index)
        log.Info(_("Starting to write %s") % filename)
        outfp = open(filename, "wb")

        if not self.write_volume(outfp):
            # end of input
            self.finished = 1
            if self.current_index == 1:
                # special case first index
                log.Notice(_("One only volume required.\n"
                             "Renaming %s to %s") % (filename, self.prefix))
                os.rename(filename, self.prefix)
                return self.prefix
        else:
            self.current_index += 1
        return filename

    def __iter__(self):
        return self


class BufferedFile:
    """Buffer file open for reading, so reads will happen in fixed sizes

    This is currently used to buffer a GzipFile, because that class
    apparently doesn't respond well to arbitrary read sizes.

    """
    def __init__(self, fileobj, blocksize = 32 * 1024):
        self.fileobj = fileobj
        self.buffer = ""
        self.blocksize = blocksize

    def read(self, length = -1):
        """Return length bytes, or all if length < 0"""
        if length < 0:
            while 1:
                buf = self.fileobj.read(self.blocksize)
                if not buf:
                    break
                self.buffer += buf
            real_length = len(self.buffer)
        else:
            while len(self.buffer) < length:
                buf = self.fileobj.read(self.blocksize)
                if not buf:
                    break
                self.buffer += buf
            real_length = min(length, len(self.buffer))
        result = self.buffer[:real_length]
        self.buffer = self.buffer[real_length:]
        return result

    def close(self):
        self.fileobj.close()


def copyfileobj(infp, outfp, byte_count = -1):
    """Copy byte_count bytes from infp to outfp, or all if byte_count < 0

    Returns the number of bytes actually written (may be less than
    byte_count if find eof.  Does not close either fileobj.

    """
    blocksize = 64 * 1024
    bytes_written = 0
    if byte_count < 0:
        while 1:
            buf = infp.read(blocksize)
            if not buf:
                break
            bytes_written += len(buf)
            outfp.write(buf)
    else:
        while bytes_written + blocksize <= byte_count:
            buf = infp.read(blocksize)
            if not buf:
                break
            bytes_written += len(buf)
            outfp.write(buf)
        buf = infp.read(byte_count - bytes_written)
        bytes_written += len(buf)
        outfp.write(buf)
    return bytes_written

def copyfileobj_close(infp, outfp):
    """Copy infp to outfp, closing afterwards"""
    copyfileobj(infp, outfp)
    if infp.close():
        raise MiscError("Error closing input file")
    if outfp.close():
        raise MiscError("Error closing output file")