Fix BlueSky build on modern Linux and libs3.
[bluesky.git] / libs3-1.4 / src / object.c
1 /** **************************************************************************
2  * object.c
3  * 
4  * Copyright 2008 Bryan Ischo <bryan@ischo.com>
5  * 
6  * This file is part of libs3.
7  * 
8  * libs3 is free software: you can redistribute it and/or modify it under the
9  * terms of the GNU General Public License as published by the Free Software
10  * Foundation, version 3 of the License.
11  *
12  * In addition, as a special exception, the copyright holders give
13  * permission to link the code of this library and its programs with the
14  * OpenSSL library, and distribute linked combinations including the two.
15  *
16  * libs3 is distributed in the hope that it will be useful, but WITHOUT ANY
17  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License version 3
22  * along with libs3, in a file named COPYING.  If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  ************************************************************************** **/
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include "libs3.h"
30 #include "request.h"
31
32
33 // put object ----------------------------------------------------------------
34
35 void S3_put_object(const S3BucketContext *bucketContext, const char *key,
36                    uint64_t contentLength,
37                    const S3PutProperties *putProperties,
38                    S3RequestContext *requestContext,
39                    const S3PutObjectHandler *handler, void *callbackData)
40 {
41     // Set up the RequestParams
42     RequestParams params =
43     {
44         HttpRequestTypePUT,                           // httpRequestType
45         { bucketContext->bucketName,                  // bucketName
46           bucketContext->protocol,                    // protocol
47           bucketContext->uriStyle,                    // uriStyle
48           bucketContext->accessKeyId,                 // accessKeyId
49           bucketContext->secretAccessKey },           // secretAccessKey
50         key,                                          // key
51         0,                                            // queryParams
52         0,                                            // subResource
53         0,                                            // copySourceBucketName
54         0,                                            // copySourceKey
55         0,                                            // getConditions
56         0,                                            // startByte
57         0,                                            // byteCount
58         putProperties,                                // putProperties
59         handler->responseHandler.propertiesCallback,  // propertiesCallback
60         handler->putObjectDataCallback,               // toS3Callback
61         contentLength,                                // toS3CallbackTotalSize
62         0,                                            // fromS3Callback
63         handler->responseHandler.completeCallback,    // completeCallback
64         callbackData                                  // callbackData
65     };
66
67     // Perform the request
68     request_perform(&params, requestContext);
69 }
70
71
72 // copy object ---------------------------------------------------------------
73
74
75 typedef struct CopyObjectData
76 {
77     SimpleXml simpleXml;
78
79     S3ResponsePropertiesCallback *responsePropertiesCallback;
80     S3ResponseCompleteCallback *responseCompleteCallback;
81     void *callbackData;
82
83     int64_t *lastModifiedReturn;
84     int eTagReturnSize;
85     char *eTagReturn;
86     int eTagReturnLen;
87     
88     string_buffer(lastModified, 256);
89 } CopyObjectData;
90
91
92 static S3Status copyObjectXmlCallback(const char *elementPath,
93                                       const char *data, int dataLen,
94                                       void *callbackData)
95 {
96     CopyObjectData *coData = (CopyObjectData *) callbackData;
97
98     int fit;
99
100     if (data) {
101         if (!strcmp(elementPath, "CopyObjectResult/LastModified")) {
102             string_buffer_append(coData->lastModified, data, dataLen, fit);
103         }
104         else if (!strcmp(elementPath, "CopyObjectResult/ETag")) {
105             if (coData->eTagReturnSize && coData->eTagReturn) {
106                 coData->eTagReturnLen +=
107                     snprintf(&(coData->eTagReturn[coData->eTagReturnLen]),
108                              coData->eTagReturnSize - 
109                              coData->eTagReturnLen - 1,
110                              "%.*s", dataLen, data);
111                 if (coData->eTagReturnLen >= coData->eTagReturnSize) {
112                     return S3StatusXmlParseFailure;
113                 }
114             }
115         }
116     }
117
118     return S3StatusOK;
119 }
120
121
122 static S3Status copyObjectPropertiesCallback
123     (const S3ResponseProperties *responseProperties, void *callbackData)
124 {
125     CopyObjectData *coData = (CopyObjectData *) callbackData;
126     
127     return (*(coData->responsePropertiesCallback))
128         (responseProperties, coData->callbackData);
129 }
130
131
132 static S3Status copyObjectDataCallback(int bufferSize, const char *buffer,
133                                        void *callbackData)
134 {
135     CopyObjectData *coData = (CopyObjectData *) callbackData;
136
137     return simplexml_add(&(coData->simpleXml), buffer, bufferSize);
138 }
139
140
141 static void copyObjectCompleteCallback(S3Status requestStatus, 
142                                        const S3ErrorDetails *s3ErrorDetails,
143                                        void *callbackData)
144 {
145     CopyObjectData *coData = (CopyObjectData *) callbackData;
146
147     if (coData->lastModifiedReturn) {
148         time_t lastModified = -1;
149         if (coData->lastModifiedLen) {
150             lastModified = parseIso8601Time(coData->lastModified);
151         }
152
153         *(coData->lastModifiedReturn) = lastModified;
154     }
155
156     (*(coData->responseCompleteCallback))
157         (requestStatus, s3ErrorDetails, coData->callbackData);
158
159     simplexml_deinitialize(&(coData->simpleXml));
160
161     free(coData);
162 }
163
164
165 void S3_copy_object(const S3BucketContext *bucketContext, const char *key,
166                     const char *destinationBucket, const char *destinationKey,
167                     const S3PutProperties *putProperties,
168                     int64_t *lastModifiedReturn, int eTagReturnSize,
169                     char *eTagReturn, S3RequestContext *requestContext,
170                     const S3ResponseHandler *handler, void *callbackData)
171 {
172     // Create the callback data
173     CopyObjectData *data = 
174         (CopyObjectData *) malloc(sizeof(CopyObjectData));
175     if (!data) {
176         (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData);
177         return;
178     }
179
180     simplexml_initialize(&(data->simpleXml), &copyObjectXmlCallback, data);
181
182     data->responsePropertiesCallback = handler->propertiesCallback;
183     data->responseCompleteCallback = handler->completeCallback;
184     data->callbackData = callbackData;
185
186     data->lastModifiedReturn = lastModifiedReturn;
187     data->eTagReturnSize = eTagReturnSize;
188     data->eTagReturn = eTagReturn;
189     if (data->eTagReturnSize && data->eTagReturn) {
190         data->eTagReturn[0] = 0;
191     }
192     data->eTagReturnLen = 0;
193     string_buffer_initialize(data->lastModified);
194
195     // Set up the RequestParams
196     RequestParams params =
197     {
198         HttpRequestTypeCOPY,                          // httpRequestType
199         { destinationBucket ? destinationBucket : 
200           bucketContext->bucketName,                  // bucketName
201           bucketContext->protocol,                    // protocol
202           bucketContext->uriStyle,                    // uriStyle
203           bucketContext->accessKeyId,                 // accessKeyId
204           bucketContext->secretAccessKey },           // secretAccessKey
205         destinationKey ? destinationKey : key,        // key
206         0,                                            // queryParams
207         0,                                            // subResource
208         bucketContext->bucketName,                    // copySourceBucketName
209         key,                                          // copySourceKey
210         0,                                            // getConditions
211         0,                                            // startByte
212         0,                                            // byteCount
213         putProperties,                                // putProperties
214         &copyObjectPropertiesCallback,                // propertiesCallback
215         0,                                            // toS3Callback
216         0,                                            // toS3CallbackTotalSize
217         &copyObjectDataCallback,                      // fromS3Callback
218         &copyObjectCompleteCallback,                  // completeCallback
219         data                                          // callbackData
220     };
221
222     // Perform the request
223     request_perform(&params, requestContext);
224 }
225
226
227 // get object ----------------------------------------------------------------
228
229 void S3_get_object(const S3BucketContext *bucketContext, const char *key,
230                    const S3GetConditions *getConditions,
231                    uint64_t startByte, uint64_t byteCount,
232                    S3RequestContext *requestContext,
233                    const S3GetObjectHandler *handler, void *callbackData)
234 {
235     // Set up the RequestParams
236     RequestParams params =
237     {
238         HttpRequestTypeGET,                           // httpRequestType
239         { bucketContext->bucketName,                  // bucketName
240           bucketContext->protocol,                    // protocol
241           bucketContext->uriStyle,                    // uriStyle
242           bucketContext->accessKeyId,                 // accessKeyId
243           bucketContext->secretAccessKey },           // secretAccessKey
244         key,                                          // key
245         0,                                            // queryParams
246         0,                                            // subResource
247         0,                                            // copySourceBucketName
248         0,                                            // copySourceKey
249         getConditions,                                // getConditions
250         startByte,                                    // startByte
251         byteCount,                                    // byteCount
252         0,                                            // putProperties
253         handler->responseHandler.propertiesCallback,  // propertiesCallback
254         0,                                            // toS3Callback
255         0,                                            // toS3CallbackTotalSize
256         handler->getObjectDataCallback,               // fromS3Callback
257         handler->responseHandler.completeCallback,    // completeCallback
258         callbackData                                  // callbackData
259     };
260
261     // Perform the request
262     request_perform(&params, requestContext);
263 }
264
265
266 // head object ---------------------------------------------------------------
267
268 void S3_head_object(const S3BucketContext *bucketContext, const char *key,
269                     S3RequestContext *requestContext,
270                     const S3ResponseHandler *handler, void *callbackData)
271 {
272     // Set up the RequestParams
273     RequestParams params =
274     {
275         HttpRequestTypeHEAD,                          // httpRequestType
276         { bucketContext->bucketName,                  // bucketName
277           bucketContext->protocol,                    // protocol
278           bucketContext->uriStyle,                    // uriStyle
279           bucketContext->accessKeyId,                 // accessKeyId
280           bucketContext->secretAccessKey },           // secretAccessKey
281         key,                                          // key
282         0,                                            // queryParams
283         0,                                            // subResource
284         0,                                            // copySourceBucketName
285         0,                                            // copySourceKey
286         0,                                            // getConditions
287         0,                                            // startByte
288         0,                                            // byteCount
289         0,                                            // putProperties
290         handler->propertiesCallback,                  // propertiesCallback
291         0,                                            // toS3Callback
292         0,                                            // toS3CallbackTotalSize
293         0,                                            // fromS3Callback
294         handler->completeCallback,                    // completeCallback
295         callbackData                                  // callbackData
296     };
297
298     // Perform the request
299     request_perform(&params, requestContext);
300 }
301                          
302
303 // delete object --------------------------------------------------------------
304
305 void S3_delete_object(const S3BucketContext *bucketContext, const char *key,
306                       S3RequestContext *requestContext,
307                       const S3ResponseHandler *handler, void *callbackData)
308 {
309     // Set up the RequestParams
310     RequestParams params =
311     {
312         HttpRequestTypeDELETE,                        // httpRequestType
313         { bucketContext->bucketName,                  // bucketName
314           bucketContext->protocol,                    // protocol
315           bucketContext->uriStyle,                    // uriStyle
316           bucketContext->accessKeyId,                 // accessKeyId
317           bucketContext->secretAccessKey },           // secretAccessKey
318         key,                                          // key
319         0,                                            // queryParams
320         0,                                            // subResource
321         0,                                            // copySourceBucketName
322         0,                                            // copySourceKey
323         0,                                            // getConditions
324         0,                                            // startByte
325         0,                                            // byteCount
326         0,                                            // putProperties
327         handler->propertiesCallback,                  // propertiesCallback
328         0,                                            // toS3Callback
329         0,                                            // toS3CallbackTotalSize
330         0,                                            // fromS3Callback
331         handler->completeCallback,                    // completeCallback
332         callbackData                                  // callbackData
333     };
334
335     // Perform the request
336     request_perform(&params, requestContext);
337 }