def windows_fast_hardlink(src, dest): from calibre_extensions import winutil winutil.create_hard_link(dest, src) ssz, dsz = windows_get_size(src), windows_get_size(dest) if ssz != dsz: msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest) raise OSError(msg % ('hardlink size: %d not the same as source size: %s' % (dsz, ssz)))
def windows_hardlink(src, dest): from calibre_extensions import winutil winutil.create_hard_link(dest, src) src_size = os.path.getsize(src) # We open and close dest, to ensure its directory entry is updated # see http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx for i in range(10): # If we are on a network filesystem, we have to wait for some indeterminate time, since # network file systems are the best thing since sliced bread try: if windows_get_size(dest) == src_size: return except EnvironmentError: pass time.sleep(0.3) sz = windows_get_size(dest) if sz != src_size: msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest) raise OSError(msg % ('hardlink size: %d not the same as source size' % sz))
def test_winutil(self): import tempfile from calibre import strftime from calibre_extensions import winutil self.assertEqual(winutil.special_folder_path(winutil.CSIDL_APPDATA), winutil.known_folder_path(winutil.FOLDERID_RoamingAppData)) self.assertEqual(winutil.special_folder_path(winutil.CSIDL_LOCAL_APPDATA), winutil.known_folder_path(winutil.FOLDERID_LocalAppData)) self.assertEqual(winutil.special_folder_path(winutil.CSIDL_FONTS), winutil.known_folder_path(winutil.FOLDERID_Fonts)) self.assertEqual(winutil.special_folder_path(winutil.CSIDL_PROFILE), winutil.known_folder_path(winutil.FOLDERID_Profile)) def au(x, name): self.assertTrue( isinstance(x, unicode_type), '%s() did not return a unicode string, instead returning: %r' % (name, x)) for x in 'username temp_path locale_name'.split(): au(getattr(winutil, x)(), x) d = winutil.localeconv() au(d['thousands_sep'], 'localeconv') au(d['decimal_point'], 'localeconv') for k, v in iteritems(d): au(v, k) os.environ['XXXTEST'] = 'YYY' self.assertEqual(getenv('XXXTEST'), 'YYY') del os.environ['XXXTEST'] self.assertIsNone(getenv('XXXTEST')) for k in os.environ: v = getenv(k) if v is not None: au(v, 'getenv-' + k) t = time.localtime() fmt = '%Y%a%b%e%H%M' for fmt in (fmt, fmt.encode('ascii')): x = strftime(fmt, t) au(x, 'strftime') tdir = tempfile.mkdtemp(dir=winutil.temp_path()) path = os.path.join(tdir, 'test-create-file.txt') h = winutil.create_file( path, winutil.GENERIC_READ | winutil.GENERIC_WRITE, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL) self.assertRaises(OSError, winutil.delete_file, path) del h winutil.delete_file(path) self.assertRaises(OSError, winutil.delete_file, path) self.assertRaises(OSError, winutil.create_file, os.path.join(path, 'cannot'), winutil.GENERIC_READ, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL) self.assertTrue(winutil.supports_hardlinks(os.path.abspath(os.getcwd())[0] + ':\\')) sz = 23 data = os.urandom(sz) open(path, 'wb').write(data) h = winutil.Handle(0, winutil.ModuleHandle, 'moo') r = repr(h) h2 = winutil.Handle(h.detach(), winutil.ModuleHandle, 'moo') self.assertEqual(r, repr(h2)) h2.close() h = winutil.create_file( path, winutil.GENERIC_READ | winutil.GENERIC_WRITE, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL) self.assertEqual(winutil.get_file_size(h), sz) self.assertRaises(OSError, winutil.set_file_pointer, h, 23, 23) self.assertEqual(winutil.read_file(h), data) self.assertEqual(winutil.read_file(h), b'') winutil.set_file_pointer(h, 3) self.assertEqual(winutil.read_file(h), data[3:]) self.assertEqual(winutil.nlinks(path), 1) npath = path + '.2' winutil.create_hard_link(npath, path) h.close() self.assertEqual(open(npath, 'rb').read(), data) self.assertEqual(winutil.nlinks(path), 2) winutil.delete_file(path) self.assertEqual(winutil.nlinks(npath), 1) winutil.set_file_attributes(npath, winutil.FILE_ATTRIBUTE_READONLY) self.assertRaises(OSError, winutil.delete_file, npath) winutil.set_file_attributes(npath, winutil.FILE_ATTRIBUTE_NORMAL) winutil.delete_file(npath) self.assertGreater(min(winutil.get_disk_free_space(None)), 0) open(path, 'wb').close() open(npath, 'wb').close() winutil.move_file(path, npath, winutil.MOVEFILE_WRITE_THROUGH | winutil.MOVEFILE_REPLACE_EXISTING) self.assertFalse(os.path.exists(path)) os.remove(npath) dpath = tempfile.mkdtemp(dir=os.path.dirname(path)) dh = winutil.create_file( dpath, winutil.FILE_LIST_DIRECTORY, winutil.FILE_SHARE_READ, winutil.OPEN_EXISTING, winutil.FILE_FLAG_BACKUP_SEMANTICS, ) from threading import Thread, Event started = Event() events = [] def read_changes(): buffer = b'0' * 8192 started.set() events.extend(winutil.read_directory_changes( dh, buffer, True, winutil.FILE_NOTIFY_CHANGE_FILE_NAME | winutil.FILE_NOTIFY_CHANGE_DIR_NAME | winutil.FILE_NOTIFY_CHANGE_ATTRIBUTES | winutil.FILE_NOTIFY_CHANGE_SIZE | winutil.FILE_NOTIFY_CHANGE_LAST_WRITE | winutil.FILE_NOTIFY_CHANGE_SECURITY )) t = Thread(target=read_changes, daemon=True) t.start() started.wait(1) t.join(0.1) testp = os.path.join(dpath, 'test') open(testp, 'w').close() t.join(4) self.assertTrue(events) for actions, path in events: self.assertEqual(os.path.join(dpath, path), testp) dh.close() os.remove(testp) os.rmdir(dpath) del h shutil.rmtree(tdir) m = winutil.create_mutex("test-mutex", False) self.assertRaises(OSError, winutil.create_mutex, 'test-mutex', False) m.close() self.assertEqual(winutil.parse_cmdline('"c:\\test exe.exe" "some arg" 2'), ('c:\\test exe.exe', 'some arg', '2'))