-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathlinks.py
71 lines (57 loc) · 2.24 KB
/
links.py
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
import os
import struct
import platform
if platform.system() == 'Windows':
import win32file
import winioctlcon
import pywintypes
def link(src, dest):
try:
make_hardlink(dest, src)
except pywintypes.error, ex:
raise OSError(ex)
def symlink(src, dest):
try:
make_symlink(dest, src)
except pywintypes.error, ex:
raise OSError(ex)
else:
from os import link, symlink
def make_hardlink(dest_path, link_path):
win32file.CreateHardLink(dest_path, link_path)
def make_symlink(dest_path, link_path):
try:
win32file.CreateSymbolicLink(dest_path, link_path, 1) # SYMBOLIC_LINK_FLAG_DIRECTORY
except NotImplementedError:
make_reparse_point(dest_path, link_path)
# Reference: http://msdn.microsoft.com/en-us/library/cc232007%28PROT.13%29.aspx
def make_reparse_point(dest, link):
if dest[-1] == '/' or dest[-1] == '\\':
dest = dest[:len(dest)-1]
link = os.path.abspath(link)
if link[-1] == '/' or link[-1] == '\\':
link = link[:len(link)-1]
os.mkdir(dest)
dirh = win32file.CreateFile(dest, win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None,
win32file.OPEN_EXISTING, win32file.FILE_FLAG_OPEN_REPARSE_POINT| win32file.FILE_FLAG_BACKUP_SEMANTICS, None)
tag = 0xA0000003L
link = '\\??\\' + link
link = link.encode('utf-16')[2:]
datalen = len(link)
inp = struct.pack('LHHHHHH', tag, datalen+8+4, 0, 0, datalen, datalen+2, 0) + link + '\0\0\0\0'
try:
win32file.DeviceIoControl(dirh, winioctlcon.FSCTL_SET_REPARSE_POINT, inp, None)
except:
os.rmdir(dest)
raise
finally:
win32file.CloseHandle(dirh)
def print_info(dest):
if dest[-1] == '/' or dest[-1] == '\\':
dest = dest[:len(dest)-1]
dirh = win32file.CreateFile(dest, win32file.GENERIC_READ, 0, None,
win32file.OPEN_EXISTING, win32file.FILE_FLAG_OPEN_REPARSE_POINT| win32file.FILE_FLAG_BACKUP_SEMANTICS, None)
MAX_SIZE = 1024
buf = win32file.DeviceIoControl(dirh, winioctlcon.FSCTL_GET_REPARSE_POINT, None, MAX_SIZE)
print buf.encode('hex')
print repr(buf)