doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
file.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * $Id: file.c,v 1.52 2004/03/10 16:20:33 bagder Exp $
22  ***************************************************************************/
23 
24 #include "setup.h"
25 
26 #ifndef CURL_DISABLE_FILE
27 /* -- WIN32 approved -- */
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 
36 #include <errno.h>
37 
38 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
39 #include <time.h>
40 #include <io.h>
41 #include <fcntl.h>
42 #else
43 #ifdef HAVE_SYS_SOCKET_H
44 #include <sys/socket.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 #include <netinet/in.h>
48 #endif
49 #include <sys/time.h>
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53 #ifdef HAVE_NETDB_H
54 #include <netdb.h>
55 #endif
56 #ifdef HAVE_ARPA_INET_H
57 #include <arpa/inet.h>
58 #endif
59 #ifdef HAVE_NET_IF_H
60 #include <net/if.h>
61 #endif
62 #include <sys/ioctl.h>
63 #include <signal.h>
64 
65 #ifdef HAVE_SYS_PARAM_H
66 #include <sys/param.h>
67 #endif
68 
69 #ifdef HAVE_SYS_STAT_H
70 #include <sys/stat.h>
71 #endif
72 #ifdef HAVE_FCNTL_H
73 #include <fcntl.h>
74 #endif
75 
76 
77 #endif
78 
79 #include "urldata.h"
80 #include <curl/curl.h>
81 #include "progress.h"
82 #include "sendf.h"
83 #include "escape.h"
84 #include "file.h"
85 #include "speedcheck.h"
86 #include "getinfo.h"
87 #include "transfer.h" /* for Curl_readwrite_init() */
88 
89 #define _MPRINTF_REPLACE /* use our functions only */
90 #include <curl/mprintf.h>
91 
92 /* The last #include file should be: */
93 #ifdef CURLDEBUG
94 #include "memdebug.h"
95 #endif
96 
97 /* Emulate a connect-then-transfer protocol. We connect to the file here */
99 {
100  char *real_path = curl_unescape(conn->path, 0);
101  struct FILEPROTO *file;
102  int fd;
103 #if defined(WIN32) || defined(__EMX__)
104  int i;
105  char *actual_path;
106 #endif
107 
108  file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1);
109  if(!file)
110  return CURLE_OUT_OF_MEMORY;
111 
112  conn->proto.file = file;
113 
114 #if defined(WIN32) || defined(__EMX__)
115  /* If the first character is a slash, and there's
116  something that looks like a drive at the beginning of
117  the path, skip the slash. If we remove the initial
118  slash in all cases, paths without drive letters end up
119  relative to the current directory which isn't how
120  browsers work.
121 
122  Some browsers accept | instead of : as the drive letter
123  separator, so we do too.
124 
125  On other platforms, we need the slash to indicate an
126  absolute pathname. On Windows, absolute paths start
127  with a drive letter.
128  */
129  actual_path = real_path;
130  if ((actual_path[0] == '/') &&
131  actual_path[1] &&
132  (actual_path[2] == ':' || actual_path[2] == '|'))
133  {
134  actual_path[2] = ':';
135  actual_path++;
136  }
137 
138  /* change path separators from '/' to '\\' for Windows and OS/2 */
139  for (i=0; actual_path[i] != '\0'; ++i)
140  if (actual_path[i] == '/')
141  actual_path[i] = '\\';
142 
143  fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */
144 #else
145  fd = open(real_path, O_RDONLY);
146 #endif
147  free(real_path);
148 
149  if(fd == -1) {
150  failf(conn->data, "Couldn't open file %s", conn->path);
152  }
153  file->fd = fd;
154 
155  return CURLE_OK;
156 }
157 
158 #if defined(WIN32) && (SIZEOF_CURL_OFF_T > 4)
159 #define lseek(x,y,z) _lseeki64(x, y, z)
160 #endif
161 
162 /* This is the do-phase, separated from the connect-phase above */
163 
165 {
166  /* This implementation ignores the host name in conformance with
167  RFC 1738. Only local files (reachable via the standard file system)
168  are supported. This means that files on remotely mounted directories
169  (via NFS, Samba, NT sharing) can be accessed through a file:// URL
170  */
172  struct stat statbuf;
173  curl_off_t expected_size=0;
174  bool fstated=FALSE;
175  ssize_t nread;
176  struct SessionHandle *data = conn->data;
177  char *buf = data->state.buffer;
178  curl_off_t bytecount = 0;
179  int fd;
180  struct timeval now = Curl_tvnow();
181 
182  Curl_readwrite_init(conn);
183  Curl_initinfo(data);
184  Curl_pgrsStartNow(data);
185 
186  /* get the fd from the connection phase */
187  fd = conn->proto.file->fd;
188 
189  /* VMS: This only works reliable for STREAMLF files */
190  if( -1 != fstat(fd, &statbuf)) {
191  /* we could stat it, then read out the size */
192  expected_size = statbuf.st_size;
193  fstated = TRUE;
194  }
195 
196  /* If we have selected NOBODY and HEADER, it means that we only want file
197  information. Which for FILE can't be much more than the file size and
198  date. */
199  if(data->set.no_body && data->set.include_header && fstated) {
201  sprintf(buf, "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size);
202  result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
203  if(result)
204  return result;
205 
206  sprintf(buf, "Accept-ranges: bytes\r\n");
207  result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
208  if(result)
209  return result;
210 
211 #ifdef HAVE_STRFTIME
212  if(fstated) {
213  struct tm *tm;
214  time_t clock = (time_t)statbuf.st_mtime;
215 #ifdef HAVE_GMTIME_R
216  struct tm buffer;
217  tm = (struct tm *)gmtime_r(&clock, &buffer);
218 #else
219  tm = gmtime(&clock);
220 #endif
221  /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
222  strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S GMT\r\n",
223  tm);
224  result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
225  }
226 #endif
227  return result;
228  }
229 
230  /* Added by Dolbneff A.V & Spiridonoff A.V */
231  if (conn->resume_from <= expected_size)
232  expected_size -= conn->resume_from;
233  else
234  /* Is this error code suitable in such situation? */
236 
237  if (fstated && (expected_size == 0))
238  return CURLE_OK;
239 
240  /* The following is a shortcut implementation of file reading
241  this is both more efficient than the former call to download() and
242  it avoids problems with select() and recv() on file descriptors
243  in Winsock */
244  if(fstated)
245  Curl_pgrsSetDownloadSize(data, expected_size);
246 
247  if(conn->resume_from)
248  lseek(fd, conn->resume_from, SEEK_SET);
249 
251 
252  while (res == CURLE_OK) {
253  nread = read(fd, buf, BUFSIZE-1);
254 
255  if ( nread > 0)
256  buf[nread] = 0;
257 
258  if (nread <= 0)
259  break;
260 
261  bytecount += nread;
262  /* NOTE: The following call to fwrite does CR/LF translation on
263  Windows systems if the target is stdout. Use -O or -o parameters
264  to prevent CR/LF translation (this then goes to a binary mode
265  file descriptor). */
266 
267  res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
268  if(res)
269  return res;
270 
271  Curl_pgrsSetDownloadCounter(data, bytecount);
272 
273  if(Curl_pgrsUpdate(conn))
275  else
276  res = Curl_speedcheck (data, now);
277  }
278  if(Curl_pgrsUpdate(conn))
280 
281  close(fd);
282 
283  return res;
284 }
285 #endif
void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size)
Definition: progress.c:180
bool no_body
Definition: urldata.h:864
#define CLIENTWRITE_BOTH
Definition: sendf.h:36
#define CLIENTWRITE_BODY
Definition: sendf.h:34
CURLcode Curl_file_connect(struct connectdata *conn)
Definition: file.c:98
#define O_RDONLY
char buffer[BUFSIZE+1]
Definition: urldata.h:679
int fd
Definition: urldata.h:271
char * curl_unescape(const char *string, int length)
Definition: escape.c:86
CURLcode Curl_initinfo(struct SessionHandle *data)
Definition: getinfo.c:50
struct FILEPROTO * file
Definition: urldata.h:543
union connectdata::@11 proto
void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
Definition: progress.c:126
#define failf
Definition: sendf.h:32
CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr, size_t len)
Definition: sendf.c:319
CURLcode
Definition: curl.h:209
struct UrlState state
Definition: urldata.h:903
off_t curl_off_t
Definition: curl.h:96
int i
Definition: process.py:33
Boolean result
#define ssize_t
Definition: config-win32.h:27
curl_off_t resume_from
Definition: urldata.h:442
int Curl_pgrsUpdate(struct connectdata *conn)
Definition: progress.c:206
void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size)
Definition: progress.c:170
#define FORMAT_OFF_T
Definition: setup.h:99
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
GLuint buffer
Definition: glext.h:3108
bool include_header
Definition: urldata.h:859
struct tm * gmtime(const time_t *)
CURLcode Curl_speedcheck(struct SessionHandle *data, struct timeval now)
Definition: speedcheck.c:39
Definition: curl.h:210
struct SessionHandle * data
Definition: urldata.h:403
#define SEEK_SET
Definition: Unzip.cpp:129
CURLcode Curl_file(struct connectdata *conn)
Definition: file.c:164
#define FALSE
Definition: mprintf.c:70
struct timeval Curl_tvnow(void)
Definition: timeval.c:81
struct UserDefined set
Definition: urldata.h:898
char * path
Definition: urldata.h:431
GLuint res
Definition: glext.h:5385
#define TRUE
Definition: mprintf.c:69
CURLcode Curl_readwrite_init(struct connectdata *conn)
Definition: transfer.c:1274
void Curl_pgrsStartNow(struct SessionHandle *data)
Definition: progress.c:164
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
#define BUFSIZE
Definition: urldata.h:104
#define CURLE_FTP_BAD_DOWNLOAD_RESUME
Definition: curl.h:310