1 """macostools - Various utility functions for MacOS. 2 3 mkalias(src, dst) - Create a finder alias 'dst' pointing to 'src' 4 copy(src, dst) - Full copy of 'src' to 'dst' 5 """ 6 7 from warnings import warnpy3k 8 warnpy3k("In 3.x, the macostools module is removed.", stacklevel=2) 9 10 from Carbon import Res 11 from Carbon import File, Files 12 import os 13 import errno 14 import MacOS 15 try: 16 openrf = MacOS.openrf 17 except AttributeError: 18 # Backward compatibility 19 openrf = open 20 21 Error = 'macostools.Error' 22 23 BUFSIZ=0x80000 # Copy in 0.5Mb chunks 24 25 COPY_FLAGS = (Files.kIsStationary|Files.kNameLocked|Files.kHasBundle| 26 Files.kIsInvisible|Files.kIsAlias) 27 28 # 29 # Not guaranteed to be correct or stay correct (Apple doesn't tell you 30 # how to do this), but it seems to work. 31 # 32 def mkalias(src, dst, relative=None): 33 """Create a finder alias""" 34 srcfsr = File.FSRef(src) 35 # The next line will fail under unix-Python if the destination 36 # doesn't exist yet. We should change this code to be fsref-based. 37 dstdir, dstname = os.path.split(dst) 38 if not dstdir: dstdir = os.curdir 39 dstdirfsr = File.FSRef(dstdir) 40 if relative: 41 relativefsr = File.FSRef(relative) 42 # ik mag er geen None in stoppen :-( 43 alias = File.FSNewAlias(relativefsr, srcfsr) 44 else: 45 alias = srcfsr.FSNewAliasMinimal() 46 47 dstfsr, dstfss = Res.FSCreateResourceFile(dstdirfsr, unicode(dstname), 48 File.FSGetResourceForkName()) 49 h = Res.FSOpenResourceFile(dstfsr, File.FSGetResourceForkName(), 3) 50 resource = Res.Resource(alias.data) 51 resource.AddResource('alis', 0, '') 52 Res.CloseResFile(h) 53 54 dstfinfo = dstfss.FSpGetFInfo() 55 dstfinfo.Flags = dstfinfo.Flags|0x8000 # Alias flag 56 dstfss.FSpSetFInfo(dstfinfo) 57 58 def mkdirs(dst): 59 """Make directories leading to 'dst' if they don't exist yet""" 60 if dst == '' or os.path.exists(dst): 61 return 62 head, tail = os.path.split(dst) 63 if os.sep == ':' and not ':' in head: 64 head = head + ':' 65 mkdirs(head) 66 67 try: 68 os.mkdir(dst, 0777) 69 except OSError, e: 70 # be happy if someone already created the path 71 if e.errno != errno.EEXIST: 72 raise 73 74 75 def touched(dst): 76 """Tell the finder a file has changed. No-op on MacOSX.""" 77 import warnings 78 warnings.warn("macostools.touched() has been deprecated", 79 DeprecationWarning, 2) 80 81 def touched_ae(dst): 82 """Tell the finder a file has changed""" 83 pardir = os.path.split(dst)[0] 84 if not pardir: 85 pardir = os.curdir 86 import Finder 87 f = Finder.Finder() 88 f.update(File.FSRef(pardir)) 89 90 def copy(src, dst, createpath=0, copydates=1, forcetype=None): 91 """Copy a file, including finder info, resource fork, etc""" 92 src = File.pathname(src) 93 dst = File.pathname(dst) 94 if createpath: 95 mkdirs(os.path.split(dst)[0]) 96 97 ifp = open(src, 'rb') 98 ofp = open(dst, 'wb') 99 d = ifp.read(BUFSIZ) 100 while d: 101 ofp.write(d) 102 d = ifp.read(BUFSIZ) 103 ifp.close() 104 ofp.close() 105 106 ifp = openrf(src, '*rb') 107 ofp = openrf(dst, '*wb') 108 d = ifp.read(BUFSIZ) 109 while d: 110 ofp.write(d) 111 d = ifp.read(BUFSIZ) 112 ifp.close() 113 ofp.close() 114 115 srcfss = File.FSSpec(src) 116 dstfss = File.FSSpec(dst) 117 sf = srcfss.FSpGetFInfo() 118 df = dstfss.FSpGetFInfo() 119 df.Creator, df.Type = sf.Creator, sf.Type 120 if forcetype is not None: 121 df.Type = forcetype 122 df.Flags = (sf.Flags & COPY_FLAGS) 123 dstfss.FSpSetFInfo(df) 124 if copydates: 125 srcfsr = File.FSRef(src) 126 dstfsr = File.FSRef(dst) 127 catinfo, _, _, _ = srcfsr.FSGetCatalogInfo(Files.kFSCatInfoAllDates) 128 dstfsr.FSSetCatalogInfo(Files.kFSCatInfoAllDates, catinfo) 129 130 def copytree(src, dst, copydates=1): 131 """Copy a complete file tree to a new destination""" 132 if os.path.isdir(src): 133 mkdirs(dst) 134 files = os.listdir(src) 135 for f in files: 136 copytree(os.path.join(src, f), os.path.join(dst, f), copydates) 137 else: 138 copy(src, dst, 1, copydates) 139