00001
00002
00003
00004 licenceEn="""
00005 file usbThread.py
00006 this file is part of the project scolasync
00007
00008 Copyright (C) 2010 Georges Khaznadar <georgesk@ofset.org>
00009
00010 This program is free software: you can redistribute it and/or modify
00011 it under the terms of the GNU General Public License as published by
00012 the Free Software Foundation, either version3 of the License, or
00013 (at your option) any later version.
00014
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018 GNU General Public License for more details.
00019
00020 You should have received a copy of the GNU General Public License
00021 along with this program. If not, see <http://www.gnu.org/licenses/>.
00022 """
00023
00024 import subprocess, threading, re, os.path, time, glob, shlex
00025 from PyQt4.QtCore import *
00026
00027 _threadNumber=0
00028
00029
00030
00031
00032
00033 class ThreadRegister:
00034
00035
00036
00037
00038
00039 def __init__(self):
00040 self.dico={}
00041
00042 def __str__(self):
00043 return "ThreadRegister: %s" %self.dico
00044
00045
00046
00047
00048
00049
00050
00051 def push(self, ud, thread):
00052 if ud.owner not in self.dico.keys():
00053 self.dico[ud.owner]=[thread]
00054 else:
00055 self.dico[ud.owner].append(thread)
00056
00057
00058
00059
00060
00061
00062
00063 def pop(self, ud, thread):
00064 self.dico[ud.owner].remove(thread)
00065
00066
00067
00068
00069
00070
00071
00072 def busy(self, owner):
00073 if owner in self.dico.keys():
00074 return self.dico[owner]
00075 return []
00076
00077
00078
00079
00080
00081 def threadSet(self):
00082 result=set()
00083 for o in self.dico.keys():
00084 for t in self.dico[o]:
00085 result.add(t)
00086 return result
00087
00088
00089
00090
00091
00092
00093
00094
00095 def _sanitizePath(path):
00096 pattern=re.compile(".*([^/]+)")
00097 m=pattern.match(str(path))
00098 if m:
00099 return m.group(1)
00100 else:
00101 return str(path).replace('/','_')
00102
00103
00104
00105
00106
00107
00108
00109
00110 def _threadName(ud):
00111 global _threadNumber
00112 name="th_%04d_%s" %(_threadNumber,_sanitizePath(ud.path))
00113 _threadNumber+=1
00114 return name
00115
00116
00117
00118
00119
00120
00121 def _date():
00122 return time.strftime("%Y/%m/%d-%H:%M:%S")
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 def _call(cmd, logfile, ud, parent=None):
00134 if parent:
00135 parent.emit(SIGNAL("pushCmd(QString, QString)"), ud.owner, cmd)
00136 for command in cmd.split(";"):
00137 retcode=subprocess.call(command, shell=True)
00138 msg="[%s] " %_date()
00139 if retcode==0:
00140 msg += "Success: "
00141 else:
00142 msg += "Error: "
00143 msg += command
00144 if parent:
00145 parent.emit(SIGNAL("popCmd(QString, QString)"), ud.owner, cmd+msg)
00146
00147
00148
00149
00150
00151
00152
00153 class abstractThreadUSB(threading.Thread):
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 def __init__(self,ud, fileList, subdir, dest=None, logfile="/dev/null",
00167 parent=None):
00168 threading.Thread.__init__(self,target=self.toDo,
00169 args=(ud, fileList, subdir, dest, logfile),
00170 name=_threadName(ud))
00171 self.cmd=u"echo This is an abstract method, don't call it"
00172 self.ud=ud
00173 ud.threadRunning=True
00174 self.fileList=fileList
00175 self.subdir=subdir
00176 self.dest=dest
00177 self.logfile=logfile
00178 self.parent=parent
00179
00180
00181
00182
00183
00184
00185
00186 def __str__(self):
00187 result="%s(\n" %self.threadType()
00188 result+=" ud = %s\n" %self.ud
00189 result+=" fileList = %s\n" %self.fileList
00190 result+=" subdir = %s\n" %self.subdir
00191 result+=" dest = %s\n" %self.dest
00192 result+=" logfile = %s\n" %self.logfile
00193 result+=" cmd = %s\n" %self.cmd
00194 result+="\n"
00195 return result
00196
00197
00198
00199
00200
00201 def threadType(self):
00202 return "abstractThreadUSB"
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 def toDo(self, ud, fileList, subdir, dest, logfile):
00214
00215 pass
00216
00217
00218
00219
00220
00221
00222
00223
00224 def protectPath(self, s):
00225 if "*" in s or "?" in s:
00226 return s
00227 else:
00228 return u'"%s"' %s
00229
00230
00231
00232
00233
00234 class threadCopyToUSB(abstractThreadUSB):
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 def __init__(self,ud, fileList, subdir, logfile="/dev/null",
00247 parent=None):
00248 abstractThreadUSB.__init__(self,ud, fileList, subdir, dest=None, logfile=logfile, parent=parent)
00249 self.cmd=u'mkdir -p "{toDir}"; cp -R {fromFile} "{toDir}"'
00250
00251
00252
00253
00254
00255 def threadType(self):
00256 return "threadCopyToUSB"
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 def toDo(self, ud, fileList, subdir, dest, logfile):
00271 while subdir[0]=='/':
00272 subdir=subdir[1:]
00273 destpath=os.path.join(ud.ensureMounted(),ud.visibleDir(),subdir)
00274 for f in fileList:
00275 fileName=os.path.basename(f)
00276 cmd=self.cmd.format(fromFile=f,
00277 toDir=destpath)
00278 _call(cmd, logfile, ud, self.parent)
00279
00280
00281
00282
00283
00284 class threadCopyFromUSB(abstractThreadUSB):
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 def __init__(self,ud, fileList, subdir=".", dest="/tmp",
00299 rootPath="/", logfile="/dev/null", parent=None):
00300 abstractThreadUSB.__init__(self,ud, fileList, subdir, dest=dest,
00301 logfile=logfile, parent=parent)
00302 self.rootPath=rootPath
00303 self.cmd=u'mkdir -p "{toPath}"; cp -R {fromPath} "{toPath}"'
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 def toDo(self, ud, fileList, subdir, dest, logfile):
00317
00318 for f in fileList:
00319
00320 fromPath=self.protectPath(os.path.join(ud.ensureMounted(), f))
00321 owner=ud.ownerByDb()
00322
00323 newName=u"%s_%s" %(owner,os.path.dirname(f))
00324
00325 toPath=os.path.join(dest,newName)
00326 cmd=self.cmd.format(fromPath=fromPath, toPath=toPath)
00327 _call(cmd,logfile, ud, self.parent)
00328
00329
00330
00331
00332
00333 class threadMoveFromUSB(abstractThreadUSB):
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 def __init__(self,ud, fileList, subdir=".", dest="/tmp",
00348 rootPath="/", logfile="/dev/null", parent=None):
00349 abstractThreadUSB.__init__(self,ud, fileList, subdir, dest=dest,
00350 logfile=logfile, parent=parent)
00351 self.rootPath=rootPath
00352 self.cmd=u'mkdir -p "{toPath}"; cp -R {fromPath} "{toPath}" && rm -rf {fromPath}'
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 def toDo(self, ud, fileList, subdir, dest, logfile):
00367 for f in fileList:
00368
00369 fromPath=self.protectPath(os.path.join(ud.ensureMounted(), f))
00370 owner=ud.ownerByDb()
00371
00372 newName=u"%s_%s" %(owner,os.path.dirname(f))
00373
00374 toPath=os.path.join(dest,newName)
00375 cmd=self.cmd.format(fromPath=fromPath, toPath=toPath)
00376 _call(cmd,logfile, ud, self.parent)
00377
00378
00379
00380
00381
00382 class threadDeleteInUSB(abstractThreadUSB):
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 def __init__(self,ud, fileList, subdir, logfile="/dev/null",
00395 parent=None):
00396 abstractThreadUSB.__init__(self,ud, fileList, subdir, dest=None,
00397 logfile=logfile, parent=parent)
00398 self.cmd=u'rm -rf {toDel}'
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 def toDo(self, ud, fileList, subdir, dest, logfile):
00414 for f in fileList:
00415 toDel=os.path.join(ud.ensureMounted(), f)
00416 cmd=self.cmd.format(toDel=toDel)
00417 _call(cmd,logfile, ud, self.parent)
00418