1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4#include "config.h"
5#ifdef HAVE_SYS_STAT_H
6#include <sys/stat.h>
7#endif
8#ifdef HAVE_UNISTD_H
9#include <unistd.h>
10#endif
11#ifdef HAVE_FCNTL_H
12#include <fcntl.h>
13#endif
14#ifdef HAVE_SYS_TYPES_H
15#include <sys/types.h>
16#endif
17#ifdef HAVE_NETINET_IN_H
18#include <netinet/in.h>
19#endif
20#ifdef _WIN32
21#include <io.h>
22#endif
23#include "ocinternal.h"
24#include "ocdebug.h"
25#include "ochttp.h"
26#include "ocread.h"
27#include "occurlfunctions.h"
28
29/*Forward*/
30static int readpacket(OCstatestateOCURI*, OCbytes*, OCdxd, long*);
31static int readfile(const char* path, const char* suffixOCbytespacket);
32static int readfiletofile(const char* path, const char* suffixFILEstreamoff_t*);
33
34int
35readDDS(OCstatestateOCtreetree)
36{
37    int stat = OC_NOERR;
38    long lastmodified = -1;
39
40    ocurisetconstraints(state->uri,tree->constraint);
41
42#ifdef OCDEBUG
43fprintf(stderr,"readDDS:\n");
44#endif
45    stat = readpacket(state,state->uri,state->packet,OCDDS,
46 &lastmodified);
47    if(stat == OC_NOERRstate->ddslastmodified = lastmodified;
48
49    return stat;
50}
51
52int
53readDAS(OCstatestateOCtreetree)
54{
55    int stat = OC_NOERR;
56
57    ocurisetconstraints(state->uri,tree->constraint);
58#ifdef OCDEBUG
59fprintf(stderr,"readDAS:\n");
60#endif
61    stat = readpacket(state,state->uri,state->packet,OCDAS,NULL);
62
63    return stat;
64}
65
66#if 0
67int
68readversion(OCstatestateOCURIurlOCbytespacket)
69{
70   return readpacket(state,url,packet,OCVER,NULL);
71}
72#endif
73
74const char*
75ocdxdextension(OCdxd dxd)
76{
77    switch(dxd) {
78    case OCDDS: return ".dds";
79    case OCDAS: return ".das";
80    case OCDATADDS: return ".dods";
81    default: break;
82    }
83    return NULL;
84}
85
86static int
87readpacket(OCstatestateOCURIurl,OCbytespacket,OCdxd dxd,long* lastmodified)
88{
89   int stat = OC_NOERR;
90   int fileprotocol = 0;
91   const char* suffix = ocdxdextension(dxd);
92   char* fetchurl = NULL;
93   CURLcurl = state->curl;
94
95   fileprotocol = (strcmp(url->protocol,"file")==0);
96
97   if(fileprotocol && !state->curlflags.proto_file) {
98        /* Short circuit file://... urls*/
99 /* We do this because the test code always needs to read files*/
100 fetchurl = ocuribuild(url,NULL,NULL,0);
101 stat = readfile(fetchurl,suffix,packet);
102    } else {
103 int flags = 0;
104 if(!fileprotocol) {
105     flags |= OCURICONSTRAINTS;
106 }
107 flags |= OCURIENCODE;
108        fetchurl = ocuribuild(url,NULL,suffix,flags);
109 MEMCHECK(fetchurl,OC_ENOMEM);
110 if(ocdebug > 0)
111            {fprintf(stderr,"fetch url=%s\n",fetchurl); fflush(stderr);}
112        stat = ocfetchurl(curl,fetchurl,packet,lastmodified,&state->creds);
113 if(stat)
114     oc_curl_printerror(state);
115 if(ocdebug > 0)
116            {fprintf(stderr,"fetch complete\n"); fflush(stderr);}
117    }
118    free(fetchurl);
119#ifdef OCDEBUG
120  {
121fprintf(stderr,"readpacket: packet.size=%lu\n",
122 (unsigned long)ocbyteslength(packet));
123  }
124#endif
125    return OCTHROW(stat);
126}
127
128int
129readDATADDS(OCstatestateOCtreetreeOCflags flags)
130{
131    int stat = OC_NOERR;
132    long lastmod = -1;
133
134#ifdef OCDEBUG
135fprintf(stderr,"readDATADDS:\n");
136#endif
137    if((flags & OCONDISK) == 0) {
138        ocurisetconstraints(state->uri,tree->constraint);
139        stat = readpacket(state,state->uri,state->packet,OCDATADDS,&lastmod);
140        if(stat == OC_NOERR)
141            state->datalastmodified = lastmod;
142        tree->data.datasize = ocbyteslength(state->packet);
143    } else { /*((flags & OCONDISK) != 0) */
144        OCURIurl = state->uri;
145        int fileprotocol = 0;
146        char* readurl = NULL;
147
148        fileprotocol = (strcmp(url->protocol,"file")==0);
149
150        if(fileprotocol && !state->curlflags.proto_file) {
151            readurl = ocuribuild(url,NULL,NULL,0);
152            stat = readfiletofile(readurl, ".dods", tree->data.file, &tree->data.datasize);
153        } else {
154            int flags = 0;
155            if(!fileprotocolflags |= OCURICONSTRAINTS;
156            flags |= OCURIENCODE;
157     flags |= OCURIUSERPWD;
158            ocurisetconstraints(url,tree->constraint);
159            readurl = ocuribuild(url,NULL,".dods",flags);
160            MEMCHECK(readurl,OC_ENOMEM);
161            if (ocdebug > 0)
162                {fprintf(stderr, "fetch url=%s\n", readurl);fflush(stderr);}
163            stat = ocfetchurl_file(state->curlreadurltree->data.file,
164                                   &tree->data.datasize, &lastmod);
165            if(stat == OC_NOERR)
166                state->datalastmodified = lastmod;
167            if (ocdebug > 0)
168                {fprintf(stderr,"fetch complete\n"); fflush(stderr);}
169        }
170        free(readurl);
171    }
172    return OCTHROW(stat);
173}
174
175static int
176readfiletofile(const char* path, const char* suffixFILEstreamoff_tsizep)
177{
178    int stat = OC_NOERR;
179    OCbytespacket = ocbytesnew();
180    size_t len;
181    /* check for leading file:/// */
182    if(ocstrncmp(path,"file:///",8)==0) path += 7; /* assume absolute path*/
183    stat = readfile(path,suffix,packet);
184#ifdef OCDEBUG
185fprintf(stderr,"readfiletofile: packet.size=%lu\n",
186 (unsigned long)ocbyteslength(packet));
187#endif
188    if(stat != OC_NOERR) goto unwind;
189    len = oclistlength(packet);
190    if(stat == OC_NOERR) {
191 size_t written;
192        fseek(stream,0,SEEK_SET);
193 written = fwrite(ocbytescontents(packet),1,len,stream);
194 if(written != len) {
195#ifdef OCDEBUG
196fprintf(stderr,"readfiletofile: written!=length: %lu :: %lu\n",
197 (unsigned long)written,(unsigned long)len);
198#endif
199     stat = OC_EIO;
200 }
201    }
202    if(sizep != NULL) *sizep = len;
203unwind:
204    ocbytesfree(packet);
205    return OCTHROW(stat);
206}
207
208static int
209readfile(const char* path, const char* suffixOCbytespacket)
210{
211    int stat = OC_NOERR;
212    char buf[1024];
213    char filename[1024];
214    int fd = -1;
215    int flags = 0;
216    off_t filesize = 0;
217    off_t totalread = 0;
218    /* check for leading file:/// */
219    if(ocstrncmp(path,"file://",7)==0) path += 7; /* assume absolute path*/
220    if(!occopycat(filename,sizeof(filename),2,path,(suffix != NULL ? suffix : "")))
221 return OCTHROW(OC_EOVERRUN);
222    flags = O_RDONLY;
223#ifdef O_BINARY
224    flags |= O_BINARY;
225#endif
226    fd = open(filename,flags);
227    if(fd < 0) {
228 oclog(OCLOGERR,"open failed:%s",filename);
229 return OCTHROW(OC_EOPEN);
230    }
231    /* Get the file size */
232    filesize = lseek(fd,(off_t)0,SEEK_END);
233    if(filesize < 0) {
234 stat = OC_EIO;
235 oclog(OCLOGERR,"lseek failed: %s",filename);
236 goto done;
237    }
238    /* Move file pointer back to the beginning of the file */
239    (void)lseek(fd,(off_t)0,SEEK_SET);
240    stat = OC_NOERR;
241    for(totalread=0;;) {
242 off_t count = (off_t)read(fd,buf,sizeof(buf));
243 if(count == 0)
244     break; /*eof*/
245 else if(count <  0) {
246     stat = OC_EIO;
247     oclog(OCLOGERR,"read failed: %s",filename);
248     goto done;
249 }
250 ocbytesappendn(packet,buf,(unsigned long)count);
251 totalread += count;
252    }
253    if(totalread < filesize) {
254 stat = OC_EIO;
255 oclog(OCLOGERR,"short read: |%s|=%lu read=%lu\n",
256 filename,(unsigned long)filesize,(unsigned long)totalread);
257        goto done;
258    }
259
260done:
261#ifdef OCDEBUG
262fprintf(stderr,"readfile: filesize=%lu totalread=%lu\n",
263 (unsigned long)filesize,(unsigned long)totalread);
264#endif
265    if(fd >= 0) close(fd);
266    return OCTHROW(stat);
267}
268
269


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed