Imported Upstream version 3.3.3
[debian/amanda] / device-src / s3.h
1 /*
2  * Copyright (c) 2008-2012 Zmanda, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  *
18  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
20  */
21
22 #ifndef __S3_H__
23 #define __S3_H__
24 #include <glib.h>
25 #include <curl/curl.h>
26
27 /*
28  * Data types
29  */
30
31 typedef enum {
32    S3_API_S3,
33    S3_API_SWIFT_1,
34    S3_API_SWIFT_2,
35    S3_API_OAUTH2,
36    S3_API_CASTOR
37 } S3_api;
38
39 /* An opaque handle.  S3Handles should only be accessed from a single
40  * thread at any given time, although it is fine to use different handles
41  * in different threads simultaneously. */
42 typedef struct S3Handle S3Handle;
43
44 /* Callback function to read data to upload
45  * 
46  * @note this is the same as CURLOPT_READFUNCTION
47  *
48  * @param data: The pointer to write data to
49  * @param size: The size of each "element" of the data buffer in bytes
50  * @param nmemb: The number of elements in the data buffer.
51  * So, the buffer's size is size*nmemb bytes.
52  * @param stream: The read_data (an opaque pointer)
53  *
54  * @return The number of bytes written to the buffer,
55  * CURL_READFUNC_PAUSE to pause, or CURL_READFUNC_ABORT to abort.
56  * Return 0 only if there's no more data to be uploaded.
57  */
58 typedef size_t (*s3_read_func)(void *data, size_t size, size_t nmemb, void *stream);
59
60 /* This function is called to get size of the upload data
61  *
62  * @param data: The write_data (opaque pointer)
63  *
64  * @return The number of bytes of data, negative for error
65  */
66 typedef size_t (*s3_size_func)(void *data);
67
68 /* This function is called to get MD5 hash of the upload data
69  *
70  * @param data: The write_data (opaque pointer)
71  *
72  * @return The MD5 hash, NULL on error
73  */
74 typedef GByteArray* (*s3_md5_func)(void *data);
75
76 /* This function is called to reset an upload or download data stream
77  * to the beginning
78  *
79  * @param data: The read_data or write_data (opaque pointer)
80  *
81  * @return The number of bytes of data, negative for error
82  */
83 typedef void (*s3_reset_func)(void *data);
84
85 /* Callback function to write data that's been downloaded
86  * 
87  * @note this is the same as CURLOPT_WRITEFUNCTION
88  *
89  * @param data: The pointer to read data from
90  * @param size: The size of each "element" of the data buffer in bytes
91  * @param nmemb: The number of elements in the data buffer.
92  * So, the buffer's size is size*nmemb bytes.
93  * @param stream: the write_data (an opaque pointer)
94  *
95  * @return The number of bytes written to the buffer or
96  * CURL_WRITEFUNC_PAUSE to pause.
97  * If it's the number of bytes written, it should match the buffer size
98  */
99 typedef size_t (*s3_write_func)(void *data, size_t size, size_t nmemb, void *stream);
100
101 /**
102  * Callback function to track progress
103  *
104  * @note this is the same as CURLOPT_PROGRESSFUNCTION
105  *
106  * @param data: The progress_data
107  * @param dltotal: The total number of bytes to downloaded
108  * @param dlnow: The current number of bytes downloaded
109  * @param ultotal: The total number of bytes to downloaded
110  * @param ulnow: The current number of bytes downloaded
111  *
112  * @return 0 to continue, non-zero to abort.
113  */
114 typedef curl_progress_callback s3_progress_func;
115
116 /*
117  * Constants
118  */
119
120 /* These are assumed to be already URL-escaped. */
121 # define STS_BASE_URL "https://ls.amazonaws.com/"
122 # define STS_PRODUCT_TOKEN "{ProductToken}AAAGQXBwVGtu4geoGybuwuk8VEEPzJ9ZANpu0yzbf9g4Gs5Iarzff9B7qaDBEEaWcAzWpcN7zmdMO765jOtEFc4DWTRNkpPSzUnTdkHbdYUamath73OreaZtB86jy/JF0gsHZfhxeKc/3aLr8HNT//DsX3r272zYHLDPWWUbFguOwqNjllnt6BshYREx59l8RrWABLSa37dyJeN+faGvz3uQxiDakZRn3LfInOE6d9+fTFl50LPoP08LCqI/SJfpouzWix7D/cep3Jq8yYNyM1rgAOTF7/wh7r8OuPDLJ/xZUDLfykePIAM="
123
124 /* This preprocessor magic will enumerate constants named S3_ERROR_XxxYyy for
125  * each of the errors in parentheses.
126  *
127  * see http://docs.amazonwebservices.com/AmazonS3/latest/API/ErrorResponses.html
128  * for Amazon's breakdown of error responses.
129  */
130 #define S3_ERROR_LIST \
131     S3_ERROR(None), \
132     S3_ERROR(AccountProblem), \
133     S3_ERROR(AllAccessDisabled), \
134     S3_ERROR(AmbiguousGrantByEmailAddress), \
135     S3_ERROR(OperationAborted), \
136     S3_ERROR(BadDigest), \
137     S3_ERROR(BucketAlreadyExists), \
138     S3_ERROR(BucketAlreadyOwnedByYou), \
139     S3_ERROR(BucketNotEmpty), \
140     S3_ERROR(CredentialsNotSupported), \
141     S3_ERROR(EntityTooLarge), \
142     S3_ERROR(IncompleteBody), \
143     S3_ERROR(InternalError), \
144     S3_ERROR(InvalidAccessKeyId), \
145     S3_ERROR(InvalidArgument), \
146     S3_ERROR(InvalidBucketName), \
147     S3_ERROR(InvalidDigest), \
148     S3_ERROR(InvalidRange), \
149     S3_ERROR(InvalidSecurity), \
150     S3_ERROR(InvalidSOAPRequest), \
151     S3_ERROR(InvalidStorageClass), \
152     S3_ERROR(InvalidTargetBucketForLogging), \
153     S3_ERROR(KeyTooLong), \
154     S3_ERROR(InvalidURI), \
155     S3_ERROR(MalformedACLError), \
156     S3_ERROR(MaxMessageLengthExceeded), \
157     S3_ERROR(MetadataTooLarge), \
158     S3_ERROR(MethodNotAllowed), \
159     S3_ERROR(MissingAttachment), \
160     S3_ERROR(MissingContentLength), \
161     S3_ERROR(MissingSecurityElement), \
162     S3_ERROR(MissingSecurityHeader), \
163     S3_ERROR(NoLoggingStatusForKey), \
164     S3_ERROR(NoSuchBucket), \
165     S3_ERROR(NoSuchEntity), \
166     S3_ERROR(NoSuchKey), \
167     S3_ERROR(NotImplemented), \
168     S3_ERROR(NotSignedUp), \
169     S3_ERROR(PreconditionFailed), \
170     S3_ERROR(RequestTimeout), \
171     S3_ERROR(RequestTimeTooSkewed), \
172     S3_ERROR(RequestTorrentOfBucketError), \
173     S3_ERROR(SignatureDoesNotMatch), \
174     S3_ERROR(TooManyBuckets), \
175     S3_ERROR(UnexpectedContent), \
176     S3_ERROR(UnresolvableGrantByEmailAddress), \
177     S3_ERROR(Unknown), \
178     S3_ERROR(Unauthorized), \
179     S3_ERROR(Created), \
180     S3_ERROR(Accepted), \
181     S3_ERROR(Forbidden), \
182     S3_ERROR(Conflict), \
183     S3_ERROR(AuthenticationRequired), \
184     S3_ERROR(END)
185
186 typedef enum {
187 #define S3_ERROR(NAME) S3_ERROR_ ## NAME
188     S3_ERROR_LIST
189 #undef S3_ERROR
190 } s3_error_code_t;
191
192 /*
193  * Functions
194  */
195
196 /* Does this install of curl support SSL?
197  *
198  * @returns: boolean
199  */
200 gboolean
201 s3_curl_supports_ssl(void);
202
203 /* Checks if the version of libcurl being used supports and checks
204  * wildcard certificates correctly (used for the subdomains required
205  * by location constraints).
206  *
207  * @returns: true if the version of libcurl is new enough
208  */
209 gboolean
210 s3_curl_location_compat(void);
211
212 /* Checks if a bucket name is compatible with setting a location
213  * constraint.
214  *
215  * @note This doesn't guarantee that bucket name is entirely valid,
216  * just that using it as one (or more) subdomain(s) of s3.amazonaws.com
217  * won't fail; that would prevent the reporting of useful messages from
218  * the service.
219  *
220  * @param bucket: the bucket name
221  * @returns: true if the bucket name is compatible
222  */
223 gboolean
224 s3_bucket_location_compat(const char *bucket);
225
226 /* Initialize S3 operation
227  *
228  * If an error occurs in this function, diagnostic information is
229  * printed to stderr.
230  *
231  * @returns: false if an error occurred
232  */
233 gboolean
234 s3_init(void);
235
236 /* Set up an S3Handle.
237  *
238  * The concept of a bucket is defined by the Amazon S3 API.
239  * See: "Components of Amazon S3" - API Version 2006-03-01 pg. 8
240  *
241  * @param access_key: the secret key for Amazon Web Services
242  * @param secret_key: the secret key for Amazon Web Services
243  * @param user_token: the user token for Amazon DevPay
244  * @param bucket_location: the location constraint for buckets
245  * @param storage_class: the storage class for new objects
246  * @param ca_info: the path to pass to libcurl as the certificate authority.
247  *                 see curl_easy_setopt() CURLOPT_CAINFO for more
248  * @returns: the new S3Handle
249  */
250 S3Handle *
251 s3_open(const char * access_key, const char *secret_key,
252         const char *swift_account_id, const char *swift_access_key,
253         const char *host,
254         const char *service_path, gboolean use_subdomain,
255         const char * user_token,
256         const char * bucket_location, const char * storage_class,
257         const char * ca_info, const char * server_side_encryption,
258         const char *proxy,
259         const S3_api s3_api,
260         const char *username,
261         const char *password,
262         const char *tenant_id,
263         const char *tenant_name,
264         const char *client_id,
265         const char *client_secret,
266         const char *refresh_token,
267         const gboolean reuse_connection,
268         const char *reps,
269         const char *reps_bucket);
270
271 /* latest step of setting up the S3Handle.
272  *
273  * Must be done after all properties are set.
274  *
275  * @param hdl: the S3Handle to set up.
276  * @returns: false if an error occured
277  */
278 gboolean
279 s3_open2(S3Handle *hdl);
280
281 /* Deallocate an S3Handle
282  *
283  * @param hdl: the S3Handle object
284  */
285 void
286 s3_free(S3Handle *hdl);
287
288 /* Reset the information about the last request, including
289  * freeing any allocated memory.  The S3Handle itself is not
290  * freed and may be used again.  This function is called
291  * automatically as needed, and should be called to free memory
292  * when the handle will not be used for some time.
293  *
294  * @param hdl: the S3Handle object
295  */
296 void
297 s3_reset(S3Handle *hdl);
298
299 /* Get the error information for the last operation
300  *
301  * All results are returned via result parameters.  If any parameter is
302  * NULL, that result will not be returned.  Caller is not responsible for
303  * freeing any returned strings, although the results are only valid until
304  * the next call to an S3 function with this handle.
305  *
306  * @param hdl: the S3Handle object
307  * @param message: (result) the error message, or NULL if none exists
308  * @param response_code: (result) the HTTP response code (or 0 if none exists)
309  * @param s3_error_code: (result) the S3 error code (see constants, above)
310  * @param s3_error_name: (result) the S3 error name (e.g., "RequestTimeout"),
311  * or NULL if none exists
312  * @param curl_code: (result) the curl error code (or 0 if none exists)
313  * @param num_retries: (result) number of retries
314  */
315 void
316 s3_error(S3Handle *hdl,
317          const char **message,
318          guint *response_code,
319          s3_error_code_t *s3_error_code,
320          const char **s3_error_name,
321          CURLcode *curl_code,
322          guint *num_retries);
323
324 /* Control verbose output of HTTP transactions, etc.
325  *
326  * @param hdl: the S3Handle object
327  * @param verbose: if true, send HTTP transactions, etc. to debug output
328  */
329 void
330 s3_verbose(S3Handle *hdl,
331        gboolean verbose);
332
333 /* Control the use of SSL with HTTP transactions.
334  *
335  * @param hdl: the S3Handle object
336  * @param use_ssl: if true, use SSL (if curl supports it)
337  * @returns: true if the setting is valid
338  */
339 gboolean
340 s3_use_ssl(S3Handle *hdl, gboolean use_ssl);
341
342 /* Control the throttling of S3 uploads.  Only supported with curl >= 7.15.5.
343  *
344  * @param hdl: the S3Handle object
345  * @param max_send_speed: max speed (bytes/sec) at which to send
346  * @returns: true if the setting is valid
347  */
348 gboolean
349 s3_set_max_send_speed(S3Handle *hdl, guint64 max_send_speed);
350
351 /* Control the throttling of S3 downloads.  Only supported with curl >= 7.15.5.
352  *
353  * @param hdl: the S3Handle object
354  * @param max_recv_speed: max speed (bytes/sec) at which to receive
355  * @returns: true if the setting is valid
356  */
357 gboolean
358 s3_set_max_recv_speed(S3Handle *hdl, guint64 max_recv_speed);
359
360 /* Get the error information from the last operation on this handle,
361  * formatted as a string.
362  *
363  * Caller is responsible for freeing the resulting string.
364  *
365  * @param hdl: the S3Handle object
366  * @returns: string, or NULL if no error occurred
367  */
368 char *
369 s3_strerror(S3Handle *hdl);
370
371 /* Perform an upload.
372  *
373  * When this function returns, KEY and BUFFER remain the
374  * responsibility of the caller.
375  *
376  * @param hdl: the S3Handle object
377  * @param bucket: the bucket to which the upload should be made
378  * @param key: the key to which the upload should be made
379  * @param read_func: the callback for reading data
380  * @param reset_func: the callback for to reset reading data
381  * @param size_func: the callback to get the number of bytes to upload
382  * @param md5_func: the callback to get the MD5 hash of the data to upload
383  * @param read_data: pointer to pass to the above functions
384  * @param progress_func: the callback for progress information
385  * @param progress_data: pointer to pass to C{progress_func}
386  *
387  * @returns: false if an error ocurred
388  */
389 gboolean
390 s3_upload(S3Handle *hdl,
391           const char *bucket,
392           const char *key, 
393           s3_read_func read_func,
394           s3_reset_func reset_func,
395           s3_size_func size_func,
396           s3_md5_func md5_func,
397           gpointer read_data,
398           s3_progress_func progress_func,
399           gpointer progress_data);
400
401 /* List all of the files matching the pseudo-glob C{PREFIX*DELIMITER*},
402  * returning only that portion which matches C{PREFIX*DELIMITER}.  S3 supports
403  * this particular semantics, making it quite efficient.  The returned list
404  * should be freed by the caller.
405  *
406  * @param hdl: the S3Handle object
407  * @param bucket: the bucket to list
408  * @param prefix: the prefix
409  * @param delimiter: delimiter (any length string)
410  * @param list: (output) the list of files
411  * @param total_size: (output) sum of size of files 
412  * @returns: FALSE if an error occurs
413  */
414 gboolean
415 s3_list_keys(S3Handle *hdl,
416               const char *bucket,
417               const char *prefix,
418               const char *delimiter,
419               GSList **list,
420               guint64 *total_size);
421
422 /* Read an entire file, passing the contents to write_func buffer
423  * by buffer.
424  *
425  * @param hdl: the S3Handle object
426  * @param bucket: the bucket to read from
427  * @param key: the key to read from
428  * @param write_func: the callback for writing data
429  * @param reset_func: the callback for to reset writing data
430  * @param write_data: pointer to pass to C{write_func}
431  * @param progress_func: the callback for progress information
432  * @param progress_data: pointer to pass to C{progress_func}
433  * @returns: FALSE if an error occurs
434  */
435 gboolean
436 s3_read(S3Handle *hdl,
437         const char *bucket,
438         const char *key,
439         s3_write_func write_func,
440         s3_reset_func reset_func,
441         gpointer write_data,
442         s3_progress_func progress_func,
443         gpointer progress_data);
444
445 /* Delete a file.
446  *
447  * @param hdl: the S3Handle object
448  * @param bucket: the bucket to delete from
449  * @param key: the key to delete
450  * @returns: FALSE if an error occurs; a non-existent file is I{not} considered an error.
451  */
452 gboolean
453 s3_delete(S3Handle *hdl,
454           const char *bucket,
455           const char *key);
456
457 /* Delete multiple file.
458  *
459  * @param hdl: the S3Handle object
460  * @param bucket: the bucket to delete from
461  * @param key: the key array to delete
462  * @returns: 0 on sucess, 1 if multi_delete is not supported, 2 if an error
463  *           occurs; a non-existent file is I{not} considered an error.
464  */
465 int
466 s3_multi_delete(S3Handle *hdl,
467                 const char *bucket,
468                 const char **key);
469
470 /* Create a bucket.
471  *
472  * @param hdl: the S3Handle object
473  * @param bucket: the bucket to create
474  * @returns: FALSE if an error occurs
475  */
476 gboolean
477 s3_make_bucket(S3Handle *hdl,
478                const char *bucket,
479                const char *project_id);
480
481 /* Check if a bucket exists.
482  *
483  * @param hdl: the S3Handle object
484  * @param bucket: the bucket to create
485  * @returns: FALSE if an error occur
486  */
487 gboolean
488 s3_is_bucket_exists(S3Handle *hdl,
489                     const char *bucket,
490                     const char *project_id);
491
492 /* Delete a bucket
493  *
494  * @note A bucket can not be deleted if it still contains keys
495  *
496  * @param hdl: the S3Handle object
497  * @param bucket: the bucket to delete
498  * @returns: FALSE if an error occurs
499  */
500 gboolean
501 s3_delete_bucket(S3Handle *hdl,
502                  const char *bucket);
503
504 /* Attempt a RefreshAWSSecurityToken on a token; if it succeeds, the old
505  * token will be freed and replaced by the new. If it fails, the old
506  * token is left unchanged and FALSE is returned. */
507 gboolean sts_refresh_token(char ** token, const char * directory);
508
509 /* These functions are for if you want to use curl on your own. You get more
510  * control, but it's a lot of work that way: */
511 typedef struct {
512     char *buffer;
513     guint buffer_len;
514     guint buffer_pos;
515     guint max_buffer_size;
516 } CurlBuffer;
517
518 #define S3_BUFFER_READ_FUNCS s3_buffer_read_func, s3_buffer_reset_func, s3_buffer_size_func, s3_buffer_md5_func
519
520 #define S3_BUFFER_WRITE_FUNCS s3_buffer_write_func, s3_buffer_reset_func
521
522 /* a CURLOPT_READFUNCTION to read data from a buffer. */
523 size_t
524 s3_buffer_read_func(void *ptr, size_t size, size_t nmemb, void * stream);
525
526 size_t
527 s3_buffer_size_func(void *stream);
528
529 GByteArray*
530 s3_buffer_md5_func(void *stream);
531
532 void
533 s3_buffer_reset_func(void *stream);
534
535 #define S3_EMPTY_READ_FUNCS s3_empty_read_func, NULL, s3_empty_size_func, s3_empty_md5_func
536
537 /* a CURLOPT_WRITEFUNCTION to write data to a buffer. */
538 size_t
539 s3_buffer_write_func(void *ptr, size_t size, size_t nmemb, void *stream);
540
541 /* a CURLOPT_READFUNCTION that writes nothing. */
542 size_t
543 s3_empty_read_func(void *ptr, size_t size, size_t nmemb, void * stream);
544
545 size_t
546 s3_empty_size_func(void *stream);
547
548 GByteArray*
549 s3_empty_md5_func(void *stream);
550
551 #define S3_COUNTER_WRITE_FUNCS s3_counter_write_func, s3_counter_reset_func
552
553 /* a CURLOPT_WRITEFUNCTION to write data that just counts data.
554  * s3_write_data should be NULL or a pointer to an gint64.
555  */
556 size_t
557 s3_counter_write_func(void *ptr, size_t size, size_t nmemb, void *stream);
558
559 void
560 s3_counter_reset_func(void *stream);
561
562 #ifdef _WIN32
563 /* a CURLOPT_READFUNCTION to read data from a file. */
564 size_t
565 s3_file_read_func(void *ptr, size_t size, size_t nmemb, void * stream);
566
567 size_t
568 s3_file_size_func(void *stream);
569
570 GByteArray*
571 s3_file_md5_func(void *stream);
572
573 size_t
574 s3_file_reset_func(void *stream);
575
576 /* a CURLOPT_WRITEFUNCTION to write data to a file. */
577 size_t
578 s3_file_write_func(void *ptr, size_t size, size_t nmemb, void *stream);
579 #endif
580
581 /* Adds a null termination to a buffer. */
582 void terminate_buffer(CurlBuffer *);
583
584 #endif