Index: Lib/tarfile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tarfile.py,v retrieving revision 1.32 diff -p -b -B -U10 -u -r1.32 tarfile.py --- tarfile.py 27 Aug 2005 10:07:56 -0000 1.32 +++ tarfile.py 30 Aug 2005 07:27:37 -0000 @@ -55,20 +55,35 @@ if sys.platform == 'mac': # handling. In many places it is assumed a simple substitution of / by the # local os.path.sep is good enough to convert pathnames, but this does not # work with the mac rooted:path:name versus :nonrooted:path:name syntax raise ImportError, "tarfile does not work for platform==mac" try: import grp, pwd except ImportError: grp = pwd = None +# This module has problems using os.stat() if the filenames use direct device +# addressing on Windows systems. For example: +# \\?\GLOBALROOT\Device\HarddiskVolume1\TEMP\1.txt +# As a solution we can use win32file.GetFileAttributesEx(). +try: + import win32file +except ImportError: + win32file = None + +# In version 2.3 win32file.FILE_ATTRIBUTE_DIRECTORY is not defined, but it is +# defined in 2.4 +if win32file: + if (sys.version_info[0] == 2) & (sys.version_info[1] == 3): + win32file.FILE_ATTRIBUTE_DIRECTORY = 16 + # from tarfile import * __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] #--------------------------------------------------------- # tar constants #--------------------------------------------------------- NUL = "\0" # the null character BLOCKSIZE = 512 # length of processing blocks RECORDSIZE = BLOCKSIZE * 20 # length of records MAGIC = "ustar" # magic tar string @@ -1129,34 +1144,52 @@ class TarFile(object): arcname = name arcname = normpath(arcname) drv, arcname = os.path.splitdrive(arcname) while arcname[0:1] == "/": arcname = arcname[1:] # Now, fill the TarInfo object with # information specific for the file. tarinfo = TarInfo() - # Use os.stat or os.lstat, depending on platform + # Use win32file.GetFileAttributesEx if the module exists, otherwise + # use os.stat or os.lstat, depending on platform # and if symlinks shall be resolved. if fileobj is None: + if win32file: + fattr=win32file.GetFileAttributesEx(name,0) + mode = 0 + if (fattr[0] & win32file.FILE_ATTRIBUTE_DIRECTORY) == win32file.FILE_ATTRIBUTE_DIRECTORY: + mode += S_IFDIR # directory + else: + mode += S_IFREG # regular file + if (fattr[0] & win32file.FILE_ATTRIBUTE_READONLY) == win32file.FILE_ATTRIBUTE_READONLY: + mode += (TUREAD + TGREAD + TOREAD) # read only + else: + mode += (TUREAD + TUWRITE + TGREAD + TGWRITE + TOREAD + TOWRITE) # writable + # Fields: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid, st_size, st_atime, st_mtime, st_ctime + # Fields st_dev and st_nlink are not used here, so they are set to 0 + statres = (mode, 0, 0, 0, 0, 0, fattr[4], int(fattr[2]), int(fattr[3]), int(fattr[1])) + else: if hasattr(os, "lstat") and not self.dereference: statres = os.lstat(name) else: statres = os.stat(name) + else: statres = os.fstat(fileobj.fileno()) linkname = "" - stmd = statres.st_mode + stmd = statres[stat.ST_MODE] + if stat.S_ISREG(stmd): - inode = (statres.st_ino, statres.st_dev) + inode = (statres[stat.ST_INO], statres[stat.ST_DEV]) if inode in self.inodes and not self.dereference: # Is it a hardlink to an already # archived file? type = LNKTYPE linkname = self.inodes[inode] else: # The inode is added only if its valid. # For win32 it is always 0. type = REGTYPE if inode[0]: @@ -1174,29 +1207,30 @@ class TarFile(object): type = CHRTYPE elif stat.S_ISBLK(stmd): type = BLKTYPE else: return None # Fill the TarInfo object with all # information we can get. tarinfo.name = arcname tarinfo.mode = stmd - tarinfo.uid = statres.st_uid - tarinfo.gid = statres.st_gid + tarinfo.uid = statres[stat.ST_UID] + tarinfo.gid = statres[stat.ST_GID] if stat.S_ISREG(stmd): - tarinfo.size = statres.st_size + tarinfo.size = statres[stat.ST_SIZE] else: tarinfo.size = 0L - tarinfo.mtime = statres.st_mtime + tarinfo.mtime = statres[stat.ST_MTIME] tarinfo.type = type tarinfo.linkname = linkname + if pwd: try: tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] except KeyError: pass if grp: try: tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] except KeyError: pass