1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# Copyright 2007, Red Hat, Inc
# seth vidal
#
# This software may be freely redistributed under the terms of the GNU
# general public license.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sha
import os
import time
import shutil
from modules import func_module
class CopyFile(func_module.FuncModule):
def __init__(self):
self.methods = {
"copyfile" : self.copyfile,
"checksum" : self.checksum
}
func_module.FuncModule.__init__(self)
def checksum(self, thing):
CHUNK=2**16
thissum = sha.new()
if os.path.exists(thing):
fo = open(thing, 'r', CHUNK)
chunk = fo.read
while chunk:
chunk = fo.read(CHUNK)
thissum.update(chunk)
fo.close()
del fo
else:
# assuming it's a string of some kind
thissum.update(thing)
return thissum.hexdigest()
def copyfile(self, filepath, filebuf, mode=0644, uid=0, gid=0, force=None):
# -1 = problem file was not copied
# 1 = file was copied
# 0 = file was not copied b/c file is unchanged
# we should probably verify mode,uid,gid are valid as well
dirpath = os.path.dirname(filepath)
basepath = os.path.basename(filepath)
if not os.path.exists(dirpath):
os.makedirs(dirpath)
remote_sum = self.checksum(filebuf)
local_sum = 0
if os.path.exists(filepath):
local_sum = self.checksum(filepath)
if remote_sum != local_sum or force is not None:
# back up the localone
if os.path.exists(filepath):
if not self._backuplocal(filepath):
return -1
# do the new write
try:
fo = open(filepath, 'w')
fo.write(filebuf)
fo.close()
del fo
except (IOError, OSError), e:
# XXX logger output here
return -1
else:
return 0
# hmm, need to figure out proper exceptions -akl
try:
# we could intify the mode here if it's a string
os.chmod(filepath, mode)
os.chown(filepath, uid, gid)
except (IOError, OSError), e:
return -1
return 1
def _backuplocal(self, fn):
"""
make a date-marked backup of the specified file,
return True or False on success or failure
"""
# backups named basename-YYYY-MM-DD@HH:MM~
ext = time.strftime("%Y-%m-%d@%H:%M~", time.localtime(time.time()))
backupdest = '%s.%s' % (fn, ext)
try:
shutil.copy2(fn, backupdest)
except shutil.Error, e:
#XXX logger output here
return False
return True
methods = CopyFile()
register_rpc = methods.register_rpc
|