flashpod 0.2.1__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. {flashpod-0.2.1 → flashpod-0.2.2}/PKG-INFO +1 -1
  2. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/platform/windows.py +56 -13
  3. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod.egg-info/PKG-INFO +1 -1
  4. {flashpod-0.2.1 → flashpod-0.2.2}/pyproject.toml +1 -1
  5. {flashpod-0.2.1 → flashpod-0.2.2}/LICENSE +0 -0
  6. {flashpod-0.2.1 → flashpod-0.2.2}/README.md +0 -0
  7. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/__init__.py +0 -0
  8. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/__main__.py +0 -0
  9. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/cli.py +0 -0
  10. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/contrib/99-flashpod-firewire-ipod.rules +0 -0
  11. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/fat32.py +0 -0
  12. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/fatfs.py +0 -0
  13. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/firmware/firmware.json +0 -0
  14. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/ipod_flash.py +0 -0
  15. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/itunesdb.py +0 -0
  16. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/platform/__init__.py +0 -0
  17. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/platform/base.py +0 -0
  18. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/platform/linux.py +0 -0
  19. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/platform/macos.py +0 -0
  20. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod/resources.py +0 -0
  21. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod.egg-info/SOURCES.txt +0 -0
  22. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod.egg-info/dependency_links.txt +0 -0
  23. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod.egg-info/entry_points.txt +0 -0
  24. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod.egg-info/requires.txt +0 -0
  25. {flashpod-0.2.1 → flashpod-0.2.2}/flashpod.egg-info/top_level.txt +0 -0
  26. {flashpod-0.2.1 → flashpod-0.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flashpod
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Command-line iPod sync + card-flashing tooling for early FireWire-era iPods, pure Python
5
5
  Author: David Barnhart
6
6
  License-Expression: MIT
@@ -35,7 +35,38 @@ GENERIC_WRITE = 0x40000000
35
35
  FILE_SHARE_READ = 0x00000001
36
36
  FILE_SHARE_WRITE = 0x00000002
37
37
  OPEN_EXISTING = 3
38
- INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value if False else (2 ** 64 - 1)
38
+ # INVALID_HANDLE_VALUE is (HANDLE)-1, so its unsigned value is pointer-sized:
39
+ # 2**64-1 on 64-bit Python, 2**32-1 on 32-bit. Derive it rather than assuming.
40
+ INVALID_HANDLE_VALUE = (1 << (8 * ctypes.sizeof(ctypes.c_void_p))) - 1
41
+
42
+
43
+ def _k32():
44
+ """kernel32 with correct prototypes for the handle APIs.
45
+
46
+ Declaring these matters: ctypes defaults restype to ``c_int``, but a HANDLE
47
+ is pointer-sized. On 64-bit Windows that truncates the handle, and — far
48
+ worse — a *failed* CreateFileW returns INVALID_HANDLE_VALUE, which as a
49
+ signed int is -1 and never equals the unsigned constant we compare against.
50
+ The failure then goes unnoticed and the bogus handle reaches
51
+ msvcrt.open_osfhandle, whose fd raises EBADF ("Bad file descriptor") on
52
+ first use — hiding the actual Windows error.
53
+
54
+ Re-declaring on every call is harmless and keeps this import-safe on
55
+ non-Windows (nothing here runs until a method is called).
56
+ """
57
+ k = ctypes.windll.kernel32
58
+ k.CreateFileW.restype = ctypes.c_void_p
59
+ k.CreateFileW.argtypes = [ctypes.c_wchar_p, ctypes.c_uint32,
60
+ ctypes.c_uint32, ctypes.c_void_p,
61
+ ctypes.c_uint32, ctypes.c_uint32,
62
+ ctypes.c_void_p]
63
+ k.CloseHandle.argtypes = [ctypes.c_void_p]
64
+ k.DeviceIoControl.argtypes = [ctypes.c_void_p, ctypes.c_uint32,
65
+ ctypes.c_void_p, ctypes.c_uint32,
66
+ ctypes.c_void_p, ctypes.c_uint32,
67
+ ctypes.POINTER(ctypes.c_ulong),
68
+ ctypes.c_void_p]
69
+ return k
39
70
 
40
71
 
41
72
  def _powershell(script):
@@ -73,24 +104,28 @@ class WindowsPlatform(Platform):
73
104
 
74
105
  # -- low-level handle helpers -----------------------------------------
75
106
  def _open_handle(self, path, write):
107
+ k = _k32()
76
108
  access = GENERIC_READ | (GENERIC_WRITE if write else 0)
77
- h = ctypes.windll.kernel32.CreateFileW(
78
- ctypes.c_wchar_p(path), access,
79
- FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, 0, None)
80
- if h == INVALID_HANDLE_VALUE or h is None:
81
- raise OSError("CreateFileW failed for %s (err %d)"
82
- % (path, ctypes.windll.kernel32.GetLastError()))
109
+ h = k.CreateFileW(path, access,
110
+ FILE_SHARE_READ | FILE_SHARE_WRITE, None,
111
+ OPEN_EXISTING, 0, None)
112
+ if h is None or h == INVALID_HANDLE_VALUE:
113
+ # Report what Windows actually said: error 5 (access denied) and 32
114
+ # (sharing violation) are the usual causes here, and both mean a
115
+ # volume on this disk is mounted and holding the sectors.
116
+ raise OSError("CreateFileW failed for %s: %s"
117
+ % (path, ctypes.WinError(k.GetLastError())))
83
118
  return h
84
119
 
85
120
  def _ioctl(self, handle, code, out_size=0):
121
+ k = _k32()
86
122
  buf = ctypes.create_string_buffer(out_size) if out_size else None
87
123
  returned = ctypes.c_ulong(0)
88
- ok = ctypes.windll.kernel32.DeviceIoControl(
89
- handle, code, None, 0, buf, out_size,
90
- ctypes.byref(returned), None)
124
+ ok = k.DeviceIoControl(handle, code, None, 0, buf, out_size,
125
+ ctypes.byref(returned), None)
91
126
  if not ok:
92
- raise OSError("DeviceIoControl 0x%X failed (err %d)"
93
- % (code, ctypes.windll.kernel32.GetLastError()))
127
+ raise OSError("DeviceIoControl 0x%X failed: %s"
128
+ % (code, ctypes.WinError(k.GetLastError())))
94
129
  return buf.raw[:returned.value] if buf else b""
95
130
 
96
131
  # -- device discovery / selection -------------------------------------
@@ -237,7 +272,15 @@ class WindowsPlatform(Platform):
237
272
  if os.path.isfile(dev):
238
273
  return open(dev, mode)
239
274
  import msvcrt
240
- h = self._open_handle(dev, write=("w" in mode or "+" in mode or "a" in mode))
275
+ write = ("w" in mode or "+" in mode or "a" in mode)
276
+ if write:
277
+ # FSCTL_LOCK_VOLUME only holds while the locking handle is open, so
278
+ # the dismount done before write_layout is already undone by now:
279
+ # writing the new MBR makes Windows rescan and re-mount the data
280
+ # partition, and it then refuses writes into those sectors. Dismount
281
+ # again immediately before each write open.
282
+ self.unmount_all(dev, False)
283
+ h = self._open_handle(dev, write=write)
241
284
  fd = msvcrt.open_osfhandle(h, os.O_BINARY)
242
285
  return AlignedRawIO(os.fdopen(fd, mode, buffering=0))
243
286
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flashpod
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Command-line iPod sync + card-flashing tooling for early FireWire-era iPods, pure Python
5
5
  Author: David Barnhart
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flashpod"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  description = "Command-line iPod sync + card-flashing tooling for early FireWire-era iPods, pure Python"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.6"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes