[Twisted-Python] How to setup a ftpserver, ftpclient?

Donovan Baarda abo at minkirri.apana.org.au
Tue Apr 9 07:05:06 MDT 2002


On Tue, Apr 09, 2002 at 12:55:14PM +1000, Andrew Bennetts wrote:
> On Mon, Apr 08, 2002 at 10:20:06PM -0400, Michael Bacarella wrote:
> > On Tue, Apr 09, 2002 at 11:22:47AM +1000, Andrew Bennetts wrote:
[...]
> Good question.  Probably not a huge amount.  The FTPFileListingProtocol
> could probably be taught to write as well as read; and perhaps the
[...]

I have code for this, non-twisted specific. I'm interested in supporting
this in conjunction with a few other useful utility modules, so any
changes/suggestions etc are welcome.

Attached.

-- 
----------------------------------------------------------------------
ABO: finger abo at minkirri.apana.org.au for more info, including pgp key
----------------------------------------------------------------------
-------------- next part --------------
# Generate and parse unix style ls output lines in the following format
#      mode nlink uid gid size date file [ -> link]
# mode is a string in the form "drwxrwxrwx", with all modes supported.
# nlink, uid, gid, and size are all numeric.
# Date has an abreviated format as explained below.
import stat,string,time
from strptime import strptime

def getuid(name):
    try:
        import pwd
        return pwd.getpwnam(name)[2]
    except:
        try: return int(name)
        except: return 0
    
def getgid(name):
    try:
        import grp
        return grp.getgrnam(name)[2]
    except:
        try: return int(name)
        except: return 0

def getuname(uid):
    try:
        import pwd
        return pwd.getpwuid(uid)[0]
    except:
        return '0'
    
def getgname(gid):
    try:
        import grp
        return grp.getgrgid(gid)[0]
    except:
        return '0'
    
def lsunparse ((name, stat_info, link)):
    mode = lsmodeunparse (stat_info[stat.ST_MODE])
    date = lsdateunparse (stat_info[stat.ST_MTIME])
    if link:
        name = name + " -> " + link
    return '%s %3d %-8s %-8s %8d %s %s' % (
        mode,
        stat_info[stat.ST_NLINK],
        getuname(stat_info[stat.ST_UID]),
        getgname(stat_info[stat.ST_GID]),
        stat_info[stat.ST_SIZE],
        date,
        name)
                
def lsparse (line):
    mode,nlink,uid,gid,size,rest = string.split(line,maxsplit=5)
    mode = lsmodeparse(mode)
    nlink = int(nlink)
    uid  = getuid(uid)
    gid  = getgid(gid)
    size = int(size)
    date = lsdateparse(rest[:12])
    name = string.strip(rest[12:])
    try:
        name,link = string.split(name," -> ")
    except ValueError:
        link = None
    return name,(mode,0,0,nlink,uid,gid,size,date,date,date),link
    
    
dchr_table = {
    'd':stat.S_IFDIR,
    'c':stat.S_IFCHR,
    'b':stat.S_IFBLK,
    '-':stat.S_IFREG,
    'f':stat.S_IFIFO,
    'l':stat.S_IFLNK,
    's':stat.S_IFSOCK
    }

ifmt_table = {
    stat.S_IFDIR:'d',
    stat.S_IFCHR:'c',
    stat.S_IFBLK:'b',
    stat.S_IFREG:'-',
    stat.S_IFIFO:'f',
    stat.S_IFLNK:'l',
    stat.S_IFSOCK:'s'
    }

def lsmodeparse(text):
    mode = dchr_table[text[0]]
    if text[1]=='r': mode = mode | stat.S_IRUSR
    if text[2]=='w': mode = mode | stat.S_IWUSR
    if text[3] in 'xs': mode = mode | stat.S_IXUSR
    if text[3] in 'Ss': mode = mode | stat.S_ISUID
    if text[4]=='r': mode = mode | stat.S_IRGRP
    if text[5]=='w': mode = mode | stat.S_IWGRP
    if text[6] in 'xs': mode = mode | stat.S_IXGRP
    if text[6] in 'Ss': mode = mode | stat.S_ISGID
    if text[7]=='r': mode = mode | stat.S_IROTH
    if text[8]=='w': mode = mode | stat.S_IWOTH
    if text[9] in 'xt': mode = mode | stat.S_IXOTH
    if text[9] in 'tT': mode = mode | stat.S_ISVTX
    return mode
    
def lsmodeunparse(mode):
    text = list(ifmt_table[stat.S_IFMT(mode)]+ "---------")
    if mode & stat.S_IRUSR: text[1]='r'
    if mode & stat.S_IWUSR: text[2]='w'
    if mode & stat.S_IXUSR:
        if mode & stat.S_ISUID: text[3]='s'
        else: text[3]='x'
    elif mode & stat.S_ISUID:
        text[3]='S'
    if mode & stat.S_IRGRP: text[4]='r'
    if mode & stat.S_IWGRP: text[5]='w'
    if mode & stat.S_IXGRP:
        if mode & stat.S_ISGID: text[6]='s'
        else: text[6]='x'
    elif mode & stat.S_ISGID:
        text[6]='S'
    if mode & stat.S_IROTH: text[7]='r'
    if mode & stat.S_IWOTH: text[8]='w'
    if mode & stat.S_IXOTH:
        if mode & stat.S_ISVTX: text[9]='t'
        else: text[9]='x'
    elif mode & stat.S_ISVTX:
        text[9]='T'
    return string.join(text,'')

# Emulate the unix 'ls' command's date field.
# it has two formats - if the date is more than 180
# days in the past, then it's like this:
# Oct 19  1995
# otherwise, it looks like this:
# Oct 19 17:33
def lsdateparse (text):
    if string.find(text,":") != -1:
        info = list(strptime(text,"%b %d %H:%M"))
        now = time.localtime(time.time())
        if now[1] < info[1]:
            info[0] = now[0]-1
        else:
            info[0] = now[0]
    else:
        info = list(strptime(text,"%b %d  %Y"))
    info[8]=0
    return time.mktime(info) + time.timezone

def lsdateunparse (t):
    try:
        info = time.gmtime (t)
    except:
        info = time.gmtime (0)
    # 15,600,000 == 180 days
    if (long(time.time()) - t) > 15600000:
        return time.strftime("%b %d  %Y",info)
    else:
        return time.strftime("%b %d %H:%M",info)


More information about the Twisted-Python mailing list