28 |
""" |
""" |
29 |
|
|
30 |
import errno, os |
import errno, os |
31 |
import Globals, log, TempFile, selection |
import Globals, log, TempFile, selection, robust |
32 |
|
|
33 |
class FSAbilities: |
class FSAbilities: |
34 |
"""Store capabilities of given file system""" |
"""Store capabilities of given file system""" |
35 |
chars_to_quote = None # Hold characters not allowable in file names |
chars_to_quote = None # Hold characters not allowable in file names |
36 |
|
case_sensitive = None # True if "foobar" and "FoObAr" are different files |
37 |
ownership = None # True if chown works on this filesystem |
ownership = None # True if chown works on this filesystem |
38 |
acls = None # True if access control lists supported |
acls = None # True if access control lists supported |
39 |
eas = None # True if extended attributes supported |
eas = None # True if extended attributes supported |
95 |
('High-bit permissions', self.high_perms)]) |
('High-bit permissions', self.high_perms)]) |
96 |
add_boolean_list([('Access control lists', self.acls), |
add_boolean_list([('Access control lists', self.acls), |
97 |
('Extended attributes', self.eas), |
('Extended attributes', self.eas), |
98 |
|
('Case sensitivity', self.case_sensitive), |
99 |
('Mac OS X style resource forks', |
('Mac OS X style resource forks', |
100 |
self.resource_forks), |
self.resource_forks), |
101 |
('Mac OS X Finder information', self.carbonfile)]) |
('Mac OS X Finder information', self.carbonfile)]) |
119 |
self.set_acls(rp) |
self.set_acls(rp) |
120 |
self.set_resource_fork_readonly(rp) |
self.set_resource_fork_readonly(rp) |
121 |
self.set_carbonfile() |
self.set_carbonfile() |
122 |
|
self.set_case_sensitive_readonly(rp) |
123 |
return self |
return self |
124 |
|
|
125 |
def init_readwrite(self, rbdir, use_ctq_file = 1, |
def init_readwrite(self, rbdir, use_ctq_file = 1, |
236 |
lower_a.delete() |
lower_a.delete() |
237 |
upper_a.setdata() |
upper_a.setdata() |
238 |
assert not upper_a.lstat() |
assert not upper_a.lstat() |
239 |
return 0 |
self.case_sensitive = 0 |
240 |
else: |
else: |
241 |
upper_a.delete() |
upper_a.delete() |
242 |
return 1 |
self.case_sensitive = 1 |
243 |
|
return self.case_sensitive |
244 |
|
|
245 |
def supports_unusual_chars(): |
def supports_unusual_chars(): |
246 |
"""Test handling of several chars sometimes not supported""" |
"""Test handling of several chars sometimes not supported""" |
289 |
log.Log("ACLs not supported by filesystem at %s" % (rp.path,), 4) |
log.Log("ACLs not supported by filesystem at %s" % (rp.path,), 4) |
290 |
self.acls = 0 |
self.acls = 0 |
291 |
else: self.acls = 1 |
else: self.acls = 1 |
292 |
|
|
293 |
|
def set_case_sensitive_readonly(self, rp): |
294 |
|
"""Determine if directory at rp is case sensitive without writing""" |
295 |
|
def find_letter(subdir): |
296 |
|
"""Find a (subdir_rp, dirlist) with a letter in it, or None |
297 |
|
|
298 |
|
Recurse down the directory, looking for any file that has |
299 |
|
a letter in it. Return the pair (rp, [list of filenames]) |
300 |
|
where the list is of the directory containing rp. |
301 |
|
|
302 |
|
""" |
303 |
|
l = robust.listrp(subdir) |
304 |
|
for filename in l: |
305 |
|
if filename != filename.swapcase(): |
306 |
|
return (subdir, l, filename) |
307 |
|
for filename in l: |
308 |
|
dir_rp = subdir.append(filename) |
309 |
|
if dir_rp.isdir(): |
310 |
|
subsearch = find_letter(dir_rp) |
311 |
|
if subsearch: return subsearch |
312 |
|
return None |
313 |
|
|
314 |
|
def test_triple(dir_rp, dirlist, filename): |
315 |
|
"""Return 1 if filename shows system case sensitive""" |
316 |
|
letter_rp = dir_rp.append(filename) |
317 |
|
assert letter_rp.lstat(), letter_rp |
318 |
|
swapped = filename.swapcase() |
319 |
|
if swapped in dirlist: return 1 |
320 |
|
|
321 |
|
swapped_rp = dir_rp.append(swapped) |
322 |
|
if swapped_rp.lstat(): return 0 |
323 |
|
return 1 |
324 |
|
|
325 |
|
triple = find_letter(rp) |
326 |
|
if not triple: |
327 |
|
log.Log("Warning: could not determine case sensitivity of " |
328 |
|
"source directory at\n " + rp.path + "\n" |
329 |
|
"because we can't find any files with letters in them.\n" |
330 |
|
"It will be treated as case sensitive.", 2) |
331 |
|
self.case_sensitive = 1 |
332 |
|
return |
333 |
|
|
334 |
|
self.case_sensitive = test_triple(*triple) |
335 |
|
|
336 |
def set_eas(self, rp, write): |
def set_eas(self, rp, write): |
337 |
"""Set extended attributes from rp. Tests writing if write is true.""" |
"""Set extended attributes from rp. Tests writing if write is true.""" |
338 |
assert Globals.local_connection is rp.conn |
assert Globals.local_connection is rp.conn |