]>
git.ipfire.org Git - thirdparty/squid.git/blob - tools/purge/copyout.cc
7d792c30c6d051837c50118824affd4c72598ec6
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 // Author: Jens-S. V?ckler <voeckler@rvs.uni-hannover.de>
14 // (c) 1999 Lehrgebiet Rechnernetze und Verteilte Systeme
15 // Universit?t Hannover, Germany
17 // Permission to use, copy, modify, distribute, and sell this software
18 // and its documentation for any purpose is hereby granted without fee,
19 // provided that (i) the above copyright notices and this permission
20 // notice appear in all copies of the software and related documentation,
21 // and (ii) the names of the Lehrgebiet Rechnernetze und Verteilte
22 // Systeme and the University of Hannover may not be used in any
23 // advertising or publicity relating to the software without the
24 // specific, prior written permission of Lehrgebiet Rechnernetze und
25 // Verteilte Systeme and the University of Hannover.
27 // THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
29 // WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
31 // IN NO EVENT SHALL THE LEHRGEBIET RECHNERNETZE UND VERTEILTE SYSTEME OR
32 // THE UNIVERSITY OF HANNOVER BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
33 // INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
34 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
35 // ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
36 // ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
39 // Revision 1.2 1999/06/16 13:05:26 voeckler
40 // mmap file copying on Solaris.
42 // Revision 1.1 1999/06/15 21:10:47 voeckler
61 assert_copydir( const char* copydir
)
62 // purpose: check, if copydir is a directory and that we can write into it.
63 // paramtr: copydir (IN): name of directory for copying bodies.
64 // returns: 0 if ok, -1 otherwise.
65 // further: errors are handled within. If the directory does not exist,
66 // the assertion function will try to create it.
69 int status
= stat( copydir
, &st
);
71 // check, if either "copydir" points to a valid directory,
72 // or if copydir can be created.
73 if ( status
== 0 && ! S_ISDIR(st
.st_mode
) ) {
74 // stat() returned true, but did not point to a directory
75 fprintf( stderr
, "copy dir \"%s\" is a file!\n", copydir
);
77 } else if ( S_ISDIR(st
.st_mode
) &&
78 !( (st
.st_uid
== geteuid() && ( (st
.st_mode
& S_IWUSR
) > 0 )) ||
79 (st
.st_gid
== getegid() && ( (st
.st_mode
& S_IWGRP
) > 0 )) ||
80 ((st
.st_mode
& S_IWOTH
) > 0) ) ) {
81 fprintf( stderr
, "copy dir \"%s\" is not accessible to me\n", copydir
);
85 // stat() returned with an error. 'File not found' is a legal error.
86 if ( errno
!= ENOENT
) {
87 // not a 'file not found' error, so this is hard error.
88 fprintf( stderr
, "accessing copy-out dir \"%s\": %s\n",
89 copydir
, strerror(errno
) );
92 // directory does not exist. Try to create it.
93 if ( mkdir( copydir
, 0750 ) == -1 ) {
94 fprintf( stderr
, "mkdir(%s): %s\n", copydir
, strerror(errno
) );
100 // postcondition: copydir exists and is a directory.
108 if ( ch
== '\r' ) return 0u;
109 else if ( ch
== '\n' ) return 1u;
113 // shortcut for monotoneous typings...
114 #define BAUTZ(x) delete[] filename; close(input); close(out); return (x)
117 copy_out( size_t filesize
, size_t metasize
, unsigned debug
,
118 const char* fn
, const char* url
, const char* copydir
,
120 // purpose: copy content from squid disk file into separate file
121 // paramtr: metasize (IN): size of metadata to skip
122 // fn (IN): current filename of squid disk file
123 // url (IN): currently looked at URL to generate separate file
124 // copydir (IN): base directory where to generate the file
125 // copyHdr (IN): copy HTTP header, too, if set to true.
126 // returns: true, if successful, false otherwise.
128 static const char* index
= "index.html";
130 // find hostname part after the scheme (okok, not counting port, etc.)
131 const char* ptr
= strstr( url
, "://" );
132 if ( ptr
== 0 || strlen(ptr
) < 4 ) return false;
134 // create filename to store contents into
135 // NP: magic extra 5 bytes for the component delimiter and termination octets
136 char *filename
= new char[ strlen(ptr
) + strlen(copydir
) + strlen(index
) +5 ];
137 assert( filename
!= 0 );
138 strcpy( filename
, copydir
);
139 strcat( filename
, "/" );
140 char* here
= filename
+ strlen(filename
);
141 strcat( filename
, ptr
+3 );
143 // handle server root (e.g. "http://www.focus.de" )
144 if ( strchr( ptr
+3, '/' ) == 0 ) strcat( filename
, "/" );
146 // handle directories (e.g. "http://www.focus.de/A/" )
147 if ( filename
[strlen(filename
)-1] == '/' ) strcat( filename
, index
);
149 // create subdirectory structure
150 for ( char* t
= strchr(here
,'/'); t
; t
= strchr(t
,'/') ) {
152 if ( mkdir( filename
, 0775 ) == -1 && errno
!= EEXIST
) {
153 fprintf( stderr
, "mkdir(%s): %s\n", filename
, strerror(errno
) );
156 } else if ( debug
& 0x02 ) {
157 fprintf( stderr
, "# creating %s\n", filename
);
164 int out
= open( filename
, O_CREAT
| O_RDWR
| O_TRUNC
, 0664 );
166 fprintf( stderr
, "open(%s,RDWR): %s\n", filename
, strerror(errno
) );
169 } else if ( debug
& 0x02 ) {
170 fprintf( stderr
, "# creating %s\n", filename
);
173 // (re)open cache file
174 int input
= open( fn
, O_RDONLY
);
176 fprintf( stderr
, "open(%s,RDONLY): %s\n", fn
, strerror(errno
) );
182 // find double CRLF sequence (actually, look at the FSM below)
183 // FIXME: this only looks at the already known buffer read previously,
184 // which is globally passed (yuck)! As a limitation, the content data
185 // *must* begin within the buffer size (that is: 16k)!
187 extern char* linebuffer
; // import from purge.cc
188 extern size_t buffersize
; // import from purge.cc
191 char* s
= linebuffer
+ metasize
;
192 while ( s
< linebuffer
+ buffersize
&& state
< 4 ) {
193 // state transition machine
194 static unsigned table
[4][3] = { {3,2,0}, {0,4,0}, {1,4,0}, {4,2,0} };
195 // old || \r | \n |else|
196 // =====++====+====+====+
201 state
= table
[ state
][ xlate(*s
) ];
206 // complain bitterly, if the HTTP header was too large ( > 16k ).
207 fprintf( stderr
, "WARNING: %s will contain partial HTTP header data!\n",
210 // adjust to different seek size
211 metasize
= s
- linebuffer
;
214 // no need to copy zero content files
215 if ( filesize
- metasize
<= 0 ) {
216 BAUTZ( filesize
-metasize
== 0 );
219 #ifdef USE_REGULAR_COPY
220 // position input at start of server answer (contains HTTP headers)
221 if ( lseek( input
, metasize
, SEEK_SET
) == -1 ) {
222 fprintf( stderr
, "lseek(%s,%lu): %s\n", fn
, metasize
, strerror(errno
) );
226 // file copy input into output via buffer (regular io)
229 while ( (rsize
=read(input
,buffer
,sizeof(buffer
))) > 0 ) {
230 if ( (wsize
=write(out
,buffer
,rsize
)) <= 0 ) break;
232 if ( rsize
< 0 || wsize
< 0 ) perror( "while copying" );
233 #else // use mmap copy (compare: Stevens APUE 12.9)
234 // precondition: filesize-metasize > 0
235 // seek end of output file ...
236 off_t position
= lseek( out
, filesize
-metasize
-1, SEEK_SET
);
237 if ( position
== -1 ) {
238 fprintf( stderr
, "lseek(%s,%lu): %s\n", filename
,
239 (unsigned long)filesize
-metasize
,
242 } else if ( debug
& 0x02 ) {
243 fprintf( stderr
, "# filesize=%lu, metasize=%lu, filepos=%ld\n",
244 (unsigned long)filesize
, (unsigned long)metasize
,
248 // ...and write 1 byte there (create a file that length)
249 if ( write( out
, "", 1 ) != 1 ) {
250 perror( "write to output" );
254 // create source mmap to copy from (mmap complete file)
255 caddr_t src
= (caddr_t
) mmap( 0, filesize
, PROT_READ
,
256 MAP_FILE
| MAP_SHARED
, input
, 0 );
257 if ( src
== (caddr_t
) -1 ) {
258 perror( "mmap input" );
262 // create destination mmap to copy into (mmap data portion)
263 caddr_t dst
= (caddr_t
) mmap( 0, filesize
-metasize
, PROT_READ
| PROT_WRITE
,
264 MAP_FILE
| MAP_SHARED
, out
, 0 );
265 if ( dst
== (caddr_t
) -1 ) {
266 perror( "mmap output" );
267 munmap( src
, filesize
);
271 // copy file (beware of offset into wanted data, skip meta data)
272 memcpy( dst
, src
+metasize
, filesize
-metasize
);
275 munmap( dst
, filesize
-metasize
);
276 munmap( src
, filesize
);
277 #endif // USE_REGULAR_COPY