summaryrefslogtreecommitdiffstats
path: root/Mac/Lib/macostools.py
blob: 8822ab8f9787ce61ed8377c0719893123bb57bce (plain)
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
"""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'
"""

import macfs
from Carbon import Res
import os
from MACFS import *
import MacOS
import time
try:
	openrf = MacOS.openrf
except AttributeError:
	# Backward compatability
	openrf = open

Error = 'macostools.Error'

BUFSIZ=0x80000		# Copy in 0.5Mb chunks

#
# 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"""
	srcfss = macfs.FSSpec(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.
	dstfss = macfs.FSSpec(dst)
	if relative:
		relativefss = macfs.FSSpec(relative)
		# ik mag er geen None in stoppen :-(
		alias = srcfss.NewAlias(relativefss)
	else:
		alias = srcfss.NewAlias()
	
	if os.path.isdir(src):
		cr, tp = 'MACS', 'fdrp'
	else:
		cr, tp = srcfss.GetCreatorType()
	
	Res.FSpCreateResFile(dstfss, cr, tp, -1)
	h = Res.FSpOpenResFile(dstfss, 3)
	resource = Res.Resource(alias.data)
	resource.AddResource('alis', 0, '')
	Res.CloseResFile(h)
	
	dstfinfo = dstfss.GetFInfo()
	dstfinfo.Flags = dstfinfo.Flags|0x8000    # Alias flag
	dstfss.SetFInfo(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"""
	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"""
	import Finder
	f = Finder.Finder()
	file_fss = macfs.FSSpec(dst)
	vRefNum, dirID, name = file_fss.as_tuple()
	dir_fss = macfs.FSSpec((vRefNum, dirID, ''))
	f.update(dir_fss)
	
def copy(src, dst, createpath=0, copydates=1, forcetype=None):
	"""Copy a file, including finder info, resource fork, etc"""
	if hasattr(src, 'as_pathname'):
		src = src.as_pathname()
	if hasattr(dst, 'as_pathname'):
		dst = dst.as_pathname()
	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 = macfs.FSSpec(src)
	dstfss = macfs.FSSpec(dst)
	sf = srcfss.GetFInfo()
	df = dstfss.GetFInfo()
	df.Creator, df.Type = sf.Creator, sf.Type
	if forcetype != None:
		df.Type = forcetype
	df.Flags = (sf.Flags & (kIsStationary|kNameLocked|kHasBundle|kIsInvisible|kIsAlias))
	dstfss.SetFInfo(df)
	if copydates:
		crdate, mddate, bkdate = srcfss.GetDates()
		dstfss.SetDates(crdate, mddate, bkdate)
	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)