##// END OF EJS Templates
posixfile_nt: set closed early...
Matt Mackall -
r5840:c67dfc4e default
parent child Browse files
Show More
@@ -1,329 +1,329 b''
1 # util_win32.py - utility functions that use win32 API
1 # util_win32.py - utility functions that use win32 API
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of
6 # This software may be used and distributed according to the terms of
7 # the GNU General Public License, incorporated herein by reference.
7 # the GNU General Public License, incorporated herein by reference.
8
8
9 # Mark Hammond's win32all package allows better functionality on
9 # Mark Hammond's win32all package allows better functionality on
10 # Windows. this module overrides definitions in util.py. if not
10 # Windows. this module overrides definitions in util.py. if not
11 # available, import of this module will fail, and generic code will be
11 # available, import of this module will fail, and generic code will be
12 # used.
12 # used.
13
13
14 import win32api
14 import win32api
15
15
16 from i18n import _
16 from i18n import _
17 import errno, os, pywintypes, win32con, win32file, win32process
17 import errno, os, pywintypes, win32con, win32file, win32process
18 import cStringIO, winerror
18 import cStringIO, winerror
19 import osutil
19 import osutil
20 from win32com.shell import shell,shellcon
20 from win32com.shell import shell,shellcon
21
21
22 class WinError:
22 class WinError:
23 winerror_map = {
23 winerror_map = {
24 winerror.ERROR_ACCESS_DENIED: errno.EACCES,
24 winerror.ERROR_ACCESS_DENIED: errno.EACCES,
25 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
25 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
26 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
26 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
27 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
27 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
28 winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
28 winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
29 winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
29 winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
30 winerror.ERROR_BAD_COMMAND: errno.EIO,
30 winerror.ERROR_BAD_COMMAND: errno.EIO,
31 winerror.ERROR_BAD_DEVICE: errno.ENODEV,
31 winerror.ERROR_BAD_DEVICE: errno.ENODEV,
32 winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
32 winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
33 winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
33 winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
34 winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
34 winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
35 winerror.ERROR_BAD_LENGTH: errno.EINVAL,
35 winerror.ERROR_BAD_LENGTH: errno.EINVAL,
36 winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
36 winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
37 winerror.ERROR_BAD_PIPE: errno.EPIPE,
37 winerror.ERROR_BAD_PIPE: errno.EPIPE,
38 winerror.ERROR_BAD_UNIT: errno.ENODEV,
38 winerror.ERROR_BAD_UNIT: errno.ENODEV,
39 winerror.ERROR_BAD_USERNAME: errno.EINVAL,
39 winerror.ERROR_BAD_USERNAME: errno.EINVAL,
40 winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
40 winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
41 winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
41 winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
42 winerror.ERROR_BUSY: errno.EBUSY,
42 winerror.ERROR_BUSY: errno.EBUSY,
43 winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
43 winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
44 winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
44 winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
45 winerror.ERROR_CANNOT_MAKE: errno.EACCES,
45 winerror.ERROR_CANNOT_MAKE: errno.EACCES,
46 winerror.ERROR_CANTOPEN: errno.EIO,
46 winerror.ERROR_CANTOPEN: errno.EIO,
47 winerror.ERROR_CANTREAD: errno.EIO,
47 winerror.ERROR_CANTREAD: errno.EIO,
48 winerror.ERROR_CANTWRITE: errno.EIO,
48 winerror.ERROR_CANTWRITE: errno.EIO,
49 winerror.ERROR_CRC: errno.EIO,
49 winerror.ERROR_CRC: errno.EIO,
50 winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
50 winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
51 winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
51 winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
52 winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
52 winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
53 winerror.ERROR_DIRECTORY: errno.EINVAL,
53 winerror.ERROR_DIRECTORY: errno.EINVAL,
54 winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
54 winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
55 winerror.ERROR_DISK_CHANGE: errno.EIO,
55 winerror.ERROR_DISK_CHANGE: errno.EIO,
56 winerror.ERROR_DISK_FULL: errno.ENOSPC,
56 winerror.ERROR_DISK_FULL: errno.ENOSPC,
57 winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
57 winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
58 winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
58 winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
59 winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
59 winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
60 winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
60 winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
61 winerror.ERROR_FILE_EXISTS: errno.EEXIST,
61 winerror.ERROR_FILE_EXISTS: errno.EEXIST,
62 winerror.ERROR_FILE_INVALID: errno.ENODEV,
62 winerror.ERROR_FILE_INVALID: errno.ENODEV,
63 winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
63 winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
64 winerror.ERROR_GEN_FAILURE: errno.EIO,
64 winerror.ERROR_GEN_FAILURE: errno.EIO,
65 winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
65 winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
66 winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
66 winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
67 winerror.ERROR_INVALID_ACCESS: errno.EACCES,
67 winerror.ERROR_INVALID_ACCESS: errno.EACCES,
68 winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
68 winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
69 winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
69 winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
70 winerror.ERROR_INVALID_DATA: errno.EINVAL,
70 winerror.ERROR_INVALID_DATA: errno.EINVAL,
71 winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
71 winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
72 winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
72 winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
73 winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
73 winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
74 winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
74 winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
75 winerror.ERROR_INVALID_HANDLE: errno.EBADF,
75 winerror.ERROR_INVALID_HANDLE: errno.EBADF,
76 winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
76 winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
77 winerror.ERROR_INVALID_NAME: errno.EINVAL,
77 winerror.ERROR_INVALID_NAME: errno.EINVAL,
78 winerror.ERROR_INVALID_OWNER: errno.EINVAL,
78 winerror.ERROR_INVALID_OWNER: errno.EINVAL,
79 winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
79 winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
80 winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
80 winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
81 winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
81 winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
82 winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
82 winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
83 winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
83 winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
84 winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
84 winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
85 winerror.ERROR_IO_DEVICE: errno.EIO,
85 winerror.ERROR_IO_DEVICE: errno.EIO,
86 winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
86 winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
87 winerror.ERROR_LOCKED: errno.EBUSY,
87 winerror.ERROR_LOCKED: errno.EBUSY,
88 winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
88 winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
89 winerror.ERROR_LOGON_FAILURE: errno.EACCES,
89 winerror.ERROR_LOGON_FAILURE: errno.EACCES,
90 winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
90 winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
91 winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
91 winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
92 winerror.ERROR_MORE_DATA: errno.EPIPE,
92 winerror.ERROR_MORE_DATA: errno.EPIPE,
93 winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
93 winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
94 winerror.ERROR_NOACCESS: errno.EFAULT,
94 winerror.ERROR_NOACCESS: errno.EFAULT,
95 winerror.ERROR_NONE_MAPPED: errno.EINVAL,
95 winerror.ERROR_NONE_MAPPED: errno.EINVAL,
96 winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
96 winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
97 winerror.ERROR_NOT_READY: errno.EAGAIN,
97 winerror.ERROR_NOT_READY: errno.EAGAIN,
98 winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
98 winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
99 winerror.ERROR_NO_DATA: errno.EPIPE,
99 winerror.ERROR_NO_DATA: errno.EPIPE,
100 winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
100 winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
101 winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
101 winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
102 winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
102 winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
103 winerror.ERROR_OPEN_FAILED: errno.EIO,
103 winerror.ERROR_OPEN_FAILED: errno.EIO,
104 winerror.ERROR_OPEN_FILES: errno.EBUSY,
104 winerror.ERROR_OPEN_FILES: errno.EBUSY,
105 winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
105 winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
106 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
106 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
107 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
107 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
108 winerror.ERROR_PATH_BUSY: errno.EBUSY,
108 winerror.ERROR_PATH_BUSY: errno.EBUSY,
109 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
109 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
110 winerror.ERROR_PIPE_BUSY: errno.EBUSY,
110 winerror.ERROR_PIPE_BUSY: errno.EBUSY,
111 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
111 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
112 winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
112 winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
113 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
113 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
114 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
114 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
115 winerror.ERROR_READ_FAULT: errno.EIO,
115 winerror.ERROR_READ_FAULT: errno.EIO,
116 winerror.ERROR_SEEK: errno.EIO,
116 winerror.ERROR_SEEK: errno.EIO,
117 winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
117 winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
118 winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
118 winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
119 winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
119 winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
120 winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
120 winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
121 winerror.ERROR_SWAPERROR: errno.ENOENT,
121 winerror.ERROR_SWAPERROR: errno.ENOENT,
122 winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
122 winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
123 winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
123 winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
124 winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
124 winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
125 winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
125 winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
126 winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
126 winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
127 winerror.ERROR_WRITE_FAULT: errno.EIO,
127 winerror.ERROR_WRITE_FAULT: errno.EIO,
128 winerror.ERROR_WRITE_PROTECT: errno.EROFS,
128 winerror.ERROR_WRITE_PROTECT: errno.EROFS,
129 }
129 }
130
130
131 def __init__(self, err):
131 def __init__(self, err):
132 self.win_errno, self.win_function, self.win_strerror = err
132 self.win_errno, self.win_function, self.win_strerror = err
133 if self.win_strerror.endswith('.'):
133 if self.win_strerror.endswith('.'):
134 self.win_strerror = self.win_strerror[:-1]
134 self.win_strerror = self.win_strerror[:-1]
135
135
136 class WinIOError(WinError, IOError):
136 class WinIOError(WinError, IOError):
137 def __init__(self, err, filename=None):
137 def __init__(self, err, filename=None):
138 WinError.__init__(self, err)
138 WinError.__init__(self, err)
139 IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
139 IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
140 self.win_strerror)
140 self.win_strerror)
141 self.filename = filename
141 self.filename = filename
142
142
143 class WinOSError(WinError, OSError):
143 class WinOSError(WinError, OSError):
144 def __init__(self, err):
144 def __init__(self, err):
145 WinError.__init__(self, err)
145 WinError.__init__(self, err)
146 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
146 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
147 self.win_strerror)
147 self.win_strerror)
148
148
149 def os_link(src, dst):
149 def os_link(src, dst):
150 # NB will only succeed on NTFS
150 # NB will only succeed on NTFS
151 try:
151 try:
152 win32file.CreateHardLink(dst, src)
152 win32file.CreateHardLink(dst, src)
153 except pywintypes.error, details:
153 except pywintypes.error, details:
154 raise WinOSError(details)
154 raise WinOSError(details)
155
155
156 def nlinks(pathname):
156 def nlinks(pathname):
157 """Return number of hardlinks for the given file."""
157 """Return number of hardlinks for the given file."""
158 try:
158 try:
159 fh = win32file.CreateFile(pathname,
159 fh = win32file.CreateFile(pathname,
160 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
160 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
161 None, win32file.OPEN_EXISTING, 0, None)
161 None, win32file.OPEN_EXISTING, 0, None)
162 res = win32file.GetFileInformationByHandle(fh)
162 res = win32file.GetFileInformationByHandle(fh)
163 fh.Close()
163 fh.Close()
164 return res[7]
164 return res[7]
165 except pywintypes.error:
165 except pywintypes.error:
166 return os.lstat(pathname).st_nlink
166 return os.lstat(pathname).st_nlink
167
167
168 def testpid(pid):
168 def testpid(pid):
169 '''return True if pid is still running or unable to
169 '''return True if pid is still running or unable to
170 determine, False otherwise'''
170 determine, False otherwise'''
171 try:
171 try:
172 handle = win32api.OpenProcess(
172 handle = win32api.OpenProcess(
173 win32con.PROCESS_QUERY_INFORMATION, False, pid)
173 win32con.PROCESS_QUERY_INFORMATION, False, pid)
174 if handle:
174 if handle:
175 status = win32process.GetExitCodeProcess(handle)
175 status = win32process.GetExitCodeProcess(handle)
176 return status == win32con.STILL_ACTIVE
176 return status == win32con.STILL_ACTIVE
177 except pywintypes.error, details:
177 except pywintypes.error, details:
178 return details[0] != winerror.ERROR_INVALID_PARAMETER
178 return details[0] != winerror.ERROR_INVALID_PARAMETER
179 return True
179 return True
180
180
181 def system_rcpath_win32():
181 def system_rcpath_win32():
182 '''return default os-specific hgrc search path'''
182 '''return default os-specific hgrc search path'''
183 proc = win32api.GetCurrentProcess()
183 proc = win32api.GetCurrentProcess()
184 try:
184 try:
185 # This will fail on windows < NT
185 # This will fail on windows < NT
186 filename = win32process.GetModuleFileNameEx(proc, 0)
186 filename = win32process.GetModuleFileNameEx(proc, 0)
187 except:
187 except:
188 filename = win32api.GetModuleFileName(0)
188 filename = win32api.GetModuleFileName(0)
189 # Use mercurial.ini found in directory with hg.exe
189 # Use mercurial.ini found in directory with hg.exe
190 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
190 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
191 if os.path.isfile(progrc):
191 if os.path.isfile(progrc):
192 return [progrc]
192 return [progrc]
193 # else look for a system rcpath in the registry
193 # else look for a system rcpath in the registry
194 try:
194 try:
195 value = win32api.RegQueryValue(
195 value = win32api.RegQueryValue(
196 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
196 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
197 rcpath = []
197 rcpath = []
198 for p in value.split(os.pathsep):
198 for p in value.split(os.pathsep):
199 if p.lower().endswith('mercurial.ini'):
199 if p.lower().endswith('mercurial.ini'):
200 rcpath.append(p)
200 rcpath.append(p)
201 elif os.path.isdir(p):
201 elif os.path.isdir(p):
202 for f, kind in osutil.listdir(p):
202 for f, kind in osutil.listdir(p):
203 if f.endswith('.rc'):
203 if f.endswith('.rc'):
204 rcpath.append(os.path.join(p, f))
204 rcpath.append(os.path.join(p, f))
205 return rcpath
205 return rcpath
206 except pywintypes.error:
206 except pywintypes.error:
207 return []
207 return []
208
208
209 def user_rcpath_win32():
209 def user_rcpath_win32():
210 '''return os-specific hgrc search path to the user dir'''
210 '''return os-specific hgrc search path to the user dir'''
211 userdir = os.path.expanduser('~')
211 userdir = os.path.expanduser('~')
212 if sys.getwindowsversion() != 2 and userdir == '~':
212 if sys.getwindowsversion() != 2 and userdir == '~':
213 # We are on win < nt: fetch the APPDATA directory location and use
213 # We are on win < nt: fetch the APPDATA directory location and use
214 # the parent directory as the user home dir.
214 # the parent directory as the user home dir.
215 appdir = shell.SHGetPathFromIDList(
215 appdir = shell.SHGetPathFromIDList(
216 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
216 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
217 userdir = os.path.dirname(appdir)
217 userdir = os.path.dirname(appdir)
218 return os.path.join(userdir, 'mercurial.ini')
218 return os.path.join(userdir, 'mercurial.ini')
219
219
220 class posixfile_nt(object):
220 class posixfile_nt(object):
221 '''file object with posix-like semantics. on windows, normal
221 '''file object with posix-like semantics. on windows, normal
222 files can not be deleted or renamed if they are open. must open
222 files can not be deleted or renamed if they are open. must open
223 with win32file.FILE_SHARE_DELETE. this flag does not exist on
223 with win32file.FILE_SHARE_DELETE. this flag does not exist on
224 windows < nt, so do not use this class there.'''
224 windows < nt, so do not use this class there.'''
225
225
226 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
226 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
227 # but does not work at all. wrap win32 file api instead.
227 # but does not work at all. wrap win32 file api instead.
228
228
229 def __init__(self, name, mode='rb'):
229 def __init__(self, name, mode='rb'):
230 self.closed = False
231 self.name = name
232 self.mode = mode
230 access = 0
233 access = 0
231 if 'r' in mode or '+' in mode:
234 if 'r' in mode or '+' in mode:
232 access |= win32file.GENERIC_READ
235 access |= win32file.GENERIC_READ
233 if 'w' in mode or 'a' in mode or '+' in mode:
236 if 'w' in mode or 'a' in mode or '+' in mode:
234 access |= win32file.GENERIC_WRITE
237 access |= win32file.GENERIC_WRITE
235 if 'r' in mode:
238 if 'r' in mode:
236 creation = win32file.OPEN_EXISTING
239 creation = win32file.OPEN_EXISTING
237 elif 'a' in mode:
240 elif 'a' in mode:
238 creation = win32file.OPEN_ALWAYS
241 creation = win32file.OPEN_ALWAYS
239 else:
242 else:
240 creation = win32file.CREATE_ALWAYS
243 creation = win32file.CREATE_ALWAYS
241 try:
244 try:
242 self.handle = win32file.CreateFile(name,
245 self.handle = win32file.CreateFile(name,
243 access,
246 access,
244 win32file.FILE_SHARE_READ |
247 win32file.FILE_SHARE_READ |
245 win32file.FILE_SHARE_WRITE |
248 win32file.FILE_SHARE_WRITE |
246 win32file.FILE_SHARE_DELETE,
249 win32file.FILE_SHARE_DELETE,
247 None,
250 None,
248 creation,
251 creation,
249 win32file.FILE_ATTRIBUTE_NORMAL,
252 win32file.FILE_ATTRIBUTE_NORMAL,
250 0)
253 0)
251 except pywintypes.error, err:
254 except pywintypes.error, err:
252 raise WinIOError(err, name)
255 raise WinIOError(err, name)
253 self.closed = False
254 self.name = name
255 self.mode = mode
256
256
257 def __iter__(self):
257 def __iter__(self):
258 for line in self.read().splitlines(True):
258 for line in self.read().splitlines(True):
259 yield line
259 yield line
260
260
261 def read(self, count=-1):
261 def read(self, count=-1):
262 try:
262 try:
263 cs = cStringIO.StringIO()
263 cs = cStringIO.StringIO()
264 while count:
264 while count:
265 wincount = int(count)
265 wincount = int(count)
266 if wincount == -1:
266 if wincount == -1:
267 wincount = 1048576
267 wincount = 1048576
268 val, data = win32file.ReadFile(self.handle, wincount)
268 val, data = win32file.ReadFile(self.handle, wincount)
269 if not data: break
269 if not data: break
270 cs.write(data)
270 cs.write(data)
271 if count != -1:
271 if count != -1:
272 count -= len(data)
272 count -= len(data)
273 return cs.getvalue()
273 return cs.getvalue()
274 except pywintypes.error, err:
274 except pywintypes.error, err:
275 raise WinIOError(err)
275 raise WinIOError(err)
276
276
277 def write(self, data):
277 def write(self, data):
278 try:
278 try:
279 if 'a' in self.mode:
279 if 'a' in self.mode:
280 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
280 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
281 nwrit = 0
281 nwrit = 0
282 while nwrit < len(data):
282 while nwrit < len(data):
283 val, nwrit = win32file.WriteFile(self.handle, data)
283 val, nwrit = win32file.WriteFile(self.handle, data)
284 data = data[nwrit:]
284 data = data[nwrit:]
285 except pywintypes.error, err:
285 except pywintypes.error, err:
286 raise WinIOError(err)
286 raise WinIOError(err)
287
287
288 def seek(self, pos, whence=0):
288 def seek(self, pos, whence=0):
289 try:
289 try:
290 win32file.SetFilePointer(self.handle, int(pos), whence)
290 win32file.SetFilePointer(self.handle, int(pos), whence)
291 except pywintypes.error, err:
291 except pywintypes.error, err:
292 raise WinIOError(err)
292 raise WinIOError(err)
293
293
294 def tell(self):
294 def tell(self):
295 try:
295 try:
296 return win32file.SetFilePointer(self.handle, 0,
296 return win32file.SetFilePointer(self.handle, 0,
297 win32file.FILE_CURRENT)
297 win32file.FILE_CURRENT)
298 except pywintypes.error, err:
298 except pywintypes.error, err:
299 raise WinIOError(err)
299 raise WinIOError(err)
300
300
301 def close(self):
301 def close(self):
302 if not self.closed:
302 if not self.closed:
303 self.handle = None
303 self.handle = None
304 self.closed = True
304 self.closed = True
305
305
306 def flush(self):
306 def flush(self):
307 try:
307 try:
308 win32file.FlushFileBuffers(self.handle)
308 win32file.FlushFileBuffers(self.handle)
309 except pywintypes.error, err:
309 except pywintypes.error, err:
310 raise WinIOError(err)
310 raise WinIOError(err)
311
311
312 def truncate(self, pos=0):
312 def truncate(self, pos=0):
313 try:
313 try:
314 win32file.SetFilePointer(self.handle, int(pos),
314 win32file.SetFilePointer(self.handle, int(pos),
315 win32file.FILE_BEGIN)
315 win32file.FILE_BEGIN)
316 win32file.SetEndOfFile(self.handle)
316 win32file.SetEndOfFile(self.handle)
317 except pywintypes.error, err:
317 except pywintypes.error, err:
318 raise WinIOError(err)
318 raise WinIOError(err)
319
319
320 getuser_fallback = win32api.GetUserName
320 getuser_fallback = win32api.GetUserName
321
321
322 def set_signal_handler_win32():
322 def set_signal_handler_win32():
323 """Register a termination handler for console events including
323 """Register a termination handler for console events including
324 CTRL+C. python signal handlers do not work well with socket
324 CTRL+C. python signal handlers do not work well with socket
325 operations.
325 operations.
326 """
326 """
327 def handler(event):
327 def handler(event):
328 win32process.ExitProcess(1)
328 win32process.ExitProcess(1)
329 win32api.SetConsoleCtrlHandler(handler)
329 win32api.SetConsoleCtrlHandler(handler)
General Comments 0
You need to be logged in to leave comments. Login now