/syncy.py
Python | 928 lines | 890 code | 18 blank | 20 comment | 60 complexity | bfee9d77f5657e926597313907d6d175 MD5 | raw file
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- ####################################################################################################
- #
- # Author: wishinlife
- # QQ: 57956720
- # QQ Group: 59160264
- # E-Mail: wishinlife@qq.com
- # Web Home: http://www.syncy.cn
- # Update date: 2015-05-26
- # VERSION: 2.5.1
- # Required packages: kmod-nls-utf8, libopenssl, libcurl, python, python-curl, python-crypto
- #
- ####################################################################################################
- import sys
- import os
- import stat
- import time
- import re
- import struct
- import hashlib
- from urllib import urlencode
- import threading
- import traceback
- import json
- import random
- # import fcntl
- # if '/usr/lib/python2.7/site-packages' not in sys.path:
- # sys.path.append('/usr/lib/python2.7/site-packages')
- import pycurl
- import binascii
- # import zlib
- # import fileinput
- try: # require python-crypto
- from Crypto.Cipher import ARC4
- from Crypto.Cipher import Blowfish
- from Crypto.Cipher import AES
- except ImportError, ex:
- ARC4 = Blowfish = AES = None
- # set config_file and pidfile for your config storage path.
- if os.name == 'nt':
- _CONFIG_FILE = './syncy'
- _PIDFILE = './syncy.pid'
- _CHARSET = 'GBK' # windows charset
- _TMP_DIR = os.environ['TMP'].replace('\\', '/')
- else:
- _CONFIG_FILE = '/etc/config/syncy'
- _PIDFILE = '/var/run/syncy.pid'
- _CHARSET = 'UTF-8' # linux charset
- _TMP_DIR = '/tmp'
- if sys.getdefaultencoding() != _CHARSET:
- reload(sys)
- sys.setdefaultencoding(_CHARSET)
- # Don't modify the following.
- _VERSION = '2.5.1'
- _DEBUG = False
- __author__ = "WishInLife <wishinlife@qq.com>"
- if os.name == 'nt':
- import win32con
- import win32file
- import pywintypes
- LOCK_SH = 0
- LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
- LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
- LOCK_UN = 8
- __overlapped = pywintypes.OVERLAPPED()
- def flock(fd, op):
- fh = win32file._get_osfhandle(fd.fileno())
- if op == LOCK_UN:
- return win32file.UnlockFileEx(fh, 0, 0x0fff0000, __overlapped)
- else:
- return win32file.LockFileEx(fh, op, 0, 0x0fff0000, __overlapped)
- def lockf(fd, op, length=0, start=0, whence=0):
- fh = win32file._get_osfhandle(fd.fileno())
- fsize = win32file.GetFileSize(fh)
- if whence == 1:
- start += fd.tell()
- elif whence == 2:
- start += fsize
- if length == 0:
- length = fsize
- int32 = 2 ** 32
- if op == LOCK_UN:
- return win32file.UnlockFile(fh, int(start % int32), int(start / int32), int(length % int32), int(length / int32))
- else:
- return win32file.LockFile(fh, int(start % int32), int(start / int32), int(length % int32), int(length / int32))
- else:
- from fcntl import LOCK_EX, LOCK_SH, LOCK_NB, LOCK_UN, flock, lockf
- LogLock = threading.Lock()
- def printlog(msg):
- LogLock.acquire()
- print(msg)
- LogLock.release()
- def rename(src, dst):
- if os.name == 'nt' and os.path.exists(dst):
- os.remove(dst)
- os.rename(src, dst)
- class SyncY:
- synccount = 0
- errorcount = 0
- failcount = 0
- EXLock = threading.Lock()
- TaskSemaphore = None
- oldSTDERR = None
- oldSTDOUT = None
- syncydb = None
- sydb = None
- sydblen = None
- syncData = None
- basedirlen = None
- syncpath = {}
- extraslice = None
- encryption = None
- encryptkey = ''
- config = {
- 'syncylog' : '',
- 'blocksize' : 10,
- 'ondup' : 'rename',
- 'datacache' : 'on',
- 'excludefiles' : '',
- 'listnumber' : 100,
- 'retrytimes' : 3,
- 'retrydelay' : 3,
- 'maxsendspeed' : 0,
- 'maxrecvspeed' : 0,
- 'speedlimitperiod': '0-0',
- 'syncperiod' : '0-24',
- 'syncinterval' : 3600,
- 'tasknumber' : 2,
- 'threadnumber' : 2}
- syre = {
- 'newname': re.compile(r'^(.*)(\.[^.]+)$'),
- 'pcspath': re.compile(r'^[\s\.\n].*|.*[/<>\\|\*\?:\"].*|.*[\s\.\n]$')}
- syncytoken = {'synctotal': 0}
- pcsroot = '/apps/SyncY'
- synctask = {}
- def __init__(self, argv=sys.argv[1:]):
- self.__argv = argv
- if len(self.__argv) == 0 or self.__argv[0] in ['compress', 'convert', 'rebuild']:
- if os.path.exists(_PIDFILE):
- with open(_PIDFILE, 'r') as pidh:
- mypid = pidh.read()
- try:
- os.kill(int(mypid), 0)
- except os.error:
- pass
- else:
- print("SyncY is running!")
- sys.exit(0)
- with open(_PIDFILE, 'w') as pidh:
- pidh.write(str(os.getpid()))
- if not (os.path.isfile(_CONFIG_FILE)):
- sys.stderr.write('%s ERROR: Config file "%s" does not exist.\n' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), _CONFIG_FILE))
- sys.exit(2)
- with open(_CONFIG_FILE, 'r') as sycfg:
- line = sycfg.readline()
- section = ''
- while line:
- if re.findall(r'^\s*#', line) or re.findall(r'^\s*$', line):
- line = sycfg.readline()
- continue
- line = re.sub(r'#[^\']*$', '', line)
- m = re.findall(r'\s*config\s+([^\s]+).*', line)
- if m:
- section = m[0].strip('\'')
- if section == 'syncpath':
- SyncY.syncpath[str(len(SyncY.syncpath))] = {}
- line = sycfg.readline()
- continue
- m = re.findall(r'\s*option\s+([^\s]+)\s+\'([^\']*)\'', line)
- if m:
- if section == 'syncy':
- if m[0][0].strip('\'') in ['blocksize', 'listnumber', 'syncinterval', 'threadnumber', 'tasknumber', 'retrytimes', 'retrydelay']:
- SyncY.config[m[0][0].strip('\'')] = int(m[0][1])
- elif m[0][0].strip('\'') in ['maxsendspeed', 'maxrecvspeed']:
- if m[0][1].upper().find('K') > -1:
- idx = m[0][1].upper().find('K')
- SyncY.config[m[0][0].strip('\'')] = int(m[0][1][0:idx]) * 1024
- elif m[0][1].upper().find('M') > -1:
- idx = m[0][1].upper().find('M')
- SyncY.config[m[0][0].strip('\'')] = int(m[0][1][0:idx]) * 1024 * 1024
- else:
- SyncY.config[m[0][0].strip('\'')] = int(m[0][1])
- else:
- SyncY.config[m[0][0].strip('\'')] = m[0][1]
- elif section == 'syncytoken':
- if m[0][0].strip('\'') in ['expires_in', 'refresh_date', 'compress_date', 'synctotal']:
- SyncY.syncytoken[m[0][0].strip('\'')] = int(m[0][1])
- else:
- SyncY.syncytoken[m[0][0].strip('\'')] = m[0][1]
- elif section == 'syncpath':
- if m[0][0].strip('\'') == 'remotepath':
- if m[0][1].lower().startswith('/apps/syncy'):
- SyncY.syncpath[str(len(SyncY.syncpath) - 1)]['remotepath'] = m[0][1][11:]
- elif m[0][1].lower().startswith('/我的应用程序/syncy'):
- SyncY.syncpath[str(len(SyncY.syncpath) - 1)]['remotepath'] = m[0][1][len('/我的应用程序/syncy'):]
- else:
- SyncY.syncpath[str(len(SyncY.syncpath) - 1)]['remotepath'] = m[0][1]
- else:
- SyncY.syncpath[str(len(SyncY.syncpath) - 1)][m[0][0].strip('\'')] = m[0][1].replace('\\', '/')
- line = sycfg.readline()
- if SyncY.config['syncylog'] != '':
- if not os.path.exists(os.path.dirname(SyncY.config['syncylog'])):
- os.makedirs(os.path.dirname(SyncY.config['syncylog']))
- if os.path.exists(SyncY.config['syncylog']) and os.path.isdir(SyncY.config['syncylog']):
- SyncY.config['syncylog'] = self.__catpath(SyncY.config['syncylog'], 'syncy.log')
- self.__save_config()
- if SyncY.oldSTDERR is None and SyncY.config['syncylog'] != '' and len(self.__argv) != 0 and self.__argv[0] in ['sybind', 'cpbind']:
- SyncY.oldSTDERR = sys.stderr
- SyncY.oldSTDOUT = sys.stdout
- sys.stderr = open(SyncY.config['syncylog'], 'a', 0)
- sys.stdout = sys.stderr
- if 'refresh_token' not in SyncY.syncytoken or SyncY.syncytoken['refresh_token'] == '' or (len(self.__argv) != 0 and self.__argv[0] in ['sybind', 'cpbind']):
- sycurl = SYCurl()
- if (('device_code' not in SyncY.syncytoken or SyncY.syncytoken['device_code'] == '') and len(self.__argv) == 0) or (len(self.__argv) != 0 and self.__argv[0] == 'sybind'):
- retcode, responses = sycurl.request('https://www.syncy.cn/syserver', {}, {'method': 'bind_device', 'scope': 'basic,netdisk'}, 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- print('%s ERROR(Errno:%d): Get device code failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, responses['error_msg']))
- sys.exit(3)
- device_code = responses['device_code']
- user_code = responses['user_code']
- if len(self.__argv) != 0 and self.__argv[0] == 'sybind':
- with open(_TMP_DIR + '/syncy.bind', 'w') as sybind:
- sybind.write('{"user_code":"%s","device_code":"%s","time":%d}' % (user_code, device_code, int(time.time())))
- sys.exit(0)
- SyncY.syncytoken['device_code'] = device_code
- print('Device binding Guide:')
- print(' 1. Open web browser to visit:"https://openapi.baidu.com/device" and input user code to binding your baidu account.')
- print(' ')
- print(' 2. User code:\033[31m %s\033[0m' % user_code)
- print(' (User code valid for 30 minutes.)')
- print(' ')
- raw_input(' 3. After granting access to the application, come back here and press [Enter] to continue.')
- print(' ')
- if len(self.__argv) != 0 and self.__argv[0] == 'cpbind':
- with open(_TMP_DIR + '/syncy.bind', 'r') as sybind:
- bindinfo = sybind.read()
- bindinfo = json.loads(bindinfo)
- os.remove(_TMP_DIR + '/syncy.bind')
- if 'device_code' in bindinfo:
- if int(time.time()) - int(bindinfo['time']) >= 1800:
- sys.exit(4)
- SyncY.syncytoken['device_code'] = bindinfo['device_code']
- else:
- sys.exit(5)
- retcode, responses = sycurl.request('https://www.syncy.cn/syserver', {}, {'method': 'get_device_token', 'code': SyncY.syncytoken['device_code'], 'edition': 'python', 'ver': _VERSION}, 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- print('%s ERROR(Errno:%d): Get device token failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, responses['error_msg']))
- sys.exit(6)
- SyncY.syncytoken['refresh_token'] = responses['refresh_token']
- SyncY.syncytoken['access_token'] = responses['access_token']
- SyncY.syncytoken['expires_in'] = int(responses['expires_in'])
- SyncY.syncytoken['refresh_date'] = int(time.time())
- SyncY.syncytoken['compress_date'] = int(time.time())
- self.__save_config()
- if len(self.__argv) != 0 and self.__argv[0] == 'cpbind':
- sys.exit(0)
- print('%s INFO: Get device token success.\n' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.oldSTDERR is None and SyncY.config['syncylog'] != '':
- print('%s INFO: Running log output to log file %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), SyncY.config['syncylog']))
- SyncY.oldSTDERR = sys.stderr
- SyncY.oldSTDOUT = sys.stdout
- sys.stderr = open(SyncY.config['syncylog'], 'a', 0)
- sys.stdout = sys.stderr
- try:
- if SyncY.config['blocksize'] < 1:
- SyncY.config['blocksize'] = 10
- print('%s WARNING: "blocksize" must great than or equal to 1(M), set to default 10(M).' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['ondup'] != 'overwrite' and SyncY.config['ondup'] != 'rename':
- SyncY.config['ondup'] = 'rename'
- print('%s WARNING: ondup is invalid, set to default(overwrite).' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['datacache'] != 'on' and SyncY.config['datacache'] != 'off':
- SyncY.config['datacache'] = 'on'
- print('%s WARNING: "datacache" is invalid, set to default(on).' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['retrytimes'] < 0:
- SyncY.config['retrytimes'] = 3
- print('%s WARNING: "retrytimes" is invalid, set to default(3 times).' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['retrydelay'] < 0:
- SyncY.config['retrydelay'] = 3
- print('%s WARNING: "retrydelay" is invalid, set to default(3 second).' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['listnumber'] < 1:
- SyncY.config['listnumber'] = 100
- print('%s WARNING: "listnumber" must great than or equal to 1, set to default 100.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['syncinterval'] < 0:
- SyncY.config['syncinterval'] = 3600
- print('%s WARNING: "syncinterval" must great than or equal to 1, set to default 3600.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['maxsendspeed'] < 0:
- SyncY.config['maxsendspeed'] = 0
- print('%s WARNING: "maxsendspeed" must great than or equal to 0, set to default 0.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['maxrecvspeed'] < 0:
- SyncY.config['maxrecvspeed'] = 0
- print('%s WARNING: "maxrecvspeed" must great than or equal to 0, set to default 100.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['threadnumber'] < 1:
- SyncY.config['threadnumber'] = 2
- print('%s WARNING: "threadnumber" must great than or equal to 1, set to default 2.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- if SyncY.config['tasknumber'] < 1:
- SyncY.config['tasknumber'] = 2
- print('%s WARNING: "tasknumber" must great than or equal to 1, set to default 2.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- starthour, endhour = SyncY.config['speedlimitperiod'].split('-', 1)
- if starthour == '' or endhour == '' or int(starthour) < 0 or int(starthour) > 23 or int(endhour) < 0 or int(endhour) > 24:
- print('%s WARNING: "speedlimitperiod" is invalid, set to default(0-0), no limit.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- SyncY.config['speedlimitperiod'] = '0-0'
- starthour, endhour = SyncY.config['syncperiod'].split('-', 1)
- if starthour == '' or endhour == '' or int(starthour) < 0 or int(starthour) > 23 or int(endhour) < 0 or int(endhour) > 24 or endhour == starthour:
- print('%s WARNING: "syncperiod" is invalid, set to default(0-24).' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- SyncY.config['syncperiod'] = '0-24'
- except Exception, e:
- print('%s ERROR: initialize parameters failed. %s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), e, traceback.format_exc()))
- sys.exit(7)
- self._excludefiles = SyncY.config['excludefiles'].replace('\\', '/').replace('.', '\.').replace('*', '.*').replace('?', '.?').split(';')
- for i in xrange(len(self._excludefiles)):
- self._excludefiles[i] = re.compile(eval('r"^' + self._excludefiles[i] + '$"'))
- self._excludefiles.append(re.compile(r'^.*\.syy$'))
- if (SyncY.syncytoken['refresh_date'] + SyncY.syncytoken['expires_in'] - 864000) < int(time.time()):
- self.__check_expires()
- SyncY.TaskSemaphore = threading.Semaphore(SyncY.config['tasknumber'])
- size = 32768
- while True:
- try:
- threading.stack_size(size)
- threadtest = ThreadTest()
- threadtest.start()
- break
- except threading.ThreadError:
- threading.stack_size(0)
- break
- except RuntimeError:
- threading.stack_size(0)
- break
- except ValueError:
- if size < 512 * 1024:
- size *= 2
- else:
- threading.stack_size(0)
- break
- def __del__(self):
- if self.__class__.oldSTDERR is not None:
- sys.stderr.flush()
- sys.stderr.close()
- sys.stderr = self.__class__.oldSTDERR
- sys.stdout = self.__class__.oldSTDOUT
- if os.path.exists(_PIDFILE):
- with open(_PIDFILE, 'r') as pidh:
- lckpid = pidh.read()
- if os.getpid() == int(lckpid):
- os.remove(_PIDFILE)
- @staticmethod
- def synccount_increase():
- SyncY.EXLock.acquire()
- SyncY.synccount += 1
- SyncY.EXLock.release()
- @staticmethod
- def errorcount_increase():
- SyncY.EXLock.acquire()
- SyncY.errorcount += 1
- SyncY.EXLock.release()
- @staticmethod
- def failcount_increase():
- SyncY.EXLock.acquire()
- SyncY.failcount += 1
- SyncY.EXLock.release()
- @staticmethod
- def reset_counter():
- SyncY.EXLock.acquire()
- SyncY.synccount = 0
- SyncY.failcount = 0
- SyncY.errorcount = 0
- SyncY.EXLock.release()
- @staticmethod
- def __init_syncdata():
- SyncY.syncData = {}
- if os.path.exists(SyncY.syncydb):
- with open(SyncY.syncydb, 'rb') as sydb:
- flock(sydb, LOCK_SH)
- sydb.seek(64)
- datarec = sydb.read(64)
- while datarec:
- SyncY.syncData[datarec[0:16]] = datarec[16:]
- datarec = sydb.read(64)
- flock(sydb, LOCK_UN)
- def __check_expires(self):
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://openapi.baidu.com/rest/2.0/passport/users/getLoggedInUser', {}, {'access_token': SyncY.syncytoken['access_token']}, 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if 'uid' in responses:
- retcode, responses = sycurl.request('https://www.syncy.cn/syserver', {}, {'method': 'get_last_version', 'edition': 'python', 'ver': _VERSION, 'uid': responses['uid'], 'code': SyncY.syncytoken['device_code']}, 'POST', SYCurl.Normal)
- if retcode == 200 and responses.find('#') > -1:
- (lastver, smessage) = responses.strip('\n').split('#', 1)
- if lastver > _VERSION:
- printlog('%s WARNING: %s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), smessage.encode(_CHARSET)))
- if (SyncY.syncytoken['refresh_date'] + SyncY.syncytoken['expires_in'] - 864000) > int(time.time()):
- return
- retcode, responses = sycurl.request('https://www.syncy.cn/syserver', {}, {'method': 'refresh_access_token', 'refresh_token': SyncY.syncytoken['refresh_token'], 'code': SyncY.syncytoken['device_code']}, 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- printlog('%s ERROR(Errno:%d): Refresh access token failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, responses['error_msg']))
- return 1
- SyncY.syncytoken['refresh_token'] = responses['refresh_token']
- SyncY.syncytoken['access_token'] = responses['access_token']
- SyncY.syncytoken['expires_in'] = int(responses['expires_in'])
- SyncY.syncytoken['refresh_date'] = int(time.time())
- self.__save_config()
- printlog('%s INFO: Refresh access token success.' % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
- return 0
- @staticmethod
- def __save_config():
- with open('%s.tmp' % _CONFIG_FILE, 'w') as sycfg:
- sycfg.write("\nconfig syncy\n")
- for key, value in SyncY.config.items():
- sycfg.write("\toption %s '%s'\n" % (key, str(value)))
- sycfg.write("\nconfig syncytoken\n")
- for key, value in SyncY.syncytoken.items():
- sycfg.write("\toption %s '%s'\n" % (key, str(value)))
- for i in range(len(SyncY.syncpath)):
- sycfg.write("\nconfig syncpath\n")
- for key, value in SyncY.syncpath[str(i)].items():
- sycfg.write("\toption %s '%s'\n" % (key, str(value)))
- sycfg.flush()
- os.fsync(sycfg.fileno())
- if os.path.exists('%s.tmp' % _CONFIG_FILE):
- pmeta = os.stat(_CONFIG_FILE)
- rename('%s.tmp' % _CONFIG_FILE, _CONFIG_FILE)
- if os.name == 'posix':
- os.lchown(_CONFIG_FILE, pmeta.st_uid, pmeta.st_gid)
- os.chmod(_CONFIG_FILE, pmeta.st_mode)
- @staticmethod
- def __catpath(*names):
- fullpath = '/'.join(names)
- fullpath = re.sub(r'/+', '/', fullpath)
- fullpath = re.sub(r'/$', '', fullpath)
- return fullpath
- @staticmethod
- def __get_newname(oldname):
- nowtime = str(time.strftime("%Y%m%d%H%M%S", time.localtime()))
- m = SyncY.syre['newname'].findall(oldname)
- if m:
- newname = m[0][0] + '_old_' + nowtime + m[0][1]
- else:
- newname = oldname + '_old_' + nowtime
- return newname
- @staticmethod
- def __check_pcspath(pcsdirname, pcsfilename):
- if len(pcsdirname) + len(pcsfilename) + 1 >= 1000:
- printlog('%s ERROR: Length of PCS path(%s/%s) must less than 1000, skip upload.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), pcsdirname, pcsfilename))
- return 1
- if SyncY.syre['pcspath'].findall(pcsfilename):
- printlog('%s ERROR: PCS path(%s/%s) is invalid, please check whether special characters exists in the path, skip upload the file.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), pcsdirname, pcsfilename))
- return 1
- return 0
- @staticmethod
- def __get_pcs_quota():
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/quota', {'method': 'info', 'access_token': SyncY.syncytoken['access_token']}, '', 'GET', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- printlog('%s ERROR(Errno:%d): Get pcs quota failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, responses['error_msg']))
- return 1
- printlog('%s INFO: PCS quota is %dG,used %dG.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), responses['quota'] / 1024 / 1024 / 1024, responses['used'] / 1024 / 1024 / 1024))
- return 0
- @staticmethod
- def __get_pcs_filelist(pcspath, startindex, endindex):
- if _DEBUG:
- printlog('%s Info(%s): Start get pcs file list(%d-%d) of "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), threading.currentThread().name, startindex, endindex, pcspath))
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/file', {'method': 'list', 'access_token': SyncY.syncytoken['access_token'], 'path': pcspath, 'limit': '%d-%d' % (startindex, endindex), 'by': 'name', 'order': 'asc'}, '', 'GET', SYCurl.Normal)
- try:
- responses = json.loads(responses)
- if retcode != 200:
- if responses['error_code'] == 31066:
- return 31066, []
- else:
- printlog('%s ERROR(Errno:%d): Get PCS file list of "%s" failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, pcspath, responses['error_msg']))
- return 1, []
- return 0, responses['list']
- except Exception, e:
- printlog('%s ERROR: Get PCS file list of "%s" failed. return code: %d, response body: %s.\n%s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), pcspath, retcode, str(responses), e, traceback.format_exc()))
- return 1, []
- finally:
- del responses
- if _DEBUG:
- printlog('%s Info(%s): Complete get pcs file list(%d-%d) of "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), threading.currentThread().name, startindex, endindex, pcspath))
- @staticmethod
- def __check_create_pcsdir(pcspath):
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/file', {'method': 'meta', 'access_token': SyncY.syncytoken['access_token'], 'path': pcspath}, '', 'GET', SYCurl.Normal)
- try:
- responses = json.loads(responses)
- if retcode == 200 and responses['list'][0]['isdir'] == 1:
- return 0
- elif (retcode != 200 and responses['error_code'] == 31066) or (retcode == 200 and responses['list'][0]['isdir'] == 0):
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/file', {'method': 'mkdir', 'access_token': SyncY.syncytoken['access_token'], 'path': pcspath}, '', 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode == 200 and responses['path'].encode(_CHARSET) == pcspath:
- return 0
- printlog('%s ERROR(Errno:%d): Create PCS directory "%s" failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, pcspath, responses['error_msg']))
- return 1
- except Exception, e:
- printlog('%s ERROR: Create PCS directory "%s" failed. return code: %d, response body: %s.\n%s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), pcspath, retcode, str(responses), e, traceback.format_exc()))
- return 1
- def __rm_localfile(self, delpath, slient=False):
- try:
- if os.path.isfile(delpath):
- os.remove(delpath)
- if not slient:
- printlog('%s INFO: Delete local file "%s" completed.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), delpath))
- elif os.path.isdir(delpath):
- fnlist = os.listdir(delpath)
- for i in xrange(len(fnlist)):
- self.__rm_localfile('%s/%s' % (delpath, fnlist[i]), slient)
- os.rmdir(delpath)
- if not slient:
- printlog('%s INFO: Delete local directory "%s" completed.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), delpath))
- except Exception, e:
- if not slient:
- printlog('%s ERROR: Delete local file "%s" failed. %s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), delpath, e, traceback.format_exc()))
- return 1
- return 0
- @staticmethod
- def __rm_pcsfile(pcspath, slient=False):
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/file', {'method': 'delete', 'access_token': SyncY.syncytoken['access_token'], 'path': pcspath}, '', 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- if not slient:
- printlog('%s ERROR(Errno:%d): Delete remote file or directory "%s" failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, pcspath, responses['error_msg']))
- return 1
- if not slient:
- printlog('%s INFO: Delete remote file or directory "%s" completed.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), pcspath))
- return 0
- @staticmethod
- def __mv_pcsfile(oldpcspath, newpcspath, slient=False):
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/file', {'method': 'move', 'access_token': SyncY.syncytoken['access_token'], 'from': oldpcspath, 'to': newpcspath}, '', 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- if not slient:
- printlog('%s ERROR(Errno:%d): Move remote file or directory "%s" to "%s" failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, oldpcspath, newpcspath, responses['error_msg']))
- return 1
- if not slient:
- printlog('%s INFO: Move remote file or directory "%s" to "%s" completed.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), oldpcspath, newpcspath))
- return 0
- @staticmethod
- def __cp_pcsfile(srcpcspath, destpcspath):
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/file', {'method': 'copy', 'access_token': SyncY.syncytoken['access_token'], 'from': srcpcspath, 'to': destpcspath}, '', 'POST', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- printlog('%s ERROR(Errno:%d): Copy remote file or directory "%s" to "%s" failed: %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, srcpcspath, destpcspath, responses['error_msg']))
- return 1
- printlog('%s INFO: Copy remote file or directory "%s" to "%s" completed.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), srcpcspath, destpcspath))
- return 0
- @staticmethod
- def __get_pcs_filemeta(pcspath):
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://pcs.baidu.com/rest/2.0/pcs/file', {'method': 'meta', 'access_token': SyncY.syncytoken['access_token'], 'path': pcspath}, '', 'GET', SYCurl.Normal)
- responses = json.loads(responses)
- if retcode != 200:
- printlog('%s ERROR(Errno:%d): Get file\'s meta failed: %s, %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, pcspath, responses['error_msg']))
- return 1, {}
- return 0, responses['list'][0]
- @staticmethod
- def __upload_file_nosync(filepath, pcspath):
- sycurl = SYCurl()
- retcode, responses = sycurl.request('https://c.pcs.baidu.com/rest/2.0/pcs/file', {'method': 'upload', 'access_token': SyncY.syncytoken['access_token'], 'path': pcspath, 'ondup': 'newcopy'}, '0-%d' % (os.stat(filepath).st_size - 1), 'POST', SYCurl.Upload, filepath)
- responses = json.loads(responses)
- if retcode != 200:
- printlog('%s ERROR(Errno:%d): Upload file to pcs failed: %s, %s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), retcode, filepath, responses['error_msg']))
- return 1
- printlog('%s INFO: Upload file "%s" completed.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), filepath))
- return 0
- def __compress_data(self, pathname, sydbnew, sydb=None, sydblen=0):
- fnlist = os.listdir(pathname)
- fnlist.sort()
- for fnname in fnlist:
- if fnname[0:1] == '.':
- continue
- fullpath = '%s/%s' % (pathname, fnname)
- if os.path.isdir(fullpath):
- if SyncY.config['datacache'] == 'on':
- self.__compress_data(fullpath, sydbnew)
- else:
- self.__compress_data(fullpath, sydbnew, sydb, sydblen)
- elif os.path.isfile(fullpath):
- fnmd5 = hashlib.md5(fullpath[SyncY.basedirlen:]).digest()
- fnstat = os.stat(fullpath)
- fmate = struct.pack('>qq', int(fnstat.st_mtime), fnstat.st_size)
- if SyncY.config['datacache'] == 'on':
- if fnmd5 in SyncY.syncData and SyncY.syncData[fnmd5][0:16] == fmate:
- sydbnew.write('%s%s' % (fnmd5, SyncY.syncData[fnmd5]))
- del SyncY.syncData[fnmd5]
- else:
- if sydb.tell() == sydblen:
- sydb.seek(64)
- datarec = sydb.read(64)
- readlen = 64
- while datarec and readlen <= sydblen - 64:
- if datarec[0:32] == '%s%s' % (fnmd5, fmate):
- sydbnew.write(datarec)
- break
- if readlen == sydblen - 64:
- break
- if sydb.tell() == sydblen:
- sydb.seek(64)
- datarec = sydb.read(64)
- readlen += 64
- return 0
- def __start_compress(self, pathname=''):
- if pathname == '':
- mpath = []
- for i in range(len(SyncY.syncpath)):
- if SyncY.syncpath[str(i)]['synctype'].lower() not in ['4', 's', 'sync']:
- mpath.append(SyncY.syncpath[str(i)]['localpath'])
- printlog('%s INFO: Start compress sync data.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- else:
- mpath = [pathname]
- for ipath in mpath:
- if ipath == '':
- continue
- SyncY.basedirlen = len(ipath)
- SyncY.syncydb = '%s/.syncy.info.db' % ipath
- newdbfile = '%s/.syncy.info.dbtmp' % ipath
- if os.path.exists(SyncY.syncydb):
- if os.path.exists(newdbfile):
- os.remove(newdbfile)
- self.__check_upgrade_syncdata(newdbfile)
- with open(newdbfile, 'ab') as sydbnew:
- if SyncY.config['datacache'] == 'on':
- self.__init_syncdata()
- self.__compress_data(ipath, sydbnew)
- SyncY.syncData = None
- else:
- sydblen = os.stat(SyncY.syncydb).st_size
- with open(SyncY.syncydb, 'rb') as sydb:
- self.__compress_data(ipath, sydbnew, sydb, sydblen)
- sydbnew.flush()
- os.fsync(sydbnew.fileno())
- rename(newdbfile, SyncY.syncydb)
- if pathname == '':
- SyncY.syncytoken['compress_date'] = int(time.time())
- SyncY.syncytoken['synctotal'] = 0
- self.__save_config()
- printlog('%s INFO: Sync data compress completed.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
- def __check_excludefiles(self, filepath):
- for reexf in self._excludefiles:
- if reexf.findall(filepath):
- return 1
- return 0
- @staticmethod
- def __check_syncstatus(fmd5, fmate, rmate, rmd5):
- if rmd5 != '*':
- rmd5 = rmd5.decode('hex')
- if SyncY.config['datacache'] == 'on':
- if fmd5 not in SyncY.syncData:
- return 0
- if rmd5 == '*' and rmate == '*' and SyncY.syncData[fmd5][0:16] == fmate:
- return 1
- elif fmate == '*' and SyncY.syncData[fmd5][16:] == rmate + rmd5:
- return 1
- elif SyncY.syncData[fmd5] == fmate + rmate + rmd5:
- return 1
- else:
- if SyncY.sydb.tell() == SyncY.sydblen:
- SyncY.sydb.seek(64)
- datarec = SyncY.sydb.read(64)
- readlen = 64
- while datarec and readlen <= SyncY.sydblen - 64:
- if rmd5 == '*' and rmate == '*' and datarec[0:32] == fmd5 + fmate:
- return 1
- elif fmate == '*' and datarec[16:] == rmate + rmd5:
- return 1
- elif datarec == fmd5 + fmate + rmate + rmd5:
- return 1
- if readlen == SyncY.sydblen - 64:
- break
- if SyncY.sydb.tell() == SyncY.sydblen:
- SyncY.sydb.seek(64)
- datarec = SyncY.sydb.read(64)
- readlen += 64
- return 0
- def __syncy_upload(self, ldir, rdir):
- fnlist = os.listdir(ldir)
- fnlist.sort()
- for fi in xrange(len(fnlist)):
- lfullpath = '%s/%s' % (ldir, fnlist[fi])
- fmtime = 0
- fsize = 0
- try:
- if fnlist[fi][0:1] == '.' or self.__check_excludefiles(lfullpath) == 1 or self.__check_pcspath(rdir, fnlist[fi]) == 1:
- continue
- if _DEBUG:
- printlog('%s Info(%s): Start upload "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), threading.currentThread().name, lfullpath))
- rfullpath = '%s/%s' % (rdir, fnlist[fi])
- if os.path.isdir(lfullpath):
- self.__syncy_upload(lfullpath, rfullpath)
- else:
- fmeta = os.stat(lfullpath)
- fmtime = int(fmeta.st_mtime)
- fsize = fmeta.st_size
- fnmd5 = hashlib.md5(lfullpath[SyncY.basedirlen:]).digest()
- if self.__check_syncstatus(fnmd5, struct.pack('>qq', fmtime, fsize), '*', '*') == 0:
- if SyncY.config['ondup'] == 'rename':
- ondup = 'newcopy'
- else:
- ondup = 'overwrite'
- if SyncY.TaskSemaphore.acquire():
- synctask = SYTask(SYTask.Upload, lfullpath, int(fmeta.st_mtime), fmeta.st_size, fnmd5, rfullpath, 0, 0, '', ondup)
- synctask.start()
- else:
- continue
- except struct.error, e:
- printlog('%s ERROR: Struct.pack upload file mate(mtime:%d,size:%d) of "%s" error: %s\n%s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), fmtime, fsize, lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
- return 1
- except Exception, e:
- printlog('%s ERROR: Upload file "%s" failed. %s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
- return 1
- return 0
- def __syncy_uploadplus(self, ldir, rdir):
- startidx = 0
- retcode, rfnlist = self.__get_pcs_filelist(rdir, startidx, SyncY.config['listnumber'])
- if retcode != 0 and retcode != 31066:
- self.errorcount_increase()
- return 1
- lfnlist = os.listdir(ldir)
- lfnlist.sort()
- while retcode == 0:
- for i in xrange(len(rfnlist)):
- rfullpath = rfnlist[i]['path'].encode(_CHARSET)
- fnname = os.path.basename(rfullpath)
- lfullpath = '%s/%s' % (ldir, fnname)
- try:
- if self.__check_excludefiles(lfullpath) == 1:
- continue
- if os.path.exists(lfullpath):
- for idx in xrange(len(lfnlist)):
- if lfnlist[idx] == fnname:
- del lfnlist[idx]
- break
- else:
- continue
- if _DEBUG:
- printlog('%s Info(%s): Start upload+ "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), threading.currentThread().name, lfullpath))
- if (rfnlist[i]['isdir'] == 1 and os.path.isfile(lfullpath)) or (rfnlist[i]['isdir'] == 0 and os.path.isdir(lfullpath)):
- if SyncY.config['ondup'] == 'rename':
- fnnamenew = '%s/%s' % (rdir, self.__get_newname(fnname))
- if len(fnnamenew) >= 1000:
- printlog('%s ERROR: Rename failed, the length of PCS path "%s" must less than 1000, skip upload "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), fnnamenew, lfullpath))
- self.failcount_increase()
- continue
- if self.__mv_pcsfile(rfullpath, fnnamenew, True) == 1:
- printlog('%s ERROR: Rename "%s" failed, skip upload "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), rfullpath, lfullpath))
- self.errorcount_increase()
- continue
- else:
- self.__rm_pcsfile(rfullpath, True)
- if os.path.isdir(lfullpath):
- self.__syncy_uploadplus(lfullpath, rfullpath)
- continue
- else:
- fmeta = os.stat(lfullpath)
- fnmd5 = hashlib.md5(lfullpath[SyncY.basedirlen:]).digest()
- if SyncY.TaskSemaphore.acquire():
- synctask = SYTask(SYTask.Upload, lfullpath, int(fmeta.st_mtime), fmeta.st_size, fnmd5, rfullpath, 0, 0, '', 'overwrite')
- synctask.start()
- elif rfnlist[i]['isdir'] == 1:
- self.__syncy_uploadplus(lfullpath, rfullpath)
- continue
- else:
- fmeta = os.stat(lfullpath)
- fnmd5 = hashlib.md5(lfullpath[SyncY.basedirlen:]).digest()
- if self.__check_syncstatus(fnmd5, struct.pack('>qq', int(fmeta.st_mtime), fmeta.st_size), struct.pack('>qq', rfnlist[i]['mtime'], rfnlist[i]['size']), rfnlist[i]['md5']) == 1:
- continue
- if SyncY.config['ondup'] == 'rename':
- fnnamenew = '%s/%s' % (rdir, self.__get_newname(fnname))
- if len(fnnamenew) >= 1000:
- printlog('%s ERROR: Rename failed, the length of PCS path "%s" must less than 1000, skip upload "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), fnnamenew, lfullpath))
- self.failcount_increase()
- continue
- if self.__mv_pcsfile(rfullpath, fnnamenew, True) == 1:
- printlog('%s ERROR: Rename "%s" failed, skip upload "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), rfullpath, lfullpath))
- self.failcount_increase()
- continue
- else:
- self.__rm_pcsfile(rfullpath, True)
- if SyncY.TaskSemaphore.acquire():
- synctask = SYTask(SYTask.Upload, lfullpath, int(fmeta.st_mtime), fmeta.st_size, fnmd5, rfullpath, 0, 0, '', 'overwrite')
- synctask.start()
- except struct.error, e:
- printlog('%s ERROR: Struct.pack file mate of "%s" error: %s\n%s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
- return 1
- except Exception, e:
- printlog('%s ERROR: Upload file "%s" failed. %s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
- return 1
- if len(rfnlist) < SyncY.config['listnumber']:
- break
- startidx += SyncY.config['listnumber']
- retcode, rfnlist = self.__get_pcs_filelist(rdir, startidx, startidx + SyncY.config['listnumber'])
- if retcode != 0:
- self.errorcount_increase()
- return 1
- for idx in xrange(len(lfnlist)):
- lfullpath = '%s/%s' % (ldir, lfnlist[idx])
- try:
- if lfnlist[idx][0:1] == '.' or self.__check_excludefiles(lfullpath) == 1 or self.__check_pcspath(rdir, lfnlist[idx]) == 1:
- continue
- rfullpath = '%s/%s' % (rdir, lfnlist[idx])
- if os.path.isdir(lfullpath):
- self.__syncy_uploadplus(lfullpath, rfullpath)
- elif os.path.isfile(lfullpath):
- fmeta = os.stat(lfullpath)
- fnmd5 = hashlib.md5(lfullpath[SyncY.basedirlen:]).digest()
- if SyncY.TaskSemaphore.acquire():
- synctask = SYTask(SYTask.Upload, lfullpath, int(fmeta.st_mtime), fmeta.st_size, fnmd5, rfullpath, 0, 0, '', 'overwrite')
- synctask.start()
- except struct.error, e:
- printlog('%s ERROR: Struct.pack file mate of "%s" error: %s\n%s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
- return 1
- except Exception, e:
- printlog('%s ERROR: Upload file "%s" failed. %s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
- return 1
- return 0
- def __syncy_download(self, ldir, rdir):
- startidx = 0
- retcode, rfnlist = self.__get_pcs_filelist(rdir, startidx, SyncY.config['listnumber'])
- if retcode != 0:
- self.errorcount_increase()
- return 1
- while retcode == 0:
- for i in xrange(len(rfnlist)):
- rfullpath = rfnlist[i]['path'].encode(_CHARSET)
- fnname = os.path.basename(rfullpath)
- if self.__check_excludefiles(rfullpath) == 1:
- continue
- lfullpath = '%s/%s' % (ldir, fnname)
- try:
- if _DEBUG:
- printlog('%s Info(%s): Start download "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), threading.currentThread().name, rfullpath))
- if rfnlist[i]['isdir'] == 1:
- if os.path.exists(lfullpath) and os.path.isfile(lfullpath):
- if SyncY.config['ondup'] == 'rename':
- fnnamenew = '%s/%s' % (ldir, self.__get_newname(fnname))
- rename(lfullpath, fnnamenew)
- else:
- if self.__rm_localfile(lfullpath, True) == 1:
- printlog('%s ERROR: Delete local file "%s" failed, skip download "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, rfullpath))
- self.errorcount_increase()
- continue
- if not (os.path.exists(lfullpath)):
- os.mkdir(lfullpath)
- if os.name == 'posix':
- pmeta = os.stat(ldir)
- os.lchown(lfullpath, pmeta.st_uid, pmeta.st_gid)
- os.chmod(lfullpath, pmeta.st_mode)
- self.__syncy_download(lfullpath, rfullpath)
- else:
- fnmd5 = hashlib.md5(lfullpath[SyncY.basedirlen:]).digest()
- if not (os.path.exists(lfullpath + '.db.syy')):
- if self.__check_syncstatus(fnmd5, '*', struct.pack('>qq', rfnlist[i]['mtime'], rfnlist[i]['size']), rfnlist[i]['md5']) == 1:
- continue
- if os.path.exists(lfullpath) and SyncY.config['ondup'] == 'rename':
- fnnamenew = '%s/%s' % (ldir, self.__get_newname(fnname))
- rename(lfullpath, fnnamenew)
- elif os.path.exists(lfullpath):
- if self.__rm_localfile(lfullpath, True) == 1:
- printlog('%s ERROR: Delete local file "%s" failed, skip download "%s".' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, rfullpath))
- self.failcount_increase()
- continue
- if SyncY.TaskSemaphore.acquire():
- synctask = SYTask(SYTask.Download, lfullpath, 0, 0, fnmd5, rfullpath, rfnlist[i]['mtime'], rfnlist[i]['size'], rfnlist[i]['md5'], 'overwrite')
- synctask.start()
- except struct.error, e:
- printlog('%s ERROR: Struct.pack file mate of "%s" error: %s\n%s.' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
- return 1
- except Exception, e:
- printlog('%s ERROR: Download file "%s" failed. %s\n%s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), lfullpath, e, traceback.format_exc()))
- self.errorcount_increase()
-