def tryCopyFile(sourceFilePath, destFilePath): if not sourceFilePath.startswith('\\\\'): sourceFilePath = u"\\\\?\\" + sourceFilePath if not destFilePath.startswith('\\\\'): destFilePath = u"\\\\?\\" + destFilePath if windll.kernel32.CopyFileW(sourceFilePath, destFilePath, False) == 0: errorCode = GetLastError() log.debugWarning("Unable to copy %s, error %d" % (sourceFilePath, errorCode)) if not os.path.exists(destFilePath): raise OSError("error %d copying %s to %s" % (errorCode, sourceFilePath, destFilePath)) tempPath = tempfile.mktemp(dir=os.path.dirname(destFilePath)) try: os.rename(destFilePath, tempPath) except (WindowsError, OSError): log.error("Failed to rename %s after failed overwrite" % destFilePath, exc_info=True) raise RetriableFailure( "Failed to rename %s after failed overwrite" % destFilePath) winKernel.moveFileEx(tempPath, None, winKernel.MOVEFILE_DELAY_UNTIL_REBOOT) if windll.kernel32.CopyFileW(sourceFilePath, destFilePath, False) == 0: errorCode = GetLastError() raise OSError("Unable to copy file %s to %s, error %d" % (sourceFilePath, destFilePath, errorCode))
def tryRemoveFile(path,numRetries=6,retryInterval=0.5,rebootOK=False): dirPath=os.path.dirname(path) tempPath=tempfile.mktemp(dir=dirPath) try: os.rename(path,tempPath) except (WindowsError,IOError): raise RetriableFailure("Failed to rename file %s before remove"%path) for count in range(numRetries): try: if os.path.isdir(tempPath): shutil.rmtree(tempPath) else: os.remove(tempPath) return except OSError: pass time.sleep(retryInterval) if rebootOK: log.debugWarning("Failed to delete file %s, marking for delete on reboot"%tempPath) try: # Use escapes in a unicode string instead of raw. # In a raw string the trailing slash escapes the closing quote leading to a python syntax error. pathQualifier=u"\\\\?\\" # #9847: Move file to None to delete it. winKernel.moveFileEx(pathQualifier+tempPath,None,winKernel.MOVEFILE_DELAY_UNTIL_REBOOT) except WindowsError: log.debugWarning("Failed to delete file %s, marking for delete on reboot"%tempPath, exc_info=True) return try: os.rename(tempPath,path) except: log.error("Unable to rename back to %s before retriable failier"%path) raise RetriableFailure("File %s could not be removed"%path)
def onPostponeButton(self, evt): finalDest = os.path.join(storeUpdatesDir, os.path.basename(self.destPath)) try: # #9825: behavior of os.rename(s) has changed (see https://bugs.python.org/issue28356). # In Python 2, os.renames did rename files across drives, no longer allowed in Python 3 (error 17 (cannot move files across drives) is raised). # This is prominent when trying to postpone an update for portable copy of NVDA if this runs from a USB flash drive or another internal storage device. # Therefore use kernel32::MoveFileEx with copy allowed (0x2) flag set. winKernel.moveFileEx(self.destPath, finalDest, winKernel.MOVEFILE_COPY_ALLOWED) except: log.debugWarning("Unable to rename the file from {} to {}".format( self.destPath, finalDest), exc_info=True) gui.messageBox( # Translators: The message when a downloaded update file could not be preserved. _("Unable to postpone update."), # Translators: The title of the message when a downloaded update file could not be preserved. _("Error"), wx.OK | wx.ICON_ERROR) finalDest = self.destPath state["pendingUpdateFile"] = finalDest state["pendingUpdateVersion"] = self.version state["pendingUpdateAPIVersion"] = self.apiVersion state["pendingUpdateBackCompatToAPIVersion"] = self.backCompatTo # Postponing an update indicates that the user is likely interested in getting a reminder. # Therefore, clear the dontRemindVersion. state["dontRemindVersion"] = None saveState() self.EndModal(wx.ID_CLOSE)
def FaultTolerantFile(name): '''Used to write out files in a more fault tolerant way. A temporary file is used, and replaces the file `name' when the context manager scope ends and the the context manager __exit__ is called. This means writing out the complete file can be performed with less concern of corrupting the original file if the process is interrupted by windows shutting down. `name` must be unicode. Usage: with FaultTolerantFile("myFile.txt") as f: f.write("This is a test") This creates a temporary file, and the writes actually happen on this temp file. At the end of the `with` block, when `f` goes out of context the temporary file is closed and, this temporary file replaces "myFile.txt" ''' if not isinstance(name, text_type): raise TypeError("name must be an unicode string") dirpath, filename = os.path.split(name) with NamedTemporaryFile(dir=dirpath, prefix=filename, suffix='.tmp', delete=False) as f: log.debug(f.name) yield f f.flush() os.fsync(f) f.close() winKernel.moveFileEx(f.name, name, winKernel.MOVEFILE_REPLACE_EXISTING)