def extractTar(tmpdir, filepath): """ Extracts the indicated tar file to the indicated tmpdir. @param tmpdir: Temp directory to extract to. @param filepath: Path to tarfile to extract. @raise ValueError: If a path cannot be encoded properly. """ # pylint: disable=E1101 tmpdir = encodePath(tmpdir) filepath = encodePath(filepath) tar = tarfile.open(filepath) try: tar.format = tarfile.GNU_FORMAT except AttributeError: tar.posix = False for tarinfo in tar: tar.extract(tarinfo, tmpdir)
def _setLogfile(self, value): """ Property target used to set the logfile parameter. @raise ValueError: If the value cannot be encoded properly. """ if value is not None: if len(value) < 1: raise ValueError( "The logfile parameter must be a non-empty string.") self._logfile = encodePath(value)
def buildPath(components): """ Builds a complete path from a list of components. For instance, constructs C{"/a/b/c"} from C{["/a", "b", "c",]}. @param components: List of components. @returns: String path constructed from components. @raise ValueError: If a path cannot be encoded properly. """ path = components[0] for component in components[1:]: path = os.path.join(path, component) return encodePath(path)
def validateDevice(device, unittest=False): """ Validates a configured device. The device must be an absolute path, must exist, and must be writable. The unittest flag turns off validation of the device on disk. @param device: Filesystem device path. @param unittest: Indicates whether we're unit testing. @return: Device as a string, for instance C{"/dev/cdrw"} @raise ValueError: If the device value is invalid. @raise ValueError: If some path cannot be encoded properly. """ if device is None: raise ValueError("Device must be filled in.") device = encodePath(device) if not os.path.isabs(device): raise ValueError("Backup device must be an absolute path.") if not unittest and not os.path.exists(device): raise ValueError("Backup device must exist on disk.") if not unittest and not os.access(device, os.W_OK): raise ValueError("Backup device is not writable by the current user.") return device
def writeImage(self, imagePath): """ Writes this image to disk using the image path. @param imagePath: Path to write image out as @type imagePath: String representing a path on disk @raise IOError: If there is an error writing the image to disk. @raise ValueError: If there are no filesystem entries in the image @raise ValueError: If a path cannot be encoded properly. """ imagePath = encodePath(imagePath) if len(self.entries.keys()) == 0: raise ValueError("Image does not contain any entries.") args = self._buildWriteArgs(self.entries, imagePath) command = resolveCommand(MKISOFS_COMMAND) (result, output) = executeCommand(command, args, returnOutput=False) if result != 0: raise IOError( "Error (%d) executing mkisofs command to build image." % result)
def changeFileAge(filename, subtract=None): """ Changes a file age using the C{os.utime} function. @note: Some platforms don't seem to be able to set an age precisely. As a result, whereas we might have intended to set an age of 86400 seconds, we actually get an age of 86399.375 seconds. When util.calculateFileAge() looks at that the file, it calculates an age of 0.999992766204 days, which then gets truncated down to zero whole days. The tests get very confused. To work around this, I always subtract off one additional second as a fudge factor. That way, the file age will be I{at least} as old as requested later on. @param filename: File to operate on. @param subtract: Number of seconds to subtract from the current time. @raise ValueError: If a path cannot be encoded properly. """ filename = encodePath(filename) newTime = time.time() - 1 if subtract is not None: newTime -= subtract os.utime(filename, (newTime, newTime))
def removedir(tree): """ Recursively removes an entire directory. This is basically taken from an example on python.com. @param tree: Directory tree to remove. @raise ValueError: If a path cannot be encoded properly. """ tree = encodePath(tree) for root, dirs, files in os.walk(tree, topdown=False): for name in files: path = os.path.join(root, name) if os.path.islink(path): os.remove(path) elif os.path.isfile(path): os.remove(path) for name in dirs: path = os.path.join(root, name) if os.path.islink(path): os.remove(path) elif os.path.isdir(path): os.rmdir(path) os.rmdir(tree)
def initializeImage(self, newDisc, tmpdir, mediaLabel=None): """ Initializes the writer's associated ISO image. This method initializes the C{image} instance variable so that the caller can use the C{addImageEntry} method. Once entries have been added, the C{writeImage} method can be called with no arguments. @param newDisc: Indicates whether the disc should be re-initialized @type newDisc: Boolean true/false @param tmpdir: Temporary directory to use if needed @type tmpdir: String representing a directory path on disk @param mediaLabel: Media label to be applied to the image, if any @type mediaLabel: String, no more than 25 characters long """ self._image = _ImageProperties() self._image.newDisc = newDisc self._image.tmpdir = encodePath(tmpdir) self._image.mediaLabel = mediaLabel self._image.entries = {} # mapping from path to graft point (if any)
def addEntry(self, path, graftPoint=None, override=False, contentsOnly=False): """ Adds an individual file or directory into the ISO image. The path must exist and must be a file or a directory. By default, the entry will be placed into the image at the root directory, but this behavior can be overridden using the C{graftPoint} parameter or instance variable. You can use the C{contentsOnly} behavior to revert to the "original" C{mkisofs} behavior for adding directories, which is to add only the items within the directory, and not the directory itself. @note: Things get I{odd} if you try to add a directory to an image that will be written to a multisession disc, and the same directory already exists in an earlier session on that disc. Not all of the data gets written. You really wouldn't want to do this anyway, I guess. @note: An exception will be thrown if the path has already been added to the image, unless the C{override} parameter is set to C{True}. @note: The method C{graftPoints} parameter overrides the object-wide instance variable. If neither the method parameter or object-wide value is set, the path will be written at the image root. The graft point behavior is determined by the value which is in effect I{at the time this method is called}, so you I{must} set the object-wide value before calling this method for the first time, or your image may not be consistent. @note: You I{cannot} use the local C{graftPoint} parameter to "turn off" an object-wide instance variable by setting it to C{None}. Python's default argument functionality buys us a lot, but it can't make this method psychic. :) @param path: File or directory to be added to the image @type path: String representing a path on disk @param graftPoint: Graft point to be used when adding this entry @type graftPoint: String representing a graft point path, as described above @param override: Override an existing entry with the same path. @type override: Boolean true/false @param contentsOnly: Add directory contents only (standard C{mkisofs} behavior). @type contentsOnly: Boolean true/false @raise ValueError: If path is not a file or directory, or does not exist. @raise ValueError: If the path has already been added, and override is not set. @raise ValueError: If a path cannot be encoded properly. """ path = encodePath(path) if not override: if path in self.entries.keys(): raise ValueError("Path has already been added to the image.") if os.path.islink(path): raise ValueError("Path must not be a link.") if os.path.isdir(path): if graftPoint is not None: if contentsOnly: self.entries[path] = graftPoint else: self.entries[path] = os.path.join(graftPoint, os.path.basename(path)) elif self.graftPoint is not None: if contentsOnly: self.entries[path] = self.graftPoint else: self.entries[path] = os.path.join(self.graftPoint, os.path.basename(path)) else: if contentsOnly: self.entries[path] = None else: self.entries[path] = os.path.basename(path) elif os.path.isfile(path): if graftPoint is not None: self.entries[path] = graftPoint elif self.graftPoint is not None: self.entries[path] = self.graftPoint else: self.entries[path] = None else: raise ValueError("Path must be a file or a directory.")
def writeImage(self, imagePath=None, newDisc=False, writeMulti=True): """ Writes an ISO image to the media in the device. If C{newDisc} is passed in as C{True}, we assume that the entire disc will be re-created from scratch. Note that unlike C{CdWriter}, C{DvdWriter} does not blank rewritable media before reusing it; however, C{growisofs} is called such that the media will be re-initialized as needed. If C{imagePath} is passed in as C{None}, then the existing image configured with C{initializeImage()} will be used. Under these circumstances, the passed-in C{newDisc} flag will be ignored and the value passed in to C{initializeImage()} will apply instead. The C{writeMulti} argument is ignored. It exists for compatibility with the Cedar Backup image writer interface. @note: The image size indicated in the log ("Image size will be...") is an estimate. The estimate is conservative and is probably larger than the actual space that C{dvdwriter} will use. @param imagePath: Path to an ISO image on disk, or C{None} to use writer's image @type imagePath: String representing a path on disk @param newDisc: Indicates whether the disc should be re-initialized @type newDisc: Boolean true/false. @param writeMulti: Unused @type writeMulti: Boolean true/false @raise ValueError: If the image path is not absolute. @raise ValueError: If some path cannot be encoded properly. @raise IOError: If the media could not be written to for some reason. @raise ValueError: If no image is passed in and initializeImage() was not previously called """ if not writeMulti: logger.warn("writeMulti value of [%s] ignored.", writeMulti) if imagePath is None: if self._image is None: raise ValueError( "Must call initializeImage() before using this method with no image path." ) size = self.getEstimatedImageSize() logger.info("Image size will be %s (estimated).", displayBytes(size)) available = self.retrieveCapacity( entireDisc=self._image.newDisc).bytesAvailable if size > available: logger.error( "Image [%s] does not fit in available capacity [%s].", displayBytes(size), displayBytes(available)) raise IOError( "Media does not contain enough capacity to store image.") self._writeImage(self._image.newDisc, None, self._image.entries, self._image.mediaLabel) else: if not os.path.isabs(imagePath): raise ValueError("Image path must be absolute.") imagePath = encodePath(imagePath) self._writeImage(newDisc, imagePath, None)