1101 remote file access from higher level code. |
1102 remote file access from higher level code. |
1102 """ |
1103 """ |
1103 p = base |
1104 p = base |
1104 audit_p = audit |
1105 audit_p = audit |
1105 |
1106 |
1106 def mktempcopy(name): |
1107 def mktempcopy(name, emptyok=False): |
1107 d, fn = os.path.split(name) |
1108 d, fn = os.path.split(name) |
1108 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d) |
1109 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d) |
1109 os.close(fd) |
1110 os.close(fd) |
1110 ofp = posixfile(temp, "wb") |
1111 # Temporary files are created with mode 0600, which is usually not |
|
1112 # what we want. If the original file already exists, just copy |
|
1113 # its mode. Otherwise, manually obey umask. |
|
1114 try: |
|
1115 st_mode = os.lstat(name).st_mode |
|
1116 except OSError, inst: |
|
1117 if inst.errno != errno.ENOENT: |
|
1118 raise |
|
1119 st_mode = 0666 & ~_umask |
|
1120 os.chmod(temp, st_mode) |
|
1121 if emptyok: |
|
1122 return temp |
1111 try: |
1123 try: |
1112 try: |
1124 try: |
1113 ifp = posixfile(name, "rb") |
1125 ifp = posixfile(name, "rb") |
1114 except IOError, inst: |
1126 except IOError, inst: |
|
1127 if inst.errno == errno.ENOENT: |
|
1128 return temp |
1115 if not getattr(inst, 'filename', None): |
1129 if not getattr(inst, 'filename', None): |
1116 inst.filename = name |
1130 inst.filename = name |
1117 raise |
1131 raise |
|
1132 ofp = posixfile(temp, "wb") |
1118 for chunk in filechunkiter(ifp): |
1133 for chunk in filechunkiter(ifp): |
1119 ofp.write(chunk) |
1134 ofp.write(chunk) |
1120 ifp.close() |
1135 ifp.close() |
1121 ofp.close() |
1136 ofp.close() |
1122 except: |
1137 except: |
1123 try: os.unlink(temp) |
1138 try: os.unlink(temp) |
1124 except: pass |
1139 except: pass |
1125 raise |
1140 raise |
1126 st = os.lstat(name) |
|
1127 os.chmod(temp, st.st_mode) |
|
1128 return temp |
1141 return temp |
1129 |
1142 |
1130 class atomictempfile(posixfile): |
1143 class atomictempfile(posixfile): |
1131 """the file will only be copied when rename is called""" |
1144 """the file will only be copied when rename is called""" |
1132 def __init__(self, name, mode): |
1145 def __init__(self, name, mode): |
1133 self.__name = name |
1146 self.__name = name |
1134 self.temp = mktempcopy(name) |
1147 self.temp = mktempcopy(name, emptyok=('w' in mode)) |
1135 posixfile.__init__(self, self.temp, mode) |
1148 posixfile.__init__(self, self.temp, mode) |
1136 def rename(self): |
1149 def rename(self): |
1137 if not self.closed: |
1150 if not self.closed: |
1138 posixfile.close(self) |
1151 posixfile.close(self) |
1139 rename(self.temp, localpath(self.__name)) |
1152 rename(self.temp, localpath(self.__name)) |
1163 |
1176 |
1164 if mode[0] != "r": |
1177 if mode[0] != "r": |
1165 try: |
1178 try: |
1166 nlink = nlinks(f) |
1179 nlink = nlinks(f) |
1167 except OSError: |
1180 except OSError: |
|
1181 nlink = 0 |
1168 d = os.path.dirname(f) |
1182 d = os.path.dirname(f) |
1169 if not os.path.isdir(d): |
1183 if not os.path.isdir(d): |
1170 os.makedirs(d) |
1184 os.makedirs(d) |
1171 else: |
1185 if atomic: |
1172 if atomic: |
1186 return atomicfile(f, mode) |
1173 return atomicfile(f, mode) |
1187 elif atomictemp: |
1174 elif atomictemp: |
1188 return atomictempfile(f, mode) |
1175 return atomictempfile(f, mode) |
1189 if nlink > 1: |
1176 if nlink > 1: |
1190 rename(mktempcopy(f), f) |
1177 rename(mktempcopy(f), f) |
|
1178 return posixfile(f, mode) |
1191 return posixfile(f, mode) |
1179 |
1192 |
1180 return o |
1193 return o |
1181 |
1194 |
1182 class chunkbuffer(object): |
1195 class chunkbuffer(object): |