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
|
"""macostools - Various utility functions for MacOS.
mkalias(src, dst) - Create a finder alias 'dst' pointing to 'src'
copy(src, dst) - Full copy of 'src' to 'dst'
"""
from Carbon import Res
from Carbon import File, Files
import os
import sys
import MacOS
import time
try:
openrf = MacOS.openrf
except AttributeError:
# Backward compatibility
openrf = open
Error = 'macostools.Error'
BUFSIZ=0x80000 # Copy in 0.5Mb chunks
COPY_FLAGS = (Files.kIsStationary|Files.kNameLocked|Files.kHasBundle|
Files.kIsInvisible|Files.kIsAlias)
#
# Not guaranteed to be correct or stay correct (Apple doesn't tell you
# how to do this), but it seems to work.
#
def mkalias(src, dst, relative=None):
"""Create a finder alias"""
srcfsr = File.FSRef(src)
# The next line will fail under unix-Python if the destination
# doesn't exist yet. We should change this code to be fsref-based.
dstdir, dstname = os.path.split(dst)
if not dstdir: dstdir = os.curdir
dstdirfsr = File.FSRef(dstdir)
if relative:
relativefsr = File.FSRef(relative)
# ik mag er geen None in stoppen :-(
alias = File.FSNewAlias(relativefsr, srcfsr)
else:
alias = srcfsr.FSNewAliasMinimal()
dstfsr, dstfss = Res.FSCreateResourceFile(dstdirfsr, unicode(dstname),
File.FSGetResourceForkName())
h = Res.FSOpenResourceFile(dstfsr, File.FSGetResourceForkName(), 3)
resource = Res.Resource(alias.data)
resource.AddResource('alis', 0, '')
Res.CloseResFile(h)
dstfinfo = dstfss.FSpGetFInfo()
dstfinfo.Flags = dstfinfo.Flags|0x8000 # Alias flag
dstfss.FSpSetFInfo(dstfinfo)
def mkdirs(dst):
"""Make directories leading to 'dst' if they don't exist yet"""
if dst == '' or os.path.exists(dst):
return
head, tail = os.path.split(dst)
if os.sep == ':' and not ':' in head:
head = head + ':'
mkdirs(head)
os.mkdir(dst, 0777)
def touched(dst):
"""Tell the finder a file has changed. No-op on MacOSX."""
if sys.platform != 'mac': return
import warnings
warnings.filterwarnings("ignore", "macfs.*", DeprecationWarning, __name__)
import macfs
file_fss = macfs.FSSpec(dst)
vRefNum, dirID, name = file_fss.as_tuple()
dir_fss = macfs.FSSpec((vRefNum, dirID, ''))
crdate, moddate, bkdate = dir_fss.GetDates()
now = time.time()
if now == moddate:
now = now + 1
try:
dir_fss.SetDates(crdate, now, bkdate)
except macfs.error:
pass
def touched_ae(dst):
"""Tell the finder a file has changed"""
pardir = os.path.split(dst)[0]
if not pardir:
pardir = os.curdir
import Finder
f = Finder.Finder()
f.update(File.FSRef(pardir))
def copy(src, dst, createpath=0, copydates=1, forcetype=None):
"""Copy a file, including finder info, resource fork, etc"""
src = File.pathname(src)
dst = File.pathname(dst)
if createpath:
mkdirs(os.path.split(dst)[0])
ifp = open(src, 'rb')
ofp = open(dst, 'wb')
d = ifp.read(BUFSIZ)
while d:
ofp.write(d)
d = ifp.read(BUFSIZ)
ifp.close()
ofp.close()
ifp = openrf(src, '*rb')
ofp = openrf(dst, '*wb')
d = ifp.read(BUFSIZ)
while d:
ofp.write(d)
d = ifp.read(BUFSIZ)
ifp.close()
ofp.close()
srcfss = File.FSSpec(src)
dstfss = File.FSSpec(dst)
sf = srcfss.FSpGetFInfo()
df = dstfss.FSpGetFInfo()
df.Creator, df.Type = sf.Creator, sf.Type
if forcetype != None:
df.Type = forcetype
df.Flags = (sf.Flags & COPY_FLAGS)
dstfss.FSpSetFInfo(df)
if copydates:
srcfsr = File.FSRef(src)
dstfsr = File.FSRef(dst)
catinfo, _, _, _ = srcfsr.FSGetCatalogInfo(Files.kFSCatInfoAllDates)
dstfsr.FSSetCatalogInfo(Files.kFSCatInfoAllDates, catinfo)
touched(dstfss)
def copytree(src, dst, copydates=1):
"""Copy a complete file tree to a new destination"""
if os.path.isdir(src):
mkdirs(dst)
files = os.listdir(src)
for f in files:
copytree(os.path.join(src, f), os.path.join(dst, f), copydates)
else:
copy(src, dst, 1, copydates)
|