diff --git a/python/pyphantomjs/filesystem.py b/python/pyphantomjs/filesystem.py index 86d5faec..bf905c53 100644 --- a/python/pyphantomjs/filesystem.py +++ b/python/pyphantomjs/filesystem.py @@ -199,6 +199,15 @@ class FileSystem(QObject): qDebug('FileSystem.copyTree - %s: \'%s\' -> \'%s\'' % (e, source, target)) return False + @pyqtSlot(str, str, result=bool) + def copyLinkTree(self, source, target): + try: + shutil.copytree(source, target, True) + return True + except IOError as (t, e): + qDebug('FileSystem.copyLinkTree - %s: \'%s\' -> \'%s\'' % (e, source, target)) + return False + @pyqtSlot(str, result=bool) def makeDirectory(self, path): try: @@ -389,6 +398,10 @@ class FileSystem(QObject): def normal(self, path): return os.path.normpath(path) + @pyqtSlot(str, result=str) + def normalCase(self, path): + return os.path.normcase(path) + @pyqtProperty(str) def workingDirectory(self): return os.getcwdu() @@ -426,11 +439,79 @@ class FileSystem(QObject): os.chown(path, -1, getgrnam(group).gr_gid) return True except OSError as (t, e): - qDebug('FileSystem.changeOwner - %s: \'%s\':\'%s\'' % (e, owner, path)) + qDebug('FileSystem.changeGroup - %s: \'%s\':\'%s\'' % (e, owner, path)) except KeyError as e: - qDebug('FileSystem.changeOwner - %s: \'%s\'' % (e.args[0], path)) + qDebug('FileSystem.changeGroup - %s: \'%s\'' % (e.args[0], path)) return False + @pyqtSlot(str, str, result=bool) + @pyqtSlot(str, int, result=bool) + def changeLinkGroup(self, path, group): + try: + if isinstance(group, int): + os.lchown(path, -1, group) + else: + os.lchown(path, -1, getgrnam(group).gr_gid) + return True + except OSError as (t, e): + qDebug('FileSystem.changeLinkGroup - %s: \'%s\':\'%s\'' % (e, owner, path)) + except KeyError as e: + qDebug('FileSystem.changeLinkGroup - %s: \'%s\'' % (e.args[0], path)) + return False + + @pyqtSlot(str, str, result=bool) + @pyqtSlot(str, int, result=bool) + def changeLinkOwner(self, path, owner): + try: + if isinstance(owner, int): + os.lchown(path, owner, -1) + else: + os.lchown(path, getpwnam(owner).pw_uid, -1) + return True + except OSError as (t, e): + qDebug('FileSystem.changeLinkOwner - %s: \'%s\':\'%s\'' % (e, owner, path)) + except KeyError as e: + qDebug('FileSystem.changeLinkOwner - %s: \'%s\'' % (e.args[0], path)) + return False + + @pyqtSlot(str, int, result=bool) + @pyqtSlot(str, 'QVariantMap', result=bool) + def changeLinkPermissions(self, path, permissions): + # permissions uses an object in 4 types: owner, group, others, special + # owner,group,others each has 3 types, read,write,executable, contained in an array + # special uses setuid,setgid,sticky + # + # In order to turn values on or off, just use true or false values. + # + # Permissions can alternatively be a numeric mode to chmod too. + + keys = { + 'owner': {'read': 'S_IRUSR', 'write': 'S_IWUSR', 'executable': 'S_IXUSR'}, + 'group': {'read': 'S_IRGRP', 'write': 'S_IWGRP', 'executable': 'S_IXGRP'}, + 'others': {'read': 'S_IROTH', 'write': 'S_IWOTH', 'executable': 'S_IXOTH'}, + 'special': {'setuid': 'S_ISUID', 'setgid': 'S_ISGID', 'sticky': 'S_ISVTX'} + } + + try: + if isinstance(permissions, int): + os.lchmod(path, permissions) + else: + bitnum = os.lstat(path).st_mode + for section in permissions: + for key in permissions[section]: + try: + if permissions[section][key] is True: + bitnum = bitnum | stat.__dict__[keys[section][key]] + elif permissions[section][key] is False: + bitnum = bitnum & ~stat.__dict__[keys[section][key]] + except KeyError: + pass + os.lchmod(path, bitnum) + return True + except OSError as (t, e): + qDebug('FileSystem.changeLinkPermissions - %s: \'%s\'' % (e, path)) + return False + @pyqtSlot(str, str, result=bool) @pyqtSlot(str, int, result=bool) def changeOwner(self, path, owner): @@ -508,6 +589,68 @@ class FileSystem(QObject): qDebug('FileSystem.owner - %s: \'%s\'' % (e, path)) return + @pyqtSlot(str, result='QVariant') + def linkGroup(self, path): + try: + finfo = os.lstat(path) + return { + 'name': getgrgid(finfo.st_gid).gr_name, + 'uid': finfo.st_gid + } + except OSError as (t, e): + qDebug('FileSystem.linkGroup - %s: \'%s\'' % (e, path)) + return + + @pyqtSlot(str, result='QVariant') + def linkOwner(self, path): + try: + finfo = os.lstat(path) + return { + 'name': getpwuid(finfo.st_uid).pw_name, + 'uid': finfo.st_uid + } + except OSError as (t, e): + qDebug('FileSystem.linkOwner - %s: \'%s\'' % (e, path)) + return + + @pyqtSlot(str, result='QVariant') + def linkPermissions(self, path): + # returns an object in 4 types: owner, group, others, special + # owner,group,others each has 3 types, read,write,executable + # special will return setuid,setgid,sticky + + try: + finfo = os.lstat(path).st_mode + + # owner + isOwnRd = bool(finfo & stat.S_IRUSR) + isOwnWr = bool(finfo & stat.S_IWUSR) + isOwnEx = bool(finfo & stat.S_IXUSR) + # group + isGrpRd = bool(finfo & stat.S_IRGRP) + isGrpWr = bool(finfo & stat.S_IWGRP) + isGrpEx = bool(finfo & stat.S_IXGRP) + # others + isOthRd = bool(finfo & stat.S_IROTH) + isOthWr = bool(finfo & stat.S_IWOTH) + isOthEx = bool(finfo & stat.S_IXOTH) + # s*id + isSUid = bool(finfo & stat.S_ISUID) + isSGid = bool(finfo & stat.S_ISGID) + # sticky + isStick = bool(finfo & stat.S_ISVTX) + + return { + 'mode': oct(finfo)[-4:], + 'owner': {'read': isOwnRd, 'write': isOwnWr, 'executable': isOwnEx}, + 'group': {'read': isGrpRd, 'write': isGrpWr, 'executable': isGrpEx}, + 'others': {'read': isOthRd, 'write': isOthWr, 'executable': isOthEx}, + 'special': {'setuid': isSUid, 'setgid': isSGid, 'sticky': isStick} + } + except OSError as (t, e): + qDebug('FileSystem.linkPermissions - %s: \'%s\'' % (e, path)) + return + @pyqtSlot(str, result='QVariant') def permissions(self, path): # returns an object in 4 types: owner, group, others, special @@ -554,10 +697,44 @@ class FileSystem(QObject): def exists(self, path): return os.path.exists(path) + @pyqtSlot(str, result=bool) + def isAbsolute(self, path): + # :FIXME: windows might need to chop off + # drive letter first + return os.path.isabs(path) + + @pyqtSlot(str, result=bool) + def isBlock(self, path): + try: + return stat.S_ISBLK(os.stat(path).st_mode) + except OSError as (t, e): + qDebug('FileSystem.isBlock - %s: \'%s\'' % (e, path)) + return False + + @pyqtSlot(str, result=bool) + def isCharacter(self, path): + try: + return stat.S_ISCHR(os.stat(path).st_mode) + except OSError as (t, e): + qDebug('FileSystem.isCharacter - %s: \'%s\'' % (e, path)) + return False + @pyqtSlot(str, result=bool) def isDirectory(self, path): return os.path.isdir(path) + @pyqtSlot(str, result=bool) + def isExecutable(self, path): + return os.access(path, os.X_OK) + + @pyqtSlot(str, result=bool) + def isFifo(self, path): + try: + return stat.S_ISFIFO(os.stat(path).st_mode) + except OSError as (t, e): + qDebug('FileSystem.isFifo - %s: \'%s\'' % (e, path)) + return False + @pyqtSlot(str, result=bool) def isFile(self, path): return os.path.isfile(path) @@ -574,13 +751,29 @@ class FileSystem(QObject): def isReadable(self, path): return os.access(path, os.R_OK) + @pyqtSlot(str, result=bool) + def isRegular(self, path): + try: + return stat.S_ISREG(os.stat(path).st_mode) + except OSError as (t, e): + qDebug('FileSystem.isRegular - %s: \'%s\'' % (e, path)) + return False + @pyqtSlot(str, result=bool) def isWritable(self, path): return os.access(path, os.W_OK) @pyqtSlot(str, result=bool) - def isExecutable(self, path): - return os.access(path, os.X_OK) + def isSocket(self, path): + try: + return stat.S_ISSOCK(os.stat(path).st_mode) + except OSError as (t, e): + qDebug('FileSystem.isSocket - %s: \'%s\'' % (e, path)) + return False + + @pyqtSlot(str, result=bool) + def linkExists(self, path): + return os.path.lexists(path) @pyqtSlot(str, result=bool) def same(self, pathA, pathB):