00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <pwd.h>
00019 #include <grp.h>
00020 #include "jsoc_main.h"
00021 #include "exputil.h"
00022
00023 #define USE_FITS_STRUCTS 1
00024 #include "fitsexport.h"
00025 #undef USE_FITS_STRUCTS
00026
00027
00028 #include "fitsio.h"
00029
00030 char *module_name = "drms-export-to-stdout";
00031
00032 #define ARG_RS_SPEC "spec"
00033 #define ARG_KEYMAP_CLASS "mapclass"
00034 #define ARG_KEYMAP_FILE "mapfile"
00035 #define ARG_FILE_TEMPLATE "ffmt"
00036 #define ARG_CPARMS_STRING "cparms"
00037 #define ARG_ACK_FILE "ackfile"
00038 #define ARG_MAX_TAR_FILE_SIZE "maxfilesize"
00039 #define ARG_COMPRESS_ALL_SEGS "a"
00040 #define ARG_DO_NOT_CREATE_TAR "s"
00041
00042
00043
00044 #define FILE_LIST_PATH "jsoc/file_list.txt"
00045 #define ERROR_LIST_PATH "jsoc/error_list.txt"
00046 #define ERROR_PATH "jsoc/error.txt"
00047
00048 #define DEFAULT_MAX_TAR_FILE_SIZE "4294967296"
00049 #define MAX_MAX_TAR_FILE_SIZE 53687091200
00050 #define TAR_BLOCK_SIZE 512
00051 #define TAR_HEADER_SIZE 512
00052 #define ACK_FILE_BUFFER 96
00053
00054
00055 enum __ExpToStdoutStatus_enum__
00056 {
00057 ExpToStdoutStatus_Success = 0,
00058 ExpToStdoutStatus_InvalidArgs = 1,
00059 ExpToStdoutStatus_Dump = 2,
00060 ExpToStdoutStatus_OutOfMemory = 3,
00061 ExpToStdoutStatus_DumpPadding = 4,
00062 ExpToStdoutStatus_GetUser = 5,
00063 ExpToStdoutStatus_GetGroup = 6,
00064 ExpToStdoutStatus_IO = 7,
00065 ExpToStdoutStatus_BadFilenameTemplate = 8,
00066 ExpToStdoutStatus_DRMS = 9,
00067 ExpToStdoutStatus_Stdout = 10,
00068 ExpToStdoutStatus_TarTooLarge = 11,
00069 ExpToStdoutStatus_AllExportsFailed = 12
00070 };
00071
00072 typedef enum __ExpToStdoutStatus_enum__ ExpToStdoutStatus_t;
00073
00074
00075 #define COMPRESSION_NONE "none"
00076 #define COMPRESSION_RICE "rice"
00077 #define COMPRESSION_GZIP1 "gzip1"
00078 #define COMPRESSION_GZIP2 "gzip2"
00079 #define COMPRESSION_PLIO "plio"
00080 #define COMPRESSION_HCOMP "hcompress"
00081
00082
00083 enum __ExpToStdout_Compression_enum__
00084 {
00085 ExpToStdout_Compression_NONE = 0,
00086 ExpToStdout_Compression_RICE = RICE_1,
00087 ExpToStdout_Compression_GZIP1 = GZIP_1,
00088 ExpToStdout_Compression_GZIP2 = GZIP_2,
00089 ExpToStdout_Compression_PLIO = PLIO_1,
00090 ExpToStdout_Compression_HCOMP = HCOMPRESS_1
00091 };
00092
00093 typedef enum __ExpToStdout_Compression_enum__ ExpToStdout_Compression_t;
00094
00095 ModuleArgs_t module_args[] =
00096 {
00097 { ARG_STRING, ARG_RS_SPEC, NULL, "record-set query that specifies data to be exported" },
00098 { ARG_STRING, ARG_KEYMAP_CLASS, " ", "export key-map class" },
00099 { ARG_STRING, ARG_KEYMAP_FILE, " ", "export key-map file" },
00100 { ARG_STRING, ARG_FILE_TEMPLATE, " ", "export FITS filename template" },
00101 { ARG_STRINGS, ARG_CPARMS_STRING, " ", "a list of FITSIO compression types (none, rice, gzip1, gzip2, plio, hcompress), one for each segment; default is rice for all segments" },
00102 { ARG_STRING, ARG_ACK_FILE, " ", "a file provided by the caller to include in the tar file"},
00103 { ARG_INT, ARG_MAX_TAR_FILE_SIZE, DEFAULT_MAX_TAR_FILE_SIZE, "the maximum size in bytes of the resulting tar file"},
00104 { ARG_FLAG, ARG_COMPRESS_ALL_SEGS, NULL, "apply the single string in ARG_CPARMS_STRING to all segments" },
00105 { ARG_FLAG, ARG_DO_NOT_CREATE_TAR, NULL, "skip producing a tar file if a single FITS file is being exported"},
00106 { ARG_END }
00107 };
00108
00109 static void GetOptionValue(ModuleArgs_Type_t type, const char *key, void *result)
00110 {
00111 switch (type)
00112 {
00113 case ARG_STRING:
00114 {
00115 const char *innards = NULL;
00116
00117 innards = params_get_str(&cmdparams, (char *)key);
00118 if (strcmp(innards, " "))
00119 {
00120 *(const char **)result = innards;
00121 }
00122 }
00123 break;
00124 case ARG_STRINGS:
00125 {
00126 char **strings = NULL;
00127 int nElems = 0;
00128 LinkedList_t *list = NULL;
00129 int iElem;
00130
00131 nElems = cmdparams_get_strarr(&cmdparams, (char *)key, &strings, NULL);
00132
00133 if (nElems != 0 && (nElems != 1 || strcmp(strings[0], " ")))
00134 {
00135 list = list_llcreate(sizeof(char *), NULL);
00136 if (list)
00137 {
00138 for (iElem = 0; iElem < nElems; iElem++)
00139 {
00140 list_llinserttail(list, strings[iElem]);
00141 }
00142
00143 *(LinkedList_t **)result = list;
00144 }
00145 }
00146 }
00147 break;
00148 case ARG_INT:
00149 {
00150 long long intVal = 0;
00151
00152 intVal = params_get_int64(&cmdparams, (char *)key);
00153 *(long long *)result = intVal;
00154 }
00155 break;
00156 case ARG_FLAG:
00157 {
00158 int flag = 0;
00159
00160 flag = cmdparams_isflagset(&cmdparams, (char *)key);
00161 *(int *)result = flag;
00162 }
00163 break;
00164 }
00165 }
00166
00167
00168 static ExpToStdoutStatus_t Dump(FILE *stream, const char *buf, size_t numBytes, size_t *numBytesDumped)
00169 {
00170 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00171 size_t numDumped = 0;
00172
00173 if (stream)
00174 {
00175 numDumped = fwrite(buf, 1, numBytes, stream);
00176 if (numDumped != numBytes)
00177 {
00178 fprintf(stderr, "unable to dump to stream\n");
00179 expStatus = ExpToStdoutStatus_Dump;
00180 }
00181 }
00182 else
00183 {
00184 fprintf(stderr, "Dump(): invalid arguments\n");
00185 }
00186
00187 if (numBytesDumped)
00188 {
00189 if (expStatus == ExpToStdoutStatus_Success)
00190 {
00191 *numBytesDumped = *numBytesDumped + numDumped;
00192 }
00193 else
00194 {
00195 *numBytesDumped = *numBytesDumped + 0;
00196 }
00197 }
00198
00199 return expStatus;
00200 }
00201
00202 static ExpToStdoutStatus_t DumpPadding(FILE *stream, size_t existing, size_t total, size_t *numBytesDumped)
00203 {
00204 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00205 size_t numDumped = 0;
00206
00207 if (total > existing)
00208 {
00209 char *buf = NULL;
00210
00211 buf = calloc(total - existing, 1);
00212 if (buf)
00213 {
00214 expStatus = Dump(stream, buf, total - existing, &numDumped);
00215 free(buf);
00216 }
00217 else
00218 {
00219 expStatus = ExpToStdoutStatus_OutOfMemory;
00220 }
00221 }
00222 else if (total < existing)
00223 {
00224 fprintf(stderr, "cannot pad to %lu bytes when %lu bytes have already been written\n", total, existing);
00225 expStatus = ExpToStdoutStatus_DumpPadding;
00226 }
00227
00228 if (numBytesDumped)
00229 {
00230 if (expStatus == ExpToStdoutStatus_Success)
00231 {
00232 *numBytesDumped = *numBytesDumped + numDumped;
00233 }
00234 else
00235 {
00236 *numBytesDumped = *numBytesDumped + 0;
00237 }
00238 }
00239
00240 return expStatus;
00241 }
00242
00243 static ExpToStdoutStatus_t DumpAndPad(FILE *stream, const char *buf, size_t numBytes, size_t total, size_t *numBytesDumped)
00244 {
00245 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00246 size_t numDumped = 0;
00247
00248 if (total >= numBytes)
00249 {
00250 expStatus = Dump(stream, buf, numBytes, &numDumped);
00251 if (expStatus == ExpToStdoutStatus_Success)
00252 {
00253 expStatus = DumpPadding(stream, numBytes, total, &numDumped);
00254 }
00255 }
00256
00257 if (numBytesDumped)
00258 {
00259 if (expStatus == ExpToStdoutStatus_Success)
00260 {
00261 *numBytesDumped = *numBytesDumped + numDumped;
00262 }
00263 else
00264 {
00265 *numBytesDumped = *numBytesDumped + 0;
00266 }
00267 }
00268
00269 return expStatus;
00270 }
00271
00272 static ExpToStdoutStatus_t DumpOctal(FILE *stream, long long value, size_t fieldWidth, size_t *numBytesDumped)
00273 {
00274 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00275 size_t numDumped = 0;
00276
00277 char *field = NULL;
00278
00279 field = calloc(1, fieldWidth + 1);
00280 if (field)
00281 {
00282 snprintf(field, fieldWidth + 1, "%0*llo\0", (int)fieldWidth - 1, value);
00283 expStatus = Dump(stream, field, fieldWidth, &numDumped);
00284 }
00285
00286 if (numBytesDumped)
00287 {
00288 if (expStatus == ExpToStdoutStatus_Success)
00289 {
00290 *numBytesDumped = *numBytesDumped + numDumped;
00291 }
00292 else
00293 {
00294 *numBytesDumped = *numBytesDumped + 0;
00295 }
00296 }
00297
00298 return expStatus;
00299 }
00300
00301
00302 static ExpToStdoutStatus_t DumpTarFileObjectHeader(FILE *stream, const char *fileName, size_t fileSize)
00303 {
00304 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00305
00306 struct passwd pwd;
00307 struct passwd *resultPwd = NULL;
00308 struct group grp;
00309 struct group *resultGrp = NULL;
00310 uid_t uid;
00311 gid_t gid;
00312 char *idBuf = NULL;
00313 size_t idBufSize;
00314 int pipefds[2];
00315 char header[TAR_HEADER_SIZE];
00316 FILE *writeStream = NULL;
00317 FILE *readStream = NULL;
00318 unsigned long long chksum = 0;
00319 size_t numBytesDumped = 0;
00320
00321 if (pipe(pipefds))
00322 {
00323 expStatus = ExpToStdoutStatus_IO;
00324 }
00325
00326 if (expStatus == ExpToStdoutStatus_Success)
00327 {
00328
00329 writeStream = fdopen(pipefds[1], "w");
00330 if (!writeStream)
00331 {
00332 expStatus = ExpToStdoutStatus_IO;
00333 }
00334 else
00335 {
00336
00337 readStream = fdopen(pipefds[0], "r");
00338 if (!readStream)
00339 {
00340 expStatus = ExpToStdoutStatus_IO;
00341 }
00342 }
00343 }
00344
00345 if (expStatus == ExpToStdoutStatus_Success)
00346 {
00347
00348 expStatus = DumpAndPad(writeStream, fileName, strlen(fileName), 100, NULL);
00349 }
00350
00351 if (expStatus == ExpToStdoutStatus_Success)
00352 {
00353
00354 expStatus = DumpOctal(writeStream, 436, 8, NULL);
00355 }
00356
00357 if (expStatus == ExpToStdoutStatus_Success)
00358 {
00359
00360 idBufSize = (size_t)sysconf(_SC_GETPW_R_SIZE_MAX);
00361
00362 if (idBufSize == -1)
00363 {
00364 idBufSize = 16384;
00365 }
00366
00367 idBuf = malloc(idBufSize);
00368 if (!idBuf )
00369 {
00370 expStatus = ExpToStdoutStatus_OutOfMemory;
00371 }
00372 else
00373 {
00374 uid = getuid();
00375 getpwuid_r(uid, &pwd, idBuf, idBufSize, &resultPwd);
00376
00377 if (!resultPwd)
00378 {
00379
00380 fprintf(stderr, "user id %u not found\n", uid);
00381 expStatus = ExpToStdoutStatus_GetUser;
00382 }
00383 }
00384
00385 expStatus = DumpOctal(writeStream, pwd.pw_uid, 8, NULL);
00386 }
00387
00388 if (expStatus == ExpToStdoutStatus_Success)
00389 {
00390
00391 gid = pwd.pw_gid;
00392 expStatus = DumpOctal(writeStream, gid, 8, NULL);
00393 }
00394
00395 if (expStatus == ExpToStdoutStatus_Success)
00396 {
00397
00398 expStatus = DumpOctal(writeStream, fileSize, 12, NULL);
00399 }
00400
00401 if (expStatus == ExpToStdoutStatus_Success)
00402 {
00403
00404 expStatus = DumpOctal(writeStream, time(NULL), 12, NULL);
00405 }
00406
00407 if (expStatus == ExpToStdoutStatus_Success)
00408 {
00409
00410
00411
00412
00413
00414 expStatus = Dump(writeStream, " ", 8, NULL);
00415 }
00416
00417 if (expStatus == ExpToStdoutStatus_Success)
00418 {
00419
00420 expStatus = DumpOctal(writeStream, 0, 1, NULL);
00421 }
00422
00423 if (expStatus == ExpToStdoutStatus_Success)
00424 {
00425
00426 expStatus = DumpPadding(writeStream, 0, 100, NULL);
00427 }
00428
00429 if (expStatus == ExpToStdoutStatus_Success)
00430 {
00431
00432 expStatus = DumpAndPad(writeStream, "ustar", 5, 6, NULL);
00433 }
00434
00435 if (expStatus == ExpToStdoutStatus_Success)
00436 {
00437
00438 expStatus = DumpAndPad(writeStream, "00", 2, 2, NULL);
00439 }
00440
00441 if (expStatus == ExpToStdoutStatus_Success)
00442 {
00443
00444 expStatus = DumpAndPad(writeStream, pwd.pw_name, strlen(pwd.pw_name), 32, NULL);
00445
00446
00447 if (idBuf)
00448 {
00449 free(idBuf);
00450 idBuf = NULL;
00451 }
00452 }
00453
00454 if (expStatus == ExpToStdoutStatus_Success)
00455 {
00456
00457
00458
00459 idBufSize = (size_t)sysconf(_SC_GETGR_R_SIZE_MAX);
00460
00461 if (idBufSize == -1)
00462 {
00463 idBufSize = 16384;
00464 }
00465
00466 idBuf = malloc(idBufSize);
00467 if (!idBuf)
00468 {
00469 expStatus = ExpToStdoutStatus_OutOfMemory;
00470 }
00471 else
00472 {
00473 getgrgid_r(gid, &grp, idBuf, idBufSize, &resultGrp);
00474
00475 if (!resultGrp)
00476 {
00477
00478 fprintf(stderr, "group id %u not found\n", gid);
00479 expStatus = ExpToStdoutStatus_GetGroup;
00480 }
00481 else
00482 {
00483 expStatus = DumpAndPad(writeStream, grp.gr_name, strlen(grp.gr_name), 32, NULL);
00484 }
00485 }
00486
00487
00488 if (idBuf)
00489 {
00490 free(idBuf);
00491 idBuf = NULL;
00492 }
00493 }
00494
00495 if (expStatus == ExpToStdoutStatus_Success)
00496 {
00497
00498 expStatus = DumpPadding(writeStream, 0, 8, NULL);
00499 }
00500
00501 if (expStatus == ExpToStdoutStatus_Success)
00502 {
00503
00504 expStatus = DumpPadding(writeStream, 0, 8, NULL);
00505 }
00506
00507 if (expStatus == ExpToStdoutStatus_Success)
00508 {
00509
00510 expStatus = DumpPadding(writeStream, 0, 155, NULL);
00511 }
00512
00513
00514 if (expStatus == ExpToStdoutStatus_Success)
00515 {
00516 char *ptr = NULL;
00517 size_t num = 0;
00518
00519
00520 fflush(writeStream);
00521 fclose(writeStream);
00522 close(pipefds[1]);
00523
00524
00525 memset(header, 0, sizeof(header));
00526 ptr = header;
00527 while (1)
00528 {
00529 num = fread(header, sizeof(char), TAR_HEADER_SIZE, readStream);
00530 if (num <= 0)
00531 {
00532 break;
00533 }
00534 else
00535 {
00536 ptr += num;
00537 }
00538 }
00539
00540 fclose(readStream);
00541 close(pipefds[0]);
00542 }
00543
00544 if (expStatus == ExpToStdoutStatus_Success)
00545 {
00546 char *ptr;
00547
00548
00549 ptr = header;
00550 while (ptr < header + sizeof(header))
00551 {
00552 chksum += (int)*ptr;
00553 ptr++;
00554 }
00555 }
00556
00557 if (expStatus == ExpToStdoutStatus_Success)
00558 {
00559
00560 numBytesDumped = 0;
00561 expStatus = Dump(stream, header, 148, &numBytesDumped);
00562 }
00563
00564 if (expStatus == ExpToStdoutStatus_Success)
00565 {
00566
00567 expStatus = DumpOctal(stream, chksum, 7, &numBytesDumped);
00568
00569
00570 if (expStatus == ExpToStdoutStatus_Success)
00571 {
00572 expStatus = Dump(stream, " ", 1, &numBytesDumped);
00573 }
00574 }
00575
00576 if (expStatus == ExpToStdoutStatus_Success)
00577 {
00578
00579 expStatus = Dump(stream, &header[numBytesDumped], sizeof(header) - numBytesDumped, &numBytesDumped);
00580 }
00581
00582
00583 if (idBuf)
00584 {
00585 free(idBuf);
00586 idBuf = NULL;
00587 }
00588
00589 return expStatus;
00590 }
00591
00592 static ExpToStdoutStatus_t FillBlock(FILE *stream, int blockSize, int writeSize)
00593 {
00594 int remainder = writeSize % blockSize;
00595
00596 if (remainder != 0)
00597 {
00598 return DumpPadding(stream, 0, blockSize - remainder, NULL);
00599 }
00600
00601 return ExpToStdoutStatus_Success;
00602 }
00603
00604
00605
00606
00607
00608 static ExpToStdoutStatus_t WriteFileBuffer(FILE *stream, const char *filePath, const char *buffer, size_t size)
00609 {
00610 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00611
00612
00613 expStatus = DumpTarFileObjectHeader(stream, filePath, size);
00614
00615 if (expStatus == ExpToStdoutStatus_Success)
00616 {
00617
00618 fprintf(stream, buffer);
00619
00620
00621 expStatus = FillBlock(stream, TAR_BLOCK_SIZE, size);
00622 }
00623
00624 fflush(stream);
00625
00626 return expStatus;
00627 }
00628
00629 static ExpToStdoutStatus_t WriteFile(FILE *writeStream, const char *filePath, size_t bufSize)
00630 {
00631 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00632 const char *baseName = NULL;
00633 struct stat stBuf;
00634 char *readBuffer = NULL;
00635 size_t numBytesRead;
00636 char *ptr = NULL;
00637 FILE *readStream = NULL;
00638
00639
00640 if (lstat(filePath, &stBuf) != 0)
00641 {
00642 fprintf(stderr, "cannot get %s file status\n", filePath);
00643 expStatus = ExpToStdoutStatus_IO;
00644 }
00645
00646 if (expStatus == ExpToStdoutStatus_Success)
00647 {
00648
00649 baseName = strrchr(filePath, '/');
00650 baseName = baseName ? baseName + 1 : filePath;
00651 expStatus = DumpTarFileObjectHeader(writeStream, baseName, stBuf.st_size);
00652 }
00653
00654 if (expStatus == ExpToStdoutStatus_Success)
00655 {
00656 readStream = fopen(filePath, "r");
00657 if (readStream == NULL)
00658 {
00659 fprintf(stderr, "cannot open file %s for reading\n", filePath);
00660 expStatus = ExpToStdoutStatus_IO;
00661 }
00662 }
00663
00664 if (expStatus == ExpToStdoutStatus_Success)
00665 {
00666 readBuffer = calloc(sizeof(char), bufSize);
00667 if (!readBuffer)
00668 {
00669 expStatus = ExpToStdoutStatus_OutOfMemory;
00670 }
00671 }
00672
00673 if (expStatus == ExpToStdoutStatus_Success)
00674 {
00675
00676 while (1)
00677 {
00678 numBytesRead = fread(readBuffer, sizeof(char), bufSize - 1, readStream);
00679 if (numBytesRead <= 0)
00680 {
00681 break;
00682 }
00683 else
00684 {
00685 readBuffer[numBytesRead] = '\0';
00686 fprintf(writeStream, readBuffer);
00687 }
00688 }
00689
00690 free(readBuffer);
00691 readBuffer = NULL;
00692
00693 fclose(readStream);
00694 readStream = NULL;
00695 }
00696
00697 if (expStatus == ExpToStdoutStatus_Success)
00698 {
00699
00700 expStatus = FillBlock(writeStream, TAR_BLOCK_SIZE, stBuf.st_size);
00701 }
00702
00703 fflush(writeStream);
00704
00705 return expStatus;
00706 }
00707
00708 static ExpToStdoutStatus_t WriteAckFile(FILE *writeStream, const char *path)
00709 {
00710 return WriteFile(writeStream, path, ACK_FILE_BUFFER);
00711 }
00712
00713 static ExpToStdoutStatus_t DropDataOnFloor(fitsfile *fitsPtr)
00714 {
00715 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00716 long long numBytesFitsFile = fitsPtr->Fptr->logfilesize;
00717 int savedStdout = -1;
00718 char fileBuf[4096];
00719 int num;
00720 int fiostat = 0;
00721 int devnull = -1;
00722
00723 if (numBytesFitsFile > 0)
00724 {
00725
00726 devnull = open("/dev/null", O_WRONLY);
00727
00728 if (!devnull)
00729 {
00730 fprintf(stderr, "unable to open /dev/null for writing\n");
00731 expStatus = ExpToStdoutStatus_IO;
00732 }
00733
00734 if (expStatus == ExpToStdoutStatus_Success)
00735 {
00736 savedStdout = dup(STDOUT_FILENO);
00737 if (savedStdout != -1)
00738 {
00739 if (dup2(devnull, STDOUT_FILENO) != -1)
00740 {
00741 fiostat = 0;
00742 fits_close_file(fitsPtr, &fiostat);
00743 if (fiostat)
00744 {
00745 fprintf(stderr, "unable to close and send FITS file\n");
00746 }
00747
00748 fflush(stdout);
00749 }
00750 else
00751 {
00752
00753 fprintf(stderr, "unable to flush FITSIO internal buffers following error\n");
00754 }
00755
00756
00757 dup2(savedStdout, STDOUT_FILENO);
00758 }
00759 else
00760 {
00761
00762 fprintf(stderr, "unable to flush FITSIO internal buffers following error\n");
00763 }
00764 }
00765 }
00766
00767 return expStatus;
00768 }
00769
00770
00771
00772
00773 static ExpToStdoutStatus_t ExportRecordToStdout(int makeTar, DRMS_Record_t *expRec, const char *ffmt, ExpToStdout_Compression_t *segCompression, int compressAllSegs, const char *classname, const char *mapfile, size_t *bytesExported, size_t maxTarFileSize, size_t *numFilesExported, char **infoBuf, size_t *szInfoBuf, char **errorBuf, size_t *szErrorBuf)
00774 {
00775 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
00776 int drmsStatus = DRMS_SUCCESS;
00777 int fiostat = 0;
00778 char recordSpec[DRMS_MAXQUERYLEN];
00779 DRMS_Segment_t *segIn = NULL;
00780 int iSeg;
00781 HIterator_t *last = NULL;
00782 DRMS_Segment_t *segTgt = NULL;
00783 char formattedFitsName[DRMS_MAXPATHLEN];
00784 ExpUtlStat_t expUStat = kExpUtlStat_Success;
00785 fitsfile *fitsPtr = NULL;
00786 long long numBytesFitsFile;
00787 size_t totalBytes = 0;
00788 size_t totalFiles = 0;
00789 char msg[256];
00790 char errMsg[512];
00791
00792 drms_sprint_rec_query(recordSpec, expRec);
00793
00794 iSeg = 0;
00795 while ((segIn = drms_record_nextseg(expRec, &last, 0)) != NULL)
00796 {
00797 if (segIn->info->islink)
00798 {
00799 if ((segTgt = drms_segment_lookup(expRec, segIn->info->name)) == NULL)
00800 {
00801 snprintf(msg, sizeof(msg), "unable to locate linked segment file %s", segIn->info->name);
00802 fprintf(stderr, msg);
00803 fprintf(stderr, "\n");
00804 if (makeTar && errorBuf && *errorBuf)
00805 {
00806 snprintf(errMsg, sizeof(errMsg), "record = %s, segment = %s, message = %s\n", recordSpec, segIn->info->name, msg);
00807 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00808 }
00809
00810 iSeg++;
00811 continue;
00812 }
00813 }
00814 else
00815 {
00816 segTgt = segIn;
00817 }
00818
00819 if ((expUStat = exputl_mk_expfilename(segIn, segTgt, ffmt, formattedFitsName)) != kExpUtlStat_Success)
00820 {
00821 if (expUStat == kExpUtlStat_InvalidFmt)
00822 {
00823 snprintf(msg, sizeof(msg), "invalid file-name format template %s", ffmt);
00824 }
00825 else if (expUStat == kExpUtlStat_UnknownKey)
00826 {
00827 snprintf(msg, sizeof(msg), "one or more keywords in the file-name-format template %s do not exist in series %s", ffmt, expRec->seriesinfo->seriesname);
00828 }
00829 else
00830 {
00831 snprintf(msg, sizeof(msg), "unable to resolve file-name template %s", ffmt);
00832 }
00833
00834 fprintf(stderr, msg);
00835 fprintf(stderr, "\n");
00836 if (makeTar && errorBuf && *errorBuf)
00837 {
00838 snprintf(errMsg, sizeof(errMsg), "record = %s, segment = %s, message = %s\n", recordSpec, segIn->info->name, msg);
00839 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00840 }
00841
00842 expStatus = ExpToStdoutStatus_BadFilenameTemplate;
00843 break;
00844 }
00845
00846 fiostat = 0;
00847 if (fits_create_file(&fitsPtr, "-", &fiostat))
00848 {
00849 fits_report_error(stderr, fiostat);
00850 snprintf(msg, sizeof(msg), "cannot create FITS file");
00851 fprintf(stderr, msg);
00852 fprintf(stderr, "\n");
00853 if (makeTar && errorBuf && *errorBuf)
00854 {
00855 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = %s\n", recordSpec, formattedFitsName, msg);
00856 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00857 }
00858
00859 iSeg++;
00860 continue;
00861 }
00862
00863
00864 fiostat = 0;
00865 if (segCompression)
00866 {
00867 if (compressAllSegs && (segCompression[0] != ExpToStdout_Compression_NONE))
00868 {
00869 fits_set_compression_type(fitsPtr, segCompression[0], &fiostat);
00870 }
00871 else if (segCompression[iSeg] && segCompression[iSeg] != ExpToStdout_Compression_NONE)
00872 {
00873 fits_set_compression_type(fitsPtr, segCompression[iSeg], &fiostat);
00874 }
00875 }
00876 else
00877 {
00878 fits_set_compression_type(fitsPtr, ExpToStdout_Compression_RICE, &fiostat);
00879 }
00880
00881 if (fiostat)
00882 {
00883 fits_report_error(stderr, fiostat);
00884
00885 fits_close_file(fitsPtr, &fiostat);
00886
00887 snprintf(msg, sizeof(msg), "unable to set FITS compression");
00888 fprintf(stderr, msg);
00889 fprintf(stderr, "\n");
00890 if (makeTar && errorBuf && *errorBuf)
00891 {
00892 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = %s\n", recordSpec, formattedFitsName, msg);
00893 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00894 }
00895
00896 iSeg++;
00897 continue;
00898 }
00899
00900
00901 drmsStatus = fitsexport_mapexport_tostdout(fitsPtr, segIn, classname, mapfile);
00902
00903 if (drmsStatus == DRMS_ERROR_INVALIDFILE)
00904 {
00905
00906 snprintf(msg, sizeof(msg), "no segment file (segment %s) for this record", segIn->info->name);
00907 fprintf(stderr, msg);
00908 fprintf(stderr, "\n");
00909 if (makeTar && errorBuf && *errorBuf)
00910 {
00911 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = %s\n", recordSpec, formattedFitsName, msg);
00912 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00913 }
00914 }
00915 else if (drmsStatus != DRMS_SUCCESS)
00916 {
00917 if (drmsStatus == DRMS_ERROR_CANTCOMPRESSFLOAT)
00918 {
00919 snprintf(msg, sizeof(msg), "cannot export Rice-compressed floating-point images");
00920 }
00921 else
00922 {
00923
00924 snprintf(msg, sizeof(msg), "failure exporting segment %s", segIn->info->name);
00925 }
00926
00927 fprintf(stderr, msg);
00928 fprintf(stderr, "\n");
00929 if (makeTar && errorBuf && *errorBuf)
00930 {
00931 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = %s\n", recordSpec, formattedFitsName, msg);
00932 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942 expStatus = DropDataOnFloor(fitsPtr);
00943 if (expStatus != ExpToStdoutStatus_Success)
00944 {
00945 break;
00946 }
00947 }
00948 else
00949 {
00950
00951
00952
00953 numBytesFitsFile = fitsPtr->Fptr->logfilesize;
00954 if (numBytesFitsFile > 0)
00955 {
00956 if (numBytesFitsFile + totalBytes > maxTarFileSize)
00957 {
00958
00959 snprintf(msg, sizeof(msg), "the tar file size has exceeded the maximum size of %llu bytes; please consider requesting data for fewer records and Rice-compressing images", maxTarFileSize);
00960 fprintf(stderr, msg);
00961 fprintf(stderr, "\n");
00962 if (makeTar && errorBuf && *errorBuf)
00963 {
00964 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = %s\n", recordSpec, formattedFitsName, msg);
00965 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00966 }
00967
00968
00969 DropDataOnFloor(fitsPtr);
00970 expStatus = ExpToStdoutStatus_TarTooLarge;
00971 break;
00972 }
00973
00974 if (makeTar)
00975 {
00976
00977 DumpTarFileObjectHeader(stdout, formattedFitsName, numBytesFitsFile);
00978 }
00979
00980
00981 fiostat = 0;
00982 fits_close_file(fitsPtr, &fiostat);
00983 if (fiostat)
00984 {
00985 snprintf(msg, sizeof(msg), "unable to close and send FITS file");
00986 fprintf(stderr, msg);
00987 fprintf(stderr, "\n");
00988 if (makeTar && errorBuf && *errorBuf)
00989 {
00990 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = %s\n", recordSpec, formattedFitsName, msg);
00991 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
00992 }
00993 }
00994
00995 fflush(stdout);
00996
00997 if (makeTar)
00998 {
00999
01000 expStatus = FillBlock(stdout, TAR_BLOCK_SIZE, numBytesFitsFile);
01001 }
01002
01003 totalBytes += numBytesFitsFile;
01004 totalFiles++;
01005
01006 if (infoBuf && *infoBuf)
01007 {
01008 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = successful export\n", recordSpec, formattedFitsName);
01009 *infoBuf = base_strcatalloc(*infoBuf, errMsg, szInfoBuf);
01010 }
01011 }
01012 else
01013 {
01014 if (makeTar && errorBuf && *errorBuf)
01015 {
01016 snprintf(errMsg, sizeof(errMsg), "record = %s, file = %s, message = no data in segment, so no FITS file was produced\n", recordSpec, formattedFitsName);
01017 *errorBuf = base_strcatalloc(*errorBuf, errMsg, szErrorBuf);
01018 }
01019 }
01020 }
01021 }
01022
01023 if (last)
01024 {
01025 hiter_destroy(&last);
01026 }
01027
01028 if (bytesExported)
01029 {
01030 *bytesExported = totalBytes;
01031 }
01032
01033 if (numFilesExported)
01034 {
01035 *numFilesExported = totalFiles;
01036 }
01037
01038
01039 return expStatus;
01040 }
01041
01042
01043
01044
01045 static ExpToStdoutStatus_t ExportRecordSetToStdout(DRMS_Env_t *env, int makeTar, DRMS_RecordSet_t *expRS, const char *ffmt, ExpToStdout_Compression_t *segCompression, int compressAllSegs, const char *classname, const char *mapfile, size_t *bytesExported, size_t maxTarFileSize, size_t *numFilesExported, char **infoBuf, size_t *szInfoBuf, char **errorBuf, size_t *szErrorBuf)
01046 {
01047 int drmsStatus = DRMS_SUCCESS;
01048 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
01049
01050 int iSet;
01051 int iRec;
01052 int nRecs;
01053 DRMS_Record_t *expRecord = NULL;
01054
01055 int recsExported = 0;
01056 int recsAttempted = 0;
01057
01058 for (iSet = 0; iSet < expRS->ss_n; iSet++)
01059 {
01060 nRecs = drms_recordset_getssnrecs(expRS, iSet, &drmsStatus);
01061
01062 if (drmsStatus != DRMS_SUCCESS)
01063 {
01064
01065 fprintf(stderr, "failure calling drms_recordset_getssnrecs(), skipping subset %d\n", iSet);
01066 expStatus = ExpToStdoutStatus_DRMS;
01067 }
01068 else
01069 {
01070 for (iRec = 0; iRec < nRecs; iRec++)
01071 {
01072 expRecord = drms_recordset_fetchnext(env, expRS, &drmsStatus, NULL, NULL);
01073
01074 if (!expRecord || drmsStatus != DRMS_SUCCESS)
01075 {
01076
01077 break;
01078 }
01079
01080 recsAttempted++;
01081
01082
01083 expStatus = ExportRecordToStdout(makeTar, expRecord, ffmt, segCompression, compressAllSegs, classname, mapfile, bytesExported, maxTarFileSize, numFilesExported, infoBuf, szInfoBuf, errorBuf, szErrorBuf);
01084 if (expStatus == ExpToStdoutStatus_TarTooLarge)
01085 {
01086 break;
01087 }
01088 else if (expStatus == ExpToStdoutStatus_Success)
01089 {
01090 recsExported++;
01091 }
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 expStatus = ExpToStdoutStatus_Success;
01109 }
01110 }
01111 }
01112
01113 if (recsAttempted > 0 && recsExported == 0)
01114 {
01115 fprintf(stderr, "exports failed for %d records of %d records attempted\n", recsAttempted - recsExported, recsAttempted);
01116 expStatus = ExpToStdoutStatus_AllExportsFailed;
01117 }
01118
01119 return expStatus;
01120 }
01121
01122 int DoIt(void)
01123 {
01124 ExpToStdoutStatus_t expStatus = ExpToStdoutStatus_Success;
01125 ExpToStdoutStatus_t intStatus = ExpToStdoutStatus_Success;
01126 ExpToStdoutStatus_t tarStatus = ExpToStdoutStatus_Dump;
01127
01128
01129
01130
01131 int drmsStatus = DRMS_SUCCESS;
01132 int fiostat = 0;
01133 fitsfile *fitsPtr = NULL;
01134 long long tsize = 0;
01135 long long tsizeMB = 0;
01136 void *misspix = NULL;
01137 const char *rsSpec = NULL;
01138 const char *fileTemplate = NULL;
01139 const char *mapClass = NULL;
01140 const char *mapFile = NULL;
01141 LinkedList_t *cparmsStrings = NULL;
01142 const char *ackFile = NULL;
01143 size_t maxTarFileSize = 0;
01144 int compressAllSegs = 0;
01145 int skipTarCreation = 0;
01146 int makeTar = 1;
01147 ListNode_t *cparmNode = NULL;
01148 ExpToStdout_Compression_t *segCompression = NULL;
01149 int iComp;
01150 DRMS_RecordSet_t *expRS = NULL;
01151 char *infoBuf = NULL;
01152 size_t szInfoBuf = 0;
01153 char *errorBuf = NULL;
01154 size_t szErrorBuf = 0;
01155 char generalErrorBuf[TAR_BLOCK_SIZE];
01156 size_t bytesExported = 0;
01157 size_t numFilesExported = 0;
01158
01159
01160 rsSpec = params_get_str(&cmdparams, ARG_RS_SPEC);
01161 GetOptionValue(ARG_STRING, ARG_FILE_TEMPLATE, (void *)&fileTemplate);
01162 GetOptionValue(ARG_STRING, ARG_KEYMAP_CLASS, (void *)&mapClass);
01163 GetOptionValue(ARG_STRING, ARG_KEYMAP_FILE, (void *)&mapFile);
01164 GetOptionValue(ARG_STRINGS, ARG_CPARMS_STRING, (void *)&cparmsStrings);
01165 GetOptionValue(ARG_STRING, ARG_ACK_FILE, (void *)&ackFile);
01166 GetOptionValue(ARG_INT, ARG_MAX_TAR_FILE_SIZE, (void *)&maxTarFileSize);
01167 GetOptionValue(ARG_FLAG, ARG_COMPRESS_ALL_SEGS, (void *)&compressAllSegs);
01168 GetOptionValue(ARG_FLAG, ARG_DO_NOT_CREATE_TAR, (void *)&skipTarCreation);
01169
01170 memset(generalErrorBuf, '\0', sizeof(generalErrorBuf));
01171
01172 if (expStatus == ExpToStdoutStatus_Success)
01173 {
01174 szInfoBuf = 512;
01175 infoBuf = calloc(1, szInfoBuf);
01176 if (infoBuf)
01177 {
01178 szErrorBuf = 512;
01179 errorBuf = calloc(1, szErrorBuf);
01180 if (!errorBuf)
01181 {
01182 expStatus == ExpToStdoutStatus_OutOfMemory;
01183 }
01184 }
01185 else
01186 {
01187 expStatus == ExpToStdoutStatus_OutOfMemory;
01188 }
01189 }
01190
01191
01192 if (cparmsStrings)
01193 {
01194 char *cparmStr = NULL;
01195
01196 segCompression = calloc(1, sizeof(ExpToStdout_Compression_t));
01197
01198 if (segCompression)
01199 {
01200 list_llreset(cparmsStrings);
01201 iComp = 0;
01202 while ((cparmNode = list_llnext(cparmsStrings)) != NULL)
01203 {
01204 cparmStr = *(char **)cparmNode;
01205
01206 if (strcasecmp(cparmStr, COMPRESSION_NONE) == 0)
01207 {
01208 segCompression[iComp] = ExpToStdout_Compression_NONE;
01209 }
01210 else if (strcasecmp(cparmStr, COMPRESSION_RICE) == 0)
01211 {
01212 segCompression[iComp] = ExpToStdout_Compression_RICE;
01213 }
01214 else if (strcasecmp(cparmStr, COMPRESSION_GZIP1) == 0)
01215 {
01216 segCompression[iComp] = ExpToStdout_Compression_GZIP1;
01217 }
01218 else if (strcasecmp(cparmStr, COMPRESSION_GZIP2) == 0)
01219 {
01220 segCompression[iComp] = ExpToStdout_Compression_GZIP2;
01221 }
01222 else if (strcasecmp(cparmStr, COMPRESSION_PLIO) == 0)
01223 {
01224 segCompression[iComp] = ExpToStdout_Compression_PLIO;
01225 }
01226 else if (strcasecmp(cparmStr, COMPRESSION_HCOMP) == 0)
01227 {
01228 segCompression[iComp] = ExpToStdout_Compression_HCOMP;
01229 }
01230 else
01231 {
01232 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01233 {
01234 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "invalid compression-string argument element %s\n", cparmStr);
01235 }
01236 expStatus = ExpToStdoutStatus_InvalidArgs;
01237 break;
01238 }
01239
01240 iComp++;
01241 }
01242
01243 if (expStatus == ExpToStdoutStatus_Success && iComp != 1 && compressAllSegs)
01244 {
01245 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01246 {
01247 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "invalid combination of %s and %s arguments\n", ARG_CPARMS_STRING, ARG_COMPRESS_ALL_SEGS);
01248 }
01249 expStatus = ExpToStdoutStatus_InvalidArgs;
01250 }
01251 }
01252 else
01253 {
01254 expStatus = ExpToStdoutStatus_OutOfMemory;
01255 }
01256 }
01257 else
01258 {
01259
01260 }
01261
01262 if (expStatus == ExpToStdoutStatus_Success)
01263 {
01264 expRS = drms_open_records(drms_env, rsSpec, &drmsStatus);
01265 if (!expRS || drmsStatus != DRMS_SUCCESS)
01266 {
01267 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01268 {
01269 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "unable to open records for specification %s\n", rsSpec);
01270 }
01271 expStatus = ExpToStdoutStatus_DRMS;
01272 }
01273 else
01274 {
01275 makeTar = (!skipTarCreation || expRS->n > 1);
01276 }
01277 }
01278
01279 if (expStatus == ExpToStdoutStatus_Success)
01280 {
01281 if (makeTar && maxTarFileSize > MAX_MAX_TAR_FILE_SIZE)
01282 {
01283 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01284 {
01285 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "maximum tar file size argument, %llu, exceeds limit of %llu bytes\n", maxTarFileSize, MAX_MAX_TAR_FILE_SIZE);
01286 }
01287 expStatus = ExpToStdoutStatus_InvalidArgs;
01288 }
01289 }
01290
01291 if (expStatus == ExpToStdoutStatus_Success)
01292 {
01293
01294 if (drms_stage_records(expRS, 1, 0) != DRMS_SUCCESS)
01295 {
01296 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01297 {
01298 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "unable to stage records for specification %s\n", rsSpec);
01299 }
01300 expStatus = ExpToStdoutStatus_DRMS;
01301 }
01302 }
01303
01304 if (expStatus == ExpToStdoutStatus_Success)
01305 {
01306
01307
01308
01309
01310
01311
01312 intStatus = ExportRecordSetToStdout(drms_env, makeTar, expRS, fileTemplate, segCompression, compressAllSegs, mapClass, mapFile, &bytesExported, maxTarFileSize, &numFilesExported, &infoBuf, &szInfoBuf, &errorBuf, &szErrorBuf);
01313
01314 if (makeTar)
01315 {
01316 tarStatus = intStatus;
01317 }
01318
01319
01320 if (tarStatus == ExpToStdoutStatus_DRMS)
01321 {
01322 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01323 {
01324 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "a DRMS error occurred while processing the record set %s\n", rsSpec);
01325 }
01326 }
01327 else if (tarStatus == ExpToStdoutStatus_TarTooLarge)
01328 {
01329 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01330 {
01331 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "the tar file size exceeded the limit and has been truncated");
01332 }
01333 }
01334 else if (tarStatus == ExpToStdoutStatus_AllExportsFailed)
01335 {
01336 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01337 {
01338 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "attempts were made to export files, but they all failed");
01339 }
01340 }
01341 else
01342 {
01343
01344 }
01345 }
01346
01347 if (infoBuf)
01348 {
01349 if (makeTar && *infoBuf)
01350 {
01351
01352
01353
01354
01355 intStatus = WriteFileBuffer(stdout, FILE_LIST_PATH, infoBuf, strlen(infoBuf));
01356 if (tarStatus == ExpToStdoutStatus_Success)
01357 {
01358 tarStatus = intStatus;
01359 }
01360 }
01361
01362 free(infoBuf);
01363 infoBuf = NULL;
01364 }
01365
01366
01367 if (errorBuf)
01368 {
01369 if (expStatus == ExpToStdoutStatus_Success)
01370 {
01371
01372 if (makeTar && *errorBuf)
01373 {
01374
01375 intStatus = WriteFileBuffer(stdout, ERROR_LIST_PATH, errorBuf, strlen(errorBuf));
01376 if (tarStatus == ExpToStdoutStatus_Success)
01377 {
01378 tarStatus = intStatus;
01379 }
01380 }
01381 }
01382 else
01383 {
01384 char errorBufMsg[512];
01385
01386
01387
01388 if (expStatus == ExpToStdoutStatus_OutOfMemory)
01389 {
01390 snprintf(errorBufMsg, sizeof(errorBufMsg), "out of memory on web server\n");
01391 }
01392 else
01393 {
01394 snprintf(errorBufMsg, sizeof(errorBufMsg), "the dreaded 'internal server error' message\n");
01395 }
01396
01397
01398 if (expRS)
01399 {
01400 DRMS_Record_t *expRecord = NULL;
01401 char recordSpec[DRMS_MAXQUERYLEN];
01402 HIterator_t *last = NULL;
01403 DRMS_Segment_t *seg = NULL;
01404 char transBuf[1024];
01405
01406 drms_recordset_fetchnext_setcurrent(expRS, -1);
01407
01408 while ((expRecord = drms_recordset_fetchnext(drms_env, expRS, &drmsStatus, NULL, NULL)) != NULL)
01409 {
01410 drms_sprint_rec_query(recordSpec, expRecord);
01411
01412 while ((seg = drms_record_nextseg(expRecord, &last, 0)) != NULL)
01413 {
01414 snprintf(transBuf, sizeof(transBuf), "record = %s, segment = %s, message = %s\n", recordSpec, seg->info->name, errorBufMsg);
01415 errorBuf = base_strcatalloc(errorBuf, errorBufMsg, &szErrorBuf);
01416 }
01417 }
01418
01419 if (last)
01420 {
01421 hiter_destroy(&last);
01422 }
01423
01424 if (makeTar && *errorBuf)
01425 {
01426
01427 intStatus = WriteFileBuffer(stdout, ERROR_LIST_PATH, errorBuf, strlen(errorBuf));
01428 if (tarStatus == ExpToStdoutStatus_Success)
01429 {
01430 tarStatus = intStatus;
01431 }
01432 }
01433 }
01434 else
01435 {
01436
01437 if (sizeof(generalErrorBuf) - strlen(generalErrorBuf) > 0)
01438 {
01439 snprintf(generalErrorBuf + strlen(generalErrorBuf), sizeof(generalErrorBuf) - strlen(generalErrorBuf), "%s", errorBufMsg);
01440 }
01441 }
01442 }
01443
01444 free(errorBuf);
01445 errorBuf = NULL;
01446 }
01447
01448 if (makeTar && ackFile && *ackFile)
01449 {
01450
01451 intStatus = WriteAckFile(stdout, ackFile);
01452 if (tarStatus == ExpToStdoutStatus_Success)
01453 {
01454 tarStatus = intStatus;
01455 }
01456 }
01457
01458
01459 if (makeTar && *generalErrorBuf)
01460 {
01461 intStatus = WriteFileBuffer(stdout, ERROR_PATH, generalErrorBuf, strlen(generalErrorBuf));
01462 if (tarStatus == ExpToStdoutStatus_Success)
01463 {
01464 tarStatus = intStatus;
01465 }
01466
01467 *generalErrorBuf = '\0';
01468 }
01469
01470 if (makeTar)
01471 {
01472
01473
01474 intStatus = DumpPadding(stdout, 0, TAR_BLOCK_SIZE * 2, NULL);
01475 if (tarStatus == ExpToStdoutStatus_Success)
01476 {
01477 tarStatus = intStatus;
01478 }
01479 }
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489 if (makeTar)
01490 {
01491 expStatus = ((expStatus != ExpToStdoutStatus_Success) ? expStatus : tarStatus);
01492 }
01493 else
01494 {
01495 expStatus = ((expStatus != ExpToStdoutStatus_Success) ? expStatus : intStatus);
01496 }
01497
01498 if (expRS)
01499 {
01500 drms_close_records(expRS, DRMS_FREE_RECORD);
01501 }
01502
01503 if (cparmsStrings)
01504 {
01505 list_llfree(&cparmsStrings);
01506 cparmsStrings = NULL;
01507 }
01508
01509 return expStatus;
01510 }