📄 platform.py
字号:
# safer to do so. --Daveimage_root = os.path.join(app_root, efs2(u'images'))locale_root = os.path.join(app_root, efs2(u'locale'))no_really_makedirs(locale_root)plugin_path = []internal_plugin = os.path.join(app_root, efs2(u'BitTorrent'), efs2(u'Plugins'))if os.access(internal_plugin, os.F_OK): plugin_path.append(internal_plugin)if not os.access(image_root, os.F_OK) or not os.access(locale_root, os.F_OK): # we guess that probably we are installed on *nix in this case # (I have no idea whether this is right or not -- matt) if app_root[-4:] == '/bin': # yep, installed on *nix installed_prefix = app_root[:-4] image_root, doc_root, locale_root = map( lambda p: os.path.join(installed_prefix, p), calc_unix_dirs() ) systemwide_plugin = os.path.join(installed_prefix, efs2(u'lib'), efs2(u'BitTorrent')) if os.access(systemwide_plugin, os.F_OK): plugin_path.append(systemwide_plugin)if os.name == 'nt': def GetDiskFreeSpaceEx(s): if isinstance(s, unicode): GDFS = ctypes.windll.kernel32.GetDiskFreeSpaceExW else: GDFS = ctypes.windll.kernel32.GetDiskFreeSpaceExA FreeBytesAvailable = ctypes.c_ulonglong(0) TotalNumberOfBytes = ctypes.c_ulonglong(0) TotalNumberOfFreeBytes = ctypes.c_ulonglong(0) r = GDFS(s, ctypes.pointer(FreeBytesAvailable), ctypes.pointer(TotalNumberOfBytes), ctypes.pointer(TotalNumberOfFreeBytes)) return FreeBytesAvailable.value, TotalNumberOfBytes.value, TotalNumberOfFreeBytes.valuedef get_free_space(path): # optimistic if we can't tell free_to_user = 2**64 path, file = os.path.split(path) if os.name == 'nt': while not os.path.exists(path): path, top = os.path.split(path) free_to_user, total, total_free = GetDiskFreeSpaceEx(path) elif hasattr(os, "statvfs"): s = os.statvfs(path) free_to_user = s[statvfs.F_BAVAIL] * long(s[statvfs.F_BSIZE]) return free_to_userdef get_sparse_files_support(path): supported = False if os.name == 'nt': drive, path = os.path.splitdrive(os.path.abspath(path)) if len(drive) > 0: # might be a network path if drive[-1] != '\\': drive += '\\' volumename, serialnumber, maxpath, fsflags, fs_name = win32api.GetVolumeInformation(drive) if fsflags & FILE_SUPPORTS_SPARSE_FILES: supported = True return supported# is there a linux max path?def is_path_too_long(path): if os.name == 'nt': if len(path) > win32con.MAX_PATH: return True return Falsedef is_sparse(path): supported = get_sparse_files_support(path) if not supported: return False if os.name == 'nt': return bool(win32file.GetFileAttributes(path) & FILE_ATTRIBUTE_SPARSE_FILE) return Falsedef get_allocated_regions(path, f=None, begin=0, length=None): supported = get_sparse_files_support(path) if not supported: return if os.name == 'nt': if not os.path.exists(path): return False if f is None: f = file(path, 'r') handle = win32file._get_osfhandle(f.fileno()) if length is None: length = os.path.getsize(path) - begin a = SparseSet() interval = 10000000 i = begin end = begin + length while i < end: d = struct.pack("<QQ", i, interval) try: r = win32file.DeviceIoControl(handle, FSCTL_QUERY_ALLOCATED_RANGES, d, interval, None) except pywintypes.error, e: # I've seen: # error: (1784, 'DeviceIoControl', 'The supplied user buffer is not valid for the requested operation.') return for c in xrange(0, len(r), 16): qq = struct.unpack("<QQ", buffer(r, c, 16)) b = qq[0] e = b + qq[1] a.add(b, e) i += interval return a returndef get_max_filesize(path): fs_name = None # optimistic if we can't tell max_filesize = 2**64 if os.name == 'nt': drive, path = os.path.splitdrive(os.path.abspath(path)) if len(drive) > 0: # might be a network path if drive[-1] != '\\': drive += '\\' volumename, serialnumber, maxpath, fsflags, fs_name = win32api.GetVolumeInformation(drive) if fs_name == "FAT32": max_filesize = 2**32 - 1 elif (fs_name == "FAT" or fs_name == "FAT16"): # information on this varies, so I chose the description from # MS: http://support.microsoft.com/kb/q118335/ # which happens to also be the most conservative. max_clusters = 2**16 - 11 max_cluster_size = 2**15 max_filesize = max_clusters * max_cluster_size else: path = os.path.realpath(path) # not implemented yet #fsname = crawl_path_for_mount_entry(path) return fs_name, max_filesizedef get_config_dir(): """a cross-platform way to get user's config directory. """ if _config_dir is not None: return _config_dir shellvars = ['${APPDATA}', '${HOME}', '${USERPROFILE}'] dir_root = get_dir_root(shellvars) if dir_root is None and os.name == 'nt': app_dir = get_shell_dir(shellcon.CSIDL_APPDATA) if app_dir is not None: dir_root = app_dir if dir_root is None and os.name == 'nt': tmp_dir_root = os.path.split(sys.executable)[0] if os.access(tmp_dir_root, os.R_OK|os.W_OK): dir_root = tmp_dir_root return dir_rootdef get_old_dot_dir(): return os.path.join(get_config_dir(), efs2(u'.bittorrent'))def get_dot_dir(): """So called because on Unix platforms this returns ~/.bittorrent.""" dot_dir = get_old_dot_dir() if os.name == 'nt': new_dot_dir = os.path.join(get_config_dir(), app_name) if os.path.exists(dot_dir): if os.path.exists(new_dot_dir): count = 0 for root, dirs, files in os.walk(new_dot_dir): count = len(dirs) + len(files) break if count == 0: shutil.rmtree(new_dot_dir) shutil.move(dot_dir, new_dot_dir) else: shutil.move(dot_dir, new_dot_dir) dot_dir = new_dot_dir return dot_dirdef get_cache_dir(): dir = None if os.name == 'nt': dir = get_shell_dir(shellcon.CSIDL_INTERNET_CACHE) return dirdef get_home_dir(): shellvars = ['${HOME}', '${USERPROFILE}'] dir_root = get_dir_root(shellvars) if (dir_root is None) and (os.name == 'nt'): dir = get_shell_dir(shellcon.CSIDL_PROFILE) if dir is None: # there's no clear best fallback here # MS discourages you from writing directly in the home dir, # and sometimes (i.e. win98) there isn't one dir = get_shell_dir(shellcon.CSIDL_DESKTOPDIRECTORY) dir_root = dir return dir_rootdef get_local_data_dir(): if os.name == 'nt': # this results in paths that are too long # 86 characters: 'C:\Documents and Settings\Some Guy\Local Settings\Application Data\BitTorrent\incoming' #return os.path.join(get_shell_dir(shellcon.CSIDL_LOCAL_APPDATA), app_name) # I'm even a little nervous about this one return get_dot_dir() else: # BUG: there might be a better place to save incomplete files in under OSX return get_dot_dir()def get_old_incomplete_data_dir(): incomplete = efs2(u'incomplete') return os.path.join(get_old_dot_dir(), incomplete)def get_incomplete_data_dir(): # 'incomplete' is a directory name and should not be localized incomplete = efs2(u'incomplete') return os.path.join(get_local_data_dir(), incomplete)def get_save_dir(): dirname = u'%s Downloads' % unicode(app_name) dirname = efs2(dirname) if os.name == 'nt': d = get_shell_dir(shellcon.CSIDL_PERSONAL) if d is None: d = desktop else: d = desktop return os.path.join(d, dirname)# this function is the preferred way to get windows' pathsdef get_shell_dir(value): dir = None if os.name == 'nt': try: dir = shell.SHGetFolderPath(0, value, 0, 0) except: pass return dirdef get_startup_dir(): """get directory where symlinks/shortcuts to be run at startup belong""" dir = None if os.name == 'nt': dir = get_shell_dir(shellcon.CSIDL_STARTUP) return dirlocal_plugin = os.path.join(get_dot_dir(), efs2(u'Plugins'))if os.access(local_plugin, os.F_OK): plugin_path.append(local_plugin)def create_shortcut(source, dest, *args): if os.name == 'nt': shell = win32com.client.Dispatch("WScript.Shell") shortcut = shell.CreateShortCut(dest + ".lnk") shortcut.Targetpath = source shortcut.Arguments = ' '.join(args) path, file = os.path.split(source) shortcut.WorkingDirectory = path shortcut.save() else: # some other os may not support this, but throwing an error is good since # the function couldn't do what was requested os.symlink(source, dest) # linux also can't do args... maybe we should spit out a shell script? assert not argsdef remove_shortcut(dest): if os.name == 'nt': dest += ".lnk" os.unlink(dest)def enforce_shortcut(config, log_func): if os.name != 'nt': return try: return _enforce_shortcut(config, log_func) except WindowsError: # access denied. not much we can do. traceback.print_exc()def _enforce_shortcut(config, log_func): path = win32api.GetModuleFileName(0) if 'python' in path.lower(): # oops, running the .py too lazy to make that work path = r"C:\Program Files\BitTorrent\bittorrent.exe" root_key = _winreg.HKEY_CURRENT_USER subkey = r'Software\Microsoft\Windows\CurrentVersion\run' key = _winreg.CreateKey(root_key, subkey) if config['launch_on_startup']: _winreg.SetValueEx(key, app_name, 0, _winreg.REG_SZ, '"%s" --force_start_minimized' % path) else: try: _winreg.DeleteValue(key, app_name) except WindowsError, e: # value doesn't exist passdef enforce_association(): if os.name != 'nt': return try: _enforce_association() except WindowsError: # access denied. not much we can do. traceback.print_exc()def _enforce_association(): INSTDIR, EXENAME = os.path.split(win32api.GetModuleFileName(0)) if 'python' in EXENAME.lower(): # oops, running the .py too lazy to make that work INSTDIR = r"C:\Program Files\BitTorrent" EXENAME = "bittorrent.exe" # owie edit_flags = chr(0x00) + chr(0x00) + chr(0x10) + chr(0x00) # lots of wrappers for more direct NSIS mapping HKCR = _winreg.HKEY_CLASSES_ROOT HKCU = _winreg.HKEY_CURRENT_USER def filter_vars(s): s = s.replace("$INSTDIR", INSTDIR) s = s.replace("${EXENAME}", EXENAME) return s def WriteReg(root_key, subkey, key_name, type, value): subkey = filter_vars(subkey) key_name = filter_vars(key_name) value = filter_vars(value) # CreateKey opens the key for us and creates it if it does not exist #key = _winreg.OpenKey(root_key, subkey, 0, _winreg.KEY_ALL_ACCESS) key = _winreg.CreateKey(root_key, subkey) _winreg.SetValueEx(key, key_name, 0, type, value) def WriteRegStr(root_key, subkey, key_name, value): WriteReg(root_key, subkey, key_name, _winreg.REG_SZ, value) def WriteRegBin(root_key, subkey, key_name, value): WriteReg(root_key, subkey, key_name, _winreg.REG_BINARY, value) def DeleteRegKey(root_key, subkey): try: _winreg.DeleteKey(root_key, subkey) except WindowsError: # key doesn't exist pass ## Begin NSIS copy/paste/translate WriteRegStr(HKCR, '.torrent', "", "bittorrent")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -