diff -ur v9/ftp_ut.py v10/ftp_ut.py --- v9/ftp_ut.py 2020-02-16 12:25:20.000000000 +0900 +++ v10/ftp_ut.py 2020-02-16 14:35:41.000000000 +0900 @@ -6,6 +6,7 @@ import cmd_ut import yaml_ut import dbg +import tm_ut import arg import base @@ -131,13 +132,15 @@ do_cmd( cmd ) return cmd + '\n' - def cut_dot(lst): - return list( filter( lambda s: s not in ( './', '../' ), lst ) ) + is_dot = lambda s: s in ( '.', '..', './', '../' ) - def cut_tail(lst, c): - return list( map( lambda s: s[:-1] if s and s[-1] == c else s, lst ) ) + is_dir = lambda lst: any( map( is_dot, lst ) ) - def get_lst(path='', dot=True): + cut_dot = lambda lst: list( filter( lambda s: not is_dot( s ), lst ) ) + + cut_tail = lambda lst, c: list( map( lambda s: s[:-1] if s and s[-1] == c else s, lst ) ) + + def get_lst(path='', dot=True, cut_d=False): r = ls(path) if path else ls() lst = r.strip().split('\n') lst = map( lambda s: s.split(), lst ) @@ -152,13 +155,30 @@ if ws[0][0] == 'd': nm += '/' rlst.append( nm ) - return rlst if dot else cut_dot( rlst ) + if not dot: + rlst = cut_dot( rlst ) + if cut_d: + rlst = cut_tail( rlst, '/' ) + return rlst + + def is_exist(path): + return get_lst( path ) + + def get_kind(path, cut_d=False): + lst = get_lst( path, cut_d ) + if not lst: + return '' # no entry + if not is_dir( lst ): + return 'f' # file + lst = cut_dot( lst ) + return to_str( [ 'd' ] + lst ) # directory, and contents + def lstf(path=''): return to_str( get_lst( path ), last=True ) def rm_rf(path): - s = get_kind( path ) + s = get_kind( path, cut_d=True ) if not s: return '' @@ -170,23 +190,84 @@ return '' r = '' - lst = cut_tail( lst[1:], '/' ) - for name in lst: + for name in lst[1:]: r += rm_rf( path + '/' + name ) r += rmdir( path ) return r - def is_exist(path): - return get_lst( path ) - def get_kind(path): - lst = get_lst( path ) - if not lst: - return '' # no entry - if './' not in lst and '../' not in lst: - return 'f' # file - lst = cut_dot( lst ) - return to_str( [ 'd' ] + lst ) # directory, and contents + def cnv_use_fn(s): + allow = ( '_', '-', '+', ',' ) + return ''.join( map( lambda c: c if c.isalnum() or c in allow else '_', s ) ) + + call = lambda cmd: cmd_ut.call( cmd ).decode() + + me_str = lambda : cnv_use_fn( call( 'hostname' ) + '_' + call( 'whoami' ) ) + + def is_lock_zombi(name, me, now): + if name.startswith( me + '.' ): + return True + ws = name.split( '.' ) + if not ws: + return True + s = ws[-1] + if len(s) != 4+2+2 + 2+2+2: + return True + sec = tm_ut.str_to_sec( s ) + if now - sec > 10 * 60: # 10 min + return True + return False + + def lock(path): + me = me_str() + + now = tm_ut.now_sec() + tm = tm_ut.sec_to_str( now ) + + lock_d = path + '/_lock' + + kind = get_kind( lock_d, cut_d=False ) + if kind == 'f': + rm_rf( lock_d ) + kind = '' + if kind: + lst = cut_tail( kind[1:].split( '\n' ), '/' ) + for name in lst[:]: # copy + if is_lock_zombi( name, me, now ): + rm_rf( lock_d + '/' + name ) + lst.remove( name ) + if lst: + return to_str( ( 'no lock', to_str( lst, pre=' ' ) ), last=True ) + + name = me + '.' + tm + mkdir( lock_d + '/' + name ) + + lst = get_lst( lock_d, dot=False, cut_d=True ) + lst.remove( name ) + if lst: + return to_str( ( 'no lock', to_str( lst, pre=' ' ) ), last=True ) + + return to_str( ( 'get lock', ' ' + name ), last=True ) + + def unlock(path): + me = me_str() + + lock_d = path + '/_lock' + + kind = get_kind( lock_d, cut_d=False ) + if kind: + if kind == 'f': + rm_rf( lock_d ) + else: + lst = cut_tail( kind[1:].split( '\n' ), '/' ) + for name in lst[:]: # copy + if is_lock_zombi( name, me, now ): + rm_rf( lock_d + '/' + name ) + lst.remove( name ) + if not lst: + if get_kind( lock_d ) == 'd': + rmdir( lock_d ) + return '' def do_paths(f, paths): r = '' @@ -242,6 +323,8 @@ ' host user passwd ls path ..', ' host user passwd lst path ..', ' host user passwd rm_rf path ..', + ' host user passwd lock path ..', + ' host user passwd unlock path ..', '', ' site_name in ftp_ut.yaml, can ommit host user passwd' ] @@ -277,7 +360,7 @@ ftp = new(host, user, passwd, debug=debug) ( p0, p1_ ) = ( paths[0], paths[1:] ) - quiet = p0 in ( 'ls', 'lst' ) + quiet = p0 in ( 'ls', 'lst', 'lock', 'unlock' ) ftp.login() if not quiet: @@ -301,6 +384,10 @@ r = ftp.do_paths( ftp.lstf, p1_ ) if p1_ else ftp.lstf() elif p0 == 'rm_rf': r = ftp.do_paths( ftp.rm_rf, p1_ ) + elif p0 == 'lock': + r = ftp.do_paths( ftp.lock, p1_ ) + elif p0 == 'unlock': + r = ftp.do_paths( ftp.unlock, p1_ ) else: r = ftp.do_paths( ftp.put, p1_ if p0 == 'put' else paths ) dbg.out( r, '' )