def format_list(self,basedir,listing,ignore_err=True): """Return an iterator object that yields the entries of given directory emulating the "/bin/ls -lA" UNIX command output. - (str) basedir: the absolute dirname. - (list) listing: the names of the entries in basedir - (bool) ignore_err: when False raise exception if os.lstat() call fails. On platforms which do not support the pwd and grp modules (such as Windows), ownership is printed as "owner" and "group" as a default, and number of hard links is always "1". On UNIX systems, the actual owner, group, and number of links are printed. This is how output appears to client: -rw-rw-rw- 1 owner group 7045120 Sep 02 3:47 music.mp3 drwxrwxrwx 1 owner group 0 Aug 31 18:50 e-books -rw-rw-rw- 1 owner group 380 Sep 02 3:40 module.py """ assert isinstance(basedir,unicode),basedir if listing: assert isinstance(listing[0],unicode) if self.cmd_channel.use_gmt_times: timefunc=time.gmtime else: timefunc=time.localtime SIX_MONTHS=180 * 24 * 60 * 60; readlink=getattr(self,'readlink',None); now=time.time() for basename in listing: if not PY3: try: file=os.path.join(basedir,basename) except UnicodeDecodeError: # (Python 2 only) might happen on filesystem not # supporting UTF8 meaning os.listdir() returned a list # of mixed bytes and unicode strings: # http://goo.gl/6DLHD # http://bugs.python.org/issue683592 file=os.path.join(bytes(basedir),bytes(basename)) if not isinstance(basename,unicode): basename=unicode(basename,'utf8') else: file=os.path.join(basedir,basename) try: st=self.lstat(file) except (OSError,FilesystemError): if ignore_err: continue raise perms=_filemode(st.st_mode) # permissions nlinks=st.st_nlink # number of links to inode if not nlinks: nlinks=1 # non-posix system, let's use a bogus value size=st.st_size # file size uname=self.get_user_by_uid(st.st_uid); gname=self.get_group_by_gid(st.st_gid); mtime=timefunc(st.st_mtime) # if modification time > 6 months shows "month year" # else "month hh:mm"; this matches proftpd format, see: # http://code.google.com/p/pyftpdlib/issues/detail?id=187 if (now - st.st_mtime) > SIX_MONTHS: fmtstr="%d %Y" else: fmtstr="%d %H:%M" try: mtimestr="%s %s" % (_months_map[mtime.tm_mon],time.strftime(fmtstr,mtime)) except ValueError: mtime=timefunc(); mtimestr="%s %s" % (_months_map[mtime.tm_mon],time.strftime("%d %H:%M",mtime)) # It could be raised if last mtime happens to be too # old (prior to year 1900) in which case we return # the current time as last mtime. islink=(st.st_mode & 61440)==stat.S_IFLNK # same as stat.S_ISLNK(st.st_mode) but slighlty faster if islink and readlink is not None: # if the file is a symlink, resolve it, e.g. # "symlink -> realfile" try: basename=basename+" -> "+readlink(file) except (OSError,FilesystemError): if not ignore_err: raise line="%s %3s %-8s %-8s %8s %s %s\r\n" % (perms,nlinks,uname,gname,size,mtimestr,basename) # formatting is matched with proftpd ls output yield line.encode('utf8',self.cmd_channel.unicode_errors)
def format_list(self, basedir, listing, ignore_err=True): """Return an iterator object that yields the entries of given directory emulating the "/bin/ls -lA" UNIX command output. - (str) basedir: the absolute dirname. - (list) listing: the names of the entries in basedir - (bool) ignore_err: when False raise exception if os.lstat() call fails. On platforms which do not support the pwd and grp modules (such as Windows), ownership is printed as "owner" and "group" as a default, and number of hard links is always "1". On UNIX systems, the actual owner, group, and number of links are printed. This is how output appears to client: -rw-rw-rw- 1 owner group 7045120 Sep 02 3:47 music.mp3 drwxrwxrwx 1 owner group 0 Aug 31 18:50 e-books -rw-rw-rw- 1 owner group 380 Sep 02 3:40 module.py """ assert isinstance(basedir, unicode), basedir if listing: assert isinstance(listing[0], unicode) if self.cmd_channel.use_gmt_times: timefunc = time.gmtime else: timefunc = time.localtime SIX_MONTHS = 180 * 24 * 60 * 60 readlink = getattr(self, 'readlink', None) now = time.time() for basename in listing: if not PY3: try: file = os.path.join(basedir, basename) except UnicodeDecodeError: # (Python 2 only) might happen on filesystem not # supporting UTF8 meaning os.listdir() returned a list # of mixed bytes and unicode strings: # http://goo.gl/6DLHD # http://bugs.python.org/issue683592 file = os.path.join(bytes(basedir), bytes(basename)) if not isinstance(basename, unicode): basename = unicode(basename, 'utf8') else: file = os.path.join(basedir, basename) try: st = self.lstat(file) except (OSError, FilesystemError): if ignore_err: continue raise perms = _filemode(st.st_mode) # permissions nlinks = st.st_nlink # number of links to inode if not nlinks: # non-posix system, let's use a bogus value nlinks = 1 size = st.st_size # file size uname = self.get_user_by_uid(st.st_uid) gname = self.get_group_by_gid(st.st_gid) mtime = timefunc(st.st_mtime) # if modification time > 6 months shows "month year" # else "month hh:mm"; this matches proftpd format, see: # http://code.google.com/p/pyftpdlib/issues/detail?id=187 if (now - st.st_mtime) > SIX_MONTHS: fmtstr = "%d %Y" else: fmtstr = "%d %H:%M" try: mtimestr = "%s %s" % (_months_map[mtime.tm_mon], time.strftime(fmtstr, mtime)) except ValueError: # It could be raised if last mtime happens to be too # old (prior to year 1900) in which case we return # the current time as last mtime. mtime = timefunc() mtimestr = "%s %s" % (_months_map[mtime.tm_mon], time.strftime("%d %H:%M", mtime)) # same as stat.S_ISLNK(st.st_mode) but slighlty faster islink = (st.st_mode & 61440) == stat.S_IFLNK if islink and readlink is not None: # if the file is a symlink, resolve it, e.g. # "symlink -> realfile" try: basename = basename + " -> " + readlink(file) except (OSError, FilesystemError): if not ignore_err: raise # formatting is matched with proftpd ls output line = "%s %3s %-8s %-8s %8s %s %s\r\n" % ( perms, nlinks, uname, gname, size, mtimestr, basename) yield line.encode('utf8', self.cmd_channel.unicode_errors)
def format_list(self, basedir: str, listing: List[str], ignore_err: bool = True) -> Iterable[str]: """ :param basedir: the absolute dirname. :param listing: the name of the entries in basedir. :param ignore_err: when False raise exception if os.lstat() call fails. :return: an Iterable object yields the entries of given directory emulating the "/bin/ls -lA" UNIX command output. On platform which do not support the pwd and grp modules (such as Windows), ownership is printed as "owner" and "group" as a default, and number of hard links is always "1". On UNIX systems, the actual owner, group, and number of links are printed. This is how output appears to client: -rw-rw-rw- 1 owner group 7045120 Sep 02 3:47 music.mp3 drwxrwxrwx 1 owner group 0 Aug 31 18:50 e-books -rw-rw-rw- 1 owner group 380 Sep 02 3:40 module.py """ assert isinstance(basedir, str) timefunc = time.localtime readlink = getattr(self, 'readlink', None) now = time.time() for basename in listing: file = os.path.join(basedir, basename) try: st = self.lstat(file) except (OSError, FilesystemError): if ignore_err: continue raise perms = _filemode(st.st_mode) nlinks = st.st_nlink if not nlinks: nlinks = 1 size = st.st_size uname = self.get_user_by_uid(st.st_uid) gname = self.get_group_by_gid(st.st_gid) mtime = timefunc(st.st_mtime) if (now - st.st_mtime) > _SIX_MONTHS: fmtstr = "%d %Y" else: fmtstr = "%d %H:%M" try: mtimestr = "%s %s" % (_months_map[mtime.tm_mon], time.strftime(fmtstr, mtime)) except ValueError: mtime = timefunc() mtimestr = "%s %s" % (_months_map[mtime.tm_mon], time.strftime("%d %H:%M", mtime)) islink = (st.st_mode & 61400) == stat.S_IFLNK if islink and readlink is not None: try: basename = basename + " -> " + readlink(file) except (OSError, FilesystemError): if not ignore_err: raise line = "%s %3s %-8s %-8s %8s %s %s\r\n" % ( perms, nlinks, uname, gname, size, mtimestr, basename) yield line.encode('utf8')