Given the member, write the TAR header & copy the file */
| 1142 | |
| 1143 | /* Given the member, write the TAR header & copy the file */ |
| 1144 | static void |
| 1145 | _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th) |
| 1146 | { |
| 1147 | lclContext *ctx = (lclContext *) AH->formatData; |
| 1148 | FILE *tmp = th->tmpFH; /* Grab it for convenience */ |
| 1149 | char buf[32768]; |
| 1150 | size_t cnt; |
| 1151 | pgoff_t len = 0; |
| 1152 | size_t res; |
| 1153 | size_t i, |
| 1154 | pad; |
| 1155 | |
| 1156 | /* |
| 1157 | * Find file len & go back to start. |
| 1158 | */ |
| 1159 | if (fseeko(tmp, 0, SEEK_END) != 0) |
| 1160 | fatal("error during file seek: %m"); |
| 1161 | th->fileLen = ftello(tmp); |
| 1162 | if (th->fileLen < 0) |
| 1163 | fatal("could not determine seek position in archive file: %m"); |
| 1164 | if (fseeko(tmp, 0, SEEK_SET) != 0) |
| 1165 | fatal("error during file seek: %m"); |
| 1166 | |
| 1167 | _tarWriteHeader(th); |
| 1168 | |
| 1169 | while ((cnt = fread(buf, 1, sizeof(buf), tmp)) > 0) |
| 1170 | { |
| 1171 | if ((res = fwrite(buf, 1, cnt, th->tarFH)) != cnt) |
| 1172 | WRITE_ERROR_EXIT; |
| 1173 | len += res; |
| 1174 | } |
| 1175 | if (!feof(tmp)) |
| 1176 | READ_ERROR_EXIT(tmp); |
| 1177 | |
| 1178 | if (fclose(tmp) != 0) /* This *should* delete it... */ |
| 1179 | fatal("could not close temporary file: %m"); |
| 1180 | |
| 1181 | if (len != th->fileLen) |
| 1182 | { |
| 1183 | char buf1[32], |
| 1184 | buf2[32]; |
| 1185 | |
| 1186 | snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len); |
| 1187 | snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->fileLen); |
| 1188 | fatal("actual file length (%s) does not match expected (%s)", |
| 1189 | buf1, buf2); |
| 1190 | } |
| 1191 | |
| 1192 | pad = tarPaddingBytesRequired(len); |
| 1193 | for (i = 0; i < pad; i++) |
| 1194 | { |
| 1195 | if (fputc('\0', th->tarFH) == EOF) |
| 1196 | WRITE_ERROR_EXIT; |
| 1197 | } |
| 1198 | |
| 1199 | ctx->tarFHpos += len + pad; |
| 1200 | } |
| 1201 |
no test coverage detected