00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "config.h"
00037
00038 static char rcsid[] not_used =
00039 {"$Id: util.cc 16088 2007-03-28 21:42:19Z jimg $"
00040 };
00041
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <assert.h>
00045 #include <ctype.h>
00046 #ifndef TM_IN_SYS_TIME
00047 #include <time.h>
00048 #else
00049 #include <sys/time.h>
00050 #endif
00051
00052 #ifndef WIN32
00053 #include <unistd.h>
00054 #else
00055 #include <io.h>
00056 #include <fcntl.h>
00057 #include <process.h>
00058 #endif
00059
00060 #include <sys/types.h>
00061 #include <sys/stat.h>
00062
00063 #include <string>
00064 #include <sstream>
00065 #include <vector>
00066 #include <algorithm>
00067 #include <stdexcept>
00068
00069 #include "BaseType.h"
00070 #include "Str.h"
00071 #include "Url.h"
00072 #include "Sequence.h"
00073 #include "Error.h"
00074 #include "parser.h"
00075
00076 #include "util.h"
00077 #include "debug.h"
00078
00079
00080 using namespace std;
00081
00082
00083
00084
00093 string
00094 prune_spaces(const string &name)
00095 {
00096
00097 if (name.find_first_of(' ') == name.npos)
00098 return name;
00099 else {
00100
00101 unsigned int i = name.find_first_not_of(' ');
00102 string tmp_name = name.substr(i);
00103
00104
00105 unsigned int j = tmp_name.find('?') + 1;
00106 i = tmp_name.find_first_not_of(' ', j);
00107 tmp_name.erase(j, i - j);
00108
00109 return tmp_name;
00110 }
00111 }
00112
00113
00114
00115
00116 bool
00117 unique_names(vector<BaseType *> l, const string &var_name,
00118 const string &type_name, string &msg)
00119 {
00120
00121 vector<string> names(l.size());
00122
00123 int nelem = 0;
00124 typedef std::vector<BaseType *>::const_iterator citer ;
00125 for (citer i = l.begin(); i != l.end(); i++) {
00126 assert(*i);
00127 names[nelem++] = (*i)->name();
00128 DBG(cerr << "NAMES[" << nelem - 1 << "]=" << names[nelem-1] << endl);
00129 }
00130
00131
00132 sort(names.begin(), names.end());
00133
00134 #ifdef DODS_DEBUG2
00135 cout << "unique:" << endl;
00136 for (int ii = 0; ii < nelem; ++ii)
00137 cout << "NAMES[" << ii << "]=" << names[ii] << endl;
00138 #endif
00139
00140
00141 sort(names.begin(), names.end());
00142
00143 #ifdef DODS_DEBUG2
00144 cout << "unique:" << endl;
00145 for (int ii = 0; ii < nelem; ++ii)
00146 cout << "NAMES[" << ii << "]=" << names[ii] << endl;
00147 #endif
00148
00149
00150 for (int j = 1; j < nelem; ++j) {
00151 if (names[j-1] == names[j]) {
00152 ostringstream oss;
00153 oss << "The variable `" << names[j]
00154 << "' is used more than once in " << type_name << " `"
00155 << var_name << "'";
00156 msg = oss.str();
00157
00158 return false;
00159 }
00160 }
00161
00162 return true;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172 #ifndef __POWERPC__
00173 XDR *
00174 new_xdrstdio(FILE *stream, enum xdr_op xop)
00175 {
00176 XDR *xdr = new XDR;
00177
00178 xdrstdio_create(xdr, stream, xop);
00179
00180 return xdr;
00181 }
00182
00183 XDR *
00184 set_xdrstdio(XDR *xdr, FILE *stream, enum xdr_op xop)
00185 {
00186 xdrstdio_create(xdr, stream, xop);
00187
00188 return xdr;
00189 }
00190
00191
00192
00193
00194 void
00195 delete_xdrstdio(XDR *xdr)
00196 {
00197 xdr_destroy(xdr);
00198
00199 delete xdr; xdr = 0;
00200 }
00201 #endif
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 extern "C" bool_t
00219 xdr_str(XDR *xdrs, string &buf)
00220 {
00221 DBG(cerr << "In xdr_str, xdrs: " << xdrs << endl);
00222
00223 switch (xdrs->x_op) {
00224 case XDR_ENCODE: {
00225 const char *out_tmp = buf.c_str();
00226
00227 return xdr_string(xdrs, (char **)&out_tmp, max_str_len);
00228 }
00229
00230 case XDR_DECODE: {
00231 char *in_tmp = NULL;
00232
00233 bool_t stat = xdr_string(xdrs, &in_tmp, max_str_len);
00234 if (!stat)
00235 return stat;
00236
00237 buf = in_tmp;
00238
00239 free(in_tmp);
00240
00241 return stat;
00242 }
00243
00244 default:
00245 assert(false);
00246 return 0;
00247 }
00248 }
00249
00250 const char *
00251 libdap_root()
00252 {
00253 char *libdap_root = 0;
00254 return ((libdap_root = getenv("LIBDAP_ROOT")) ? libdap_root : LIBDAP_ROOT);
00255 }
00256
00257 extern "C"
00258 const char *
00259 libdap_version()
00260 {
00261 return PACKAGE_VERSION;
00262 }
00263
00264 extern "C"
00265 const char *
00266 libdap_name()
00267 {
00268 return PACKAGE_NAME;
00269 }
00270
00271
00272
00273
00274
00275 #if COMPRESSION_FOR_SERVER3
00276
00277
00278
00279
00280
00281
00282
00283
00284 bool
00285 deflate_exists()
00286 {
00287 DBG(cerr << "Entering deflate_exists...");
00288
00289 int status = false;
00290 struct stat buf;
00291
00292 #ifdef WIN32
00293 string deflate = (string)libdap_root() + "\\bin\\deflate";
00294 #else
00295 string deflate = (string)libdap_root() + "/sbin/deflate";
00296 #endif
00297
00298
00299
00300
00301
00302
00303 status = (stat(deflate.c_str(), &buf) == 0)
00304 #ifdef WIN32
00305 || (stat(".\\deflate", &buf) == 0);
00306 #else
00307 || (stat("./deflate", &buf) == 0);
00308 #endif
00309
00310
00311 #ifdef WIN32
00312 status &= (buf.st_mode & _S_IEXEC);
00313 #else
00314 status &= buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH);
00315 #endif
00316 DBG(cerr << " returning " << (status ? "true." : "false.") << endl);
00317 return (status != 0);
00318 }
00319
00320 FILE *
00321 compressor(FILE *output, int &childpid)
00322 {
00323 #ifdef WIN32
00324
00325
00326
00327 int pid, data[2];
00328 int hStdIn, hStdOut;
00329
00330 if (_pipe(data, 512, O_BINARY | O_NOINHERIT) < 0) {
00331 cerr << "Could not create IPC channel for compressor process"
00332 << endl;
00333 return NULL;
00334 }
00335
00336
00337
00338
00339
00340
00341 hStdIn = _dup(_fileno(stdin));
00342 hStdOut = _dup(_fileno(stdout));
00343
00344
00345 if (_dup2(data[0], _fileno(stdin)) != 0) {
00346 cerr << "dup of child stdin failed" << endl;
00347 return NULL;
00348 }
00349
00350 if (_dup2(_fileno(output), _fileno(stdout)) != 0) {
00351 cerr << "dup of child stdout failed" << endl;
00352 return NULL;
00353 }
00354
00355
00356 string deflate = "deflate.exe";
00357 if ((pid = _spawnlp(_P_NOWAIT, deflate.c_str(), deflate.c_str(),
00358 "-c", "5", "-s", NULL)) < 0) {
00359 cerr << "Could not spawn to create compressor process" << endl;
00360 return NULL;
00361 }
00362
00363
00364 if (_dup2(hStdIn, _fileno(stdin)) != 0) {
00365 cerr << "dup of stdin failed" << endl;
00366 return NULL;
00367 }
00368 if (_dup2(hStdOut, _fileno(stdout)) != 0) {
00369 cerr << "dup of stdout failed" << endl;
00370 return NULL;
00371 }
00372 close(hStdIn);
00373 close(hStdOut);
00374
00375
00376
00377 close(data[0]);
00378 FILE *input = fdopen(data[1], "w");
00379 setbuf(input, 0);
00380 childpid = pid;
00381 return input;
00382
00383 #else
00384 FILE *ret_file = NULL ;
00385
00386 int pid, data[2];
00387
00388 if (pipe(data) < 0) {
00389 cerr << "Could not create IPC channel for compressor process"
00390 << endl;
00391 return NULL;
00392 }
00393
00394 if ((pid = fork()) < 0) {
00395 cerr << "Could not fork to create compressor process" << endl;
00396 return NULL;
00397 }
00398
00399
00400
00401
00402
00403 if (pid > 0) {
00404 close(data[0]);
00405 ret_file = fdopen(data[1], "w");
00406 setbuf(ret_file, 0);
00407 childpid = pid;
00408 }
00409 else {
00410 close(data[1]);
00411 dup2(data[0], 0);
00412 dup2(fileno(output), 1);
00413
00414 DBG(cerr << "Opening compression stream." << endl);
00415
00416
00417
00418
00419 string deflate = (string)libdap_root() + "/sbin/deflate";
00420 (void) execl(deflate.c_str(), "deflate", "-c", "5", "-s", NULL);
00421 (void) execl("./deflate", "deflate", "-c", "5", "-s", NULL);
00422 cerr << "Warning: Could not start compressor!" << endl;
00423 cerr << "defalte should be in DODS_ROOT/etc or in the CWD!"
00424 << endl;
00425 _exit(127);
00426 }
00427
00428 return ret_file ;
00429 #endif
00430 }
00431
00432 #endif // COMPRESSION_FOR_SERVER3
00433
00434
00435
00436
00437 string
00438 systime()
00439 {
00440 time_t TimBin;
00441
00442 if (time(&TimBin) == (time_t) - 1)
00443 return string("time() error");
00444 else {
00445 string TimStr = ctime(&TimBin);
00446 return TimStr.substr(0, TimStr.size() - 2);
00447 }
00448 }
00449
00450 void
00451 downcase(string &s)
00452 {
00453 for (unsigned int i = 0; i < s.length(); i++)
00454 s[i] = tolower(s[i]);
00455 }
00456
00457 #ifdef WIN32
00458
00459
00460
00461
00462
00463 void flush_stream(iostream ios, FILE *out)
00464 {
00465 int nbytes;
00466 char buffer[512];
00467
00468 ios.get(buffer, 512, NULL);
00469 while ((nbytes = ios.gcount()) > 0) {
00470 fwrite(buffer, 1, nbytes, out);
00471 ios.get(buffer, 512, NULL);
00472 }
00473
00474 return;
00475 }
00476 #endif
00477
00478
00479 void
00480 append_long_to_string(long val, int base, string &str_val)
00481 {
00482
00483
00484
00485 char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00486
00487 ldiv_t r;
00488
00489 if (base > 36 || base < 2) {
00490
00491 std::invalid_argument ex("The parameter base has an invalid value.");
00492 throw ex;
00493 }
00494 if (val < 0)
00495 str_val += '-';
00496 r = ldiv(labs(val), base);
00497
00498
00499 if (r.quot > 0)
00500 append_long_to_string(r.quot, base, str_val);
00501
00502
00503
00504 str_val += digits[(int)r.rem];
00505 }
00506
00507
00508 string
00509 long_to_string(long val, int base)
00510 {
00511 string s;
00512 append_long_to_string(val, base, s);
00513 return s;
00514 }
00515
00516
00517 void append_double_to_string(const double &num, string &str)
00518 {
00519
00520
00521 ostringstream oss;
00522 oss.precision(9);
00523 oss << num;
00524 str += oss.str();
00525 }
00526
00527 string
00528 double_to_string(const double &num)
00529 {
00530 string s;
00531 append_double_to_string(num, s);
00532 return s;
00533 }
00534
00535
00536
00537
00538 string
00539 dap_version()
00540 {
00541 return (string)"OPeNDAP DAP/" + libdap_version() + ": compiled on " + __DATE__ + ":" + __TIME__ ;
00542 }
00543
00544
00545
00546
00547
00548
00549
00550 #ifdef WIN32
00551 static const char path_sep[] =
00552 {"\\"
00553 };
00554 #else
00555 static const char path_sep[] =
00556 {"/"
00557 };
00558 #endif
00559
00560 string
00561 path_to_filename(string path)
00562 {
00563 string::size_type pos = path.rfind(path_sep);
00564
00565 return (pos == string::npos) ? path : path.substr(++pos);
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575 char *
00576 get_tempfile_template(char *file_template)
00577 {
00578 char *c;
00579 #ifdef WIN32
00580 if (getenv("TEMP") && (access(getenv("TEMP"), 6) == 0))
00581 c = getenv("TEMP");
00582 else if (getenv("TMP"))
00583 c = getenv("TMP");
00584 #else
00585 if (getenv("TMPDIR") && (access(getenv("TMPDIR"), W_OK | R_OK) == 0))
00586 c = getenv("TMPDIR");
00587 #ifdef P_tmpdir
00588 else if (access(P_tmpdir, W_OK | R_OK) == 0)
00589 c = P_tmpdir;
00590 #endif
00591 #endif
00592 else
00593 c = ".";
00594
00595 char *temp = new char[strlen(c) + strlen(file_template) + 2];
00596 strcpy(temp, c);
00597 strcat(temp, "/");
00598
00599 strcat(temp, file_template);
00600
00601 return temp;
00602 }
00603
00609 #ifndef WIN32
00610 FILE *
00611 get_temp_file(char *temp)
00612 {
00613 int fd = mkstemp(temp);
00614 if (fd < 0)
00615 return 0;
00616 FILE *tmp = fdopen(fd, "a+");
00617 return tmp;
00618 }
00619 #endif
00620
00625 string
00626 file_to_string(FILE *fp)
00627 {
00628 rewind(fp);
00629 ostringstream oss;
00630 char c;
00631 while (fread(&c, 1, 1, fp))
00632 oss << c;
00633 return oss.str();
00634 }