086b6f0bb34615e9cd07c9c36a16600c8a59da54
[debian/amanda] / device-src / s3.h
1 /*
2  * Copyright (c) 2005 Zmanda, Inc.  All Rights Reserved.
3  * 
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 2.1 as 
6  * published by the Free Software Foundation.
7  * 
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
11  * License for more details.
12  * 
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation,
15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
16  * 
17  * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120
18  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19  */
20
21 #ifndef __S3_H__
22 #define __S3_H__
23 #include <glib.h>
24 #include <curl/curl.h>
25
26 /*
27  * Data types
28  */
29
30 /* An opaque handle.  S3Handles should only be accessed from a single
31  * thread at any given time, although it is fine to use different handles
32  * in different threads simultaneously. */
33 typedef struct S3Handle S3Handle;
34
35 /*
36  * Constants
37  */
38
39 #ifdef WANT_DEVPAY
40 /* These are assumed to be already URL-escaped. */
41 # define STS_BASE_URL "https://sts.amazonaws.com/"
42 # define STS_PRODUCT_TOKEN "{ProductToken}AAAGQXBwVGtu4geoGybuwuk8VEEPzJ9ZANpu0yzbf9g4Gs5Iarzff9B7qaDBEEaWcAzWpcN7zmdMO765jOtEFc4DWTRNkpPSzUnTdkHbdYUamath73OreaZtB86jy/JF0gsHZfhxeKc/3aLr8HNT//DsX3r272zYHLDPWWUbFguOwqNjllnt6BshYREx59l8RrWABLSa37dyJeN+faGvz3uQxiDakZRn3LfInOE6d9+fTFl50LPoP08LCqI/SJfpouzWix7D/cep3Jq8yYNyM1rgAOTF7/wh7r8OuPDLJ/xZUDLfykePIAM="
43 #endif
44
45 /* This preprocessor magic will enumerate constants named S3_ERROR_XxxYyy for
46  * each of the errors in parentheses.
47  *
48  * see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorCodeList.html
49  * for Amazon's breakdown of error responses.
50  */
51 #define S3_ERROR_LIST \
52     S3_ERROR(None), \
53     S3_ERROR(AccountProblem), \
54     S3_ERROR(AllAccessDisabled), \
55     S3_ERROR(AmbiguousGrantByEmailAddress), \
56     S3_ERROR(OperationAborted), \
57     S3_ERROR(BadDigest), \
58     S3_ERROR(BucketAlreadyExists), \
59     S3_ERROR(BucketNotEmpty), \
60     S3_ERROR(CredentialsNotSupported), \
61     S3_ERROR(EntityTooLarge), \
62     S3_ERROR(IncompleteBody), \
63     S3_ERROR(InternalError), \
64     S3_ERROR(InvalidAccessKeyId), \
65     S3_ERROR(InvalidArgument), \
66     S3_ERROR(InvalidBucketName), \
67     S3_ERROR(InvalidDigest), \
68     S3_ERROR(InvalidRange), \
69     S3_ERROR(InvalidSecurity), \
70     S3_ERROR(InvalidSOAPRequest), \
71     S3_ERROR(InvalidStorageClass), \
72     S3_ERROR(InvalidTargetBucketForLogging), \
73     S3_ERROR(KeyTooLong), \
74     S3_ERROR(InvalidURI), \
75     S3_ERROR(MalformedACLError), \
76     S3_ERROR(MaxMessageLengthExceeded), \
77     S3_ERROR(MetadataTooLarge), \
78     S3_ERROR(MethodNotAllowed), \
79     S3_ERROR(MissingAttachment), \
80     S3_ERROR(MissingContentLength), \
81     S3_ERROR(MissingSecurityElement), \
82     S3_ERROR(MissingSecurityHeader), \
83     S3_ERROR(NoLoggingStatusForKey), \
84     S3_ERROR(NoSuchBucket), \
85     S3_ERROR(NoSuchKey), \
86     S3_ERROR(NotImplemented), \
87     S3_ERROR(NotSignedUp), \
88     S3_ERROR(PreconditionFailed), \
89     S3_ERROR(RequestTimeout), \
90     S3_ERROR(RequestTimeTooSkewed), \
91     S3_ERROR(RequestTorrentOfBucketError), \
92     S3_ERROR(SignatureDoesNotMatch), \
93     S3_ERROR(TooManyBuckets), \
94     S3_ERROR(UnexpectedContent), \
95     S3_ERROR(UnresolvableGrantByEmailAddress), \
96     S3_ERROR(Unknown), \
97     S3_ERROR(END)
98
99 typedef enum {
100 #define S3_ERROR(NAME) S3_ERROR_ ## NAME
101     S3_ERROR_LIST
102 #undef S3_ERROR
103 } s3_error_code_t;
104
105 /*
106  * Functions
107  */
108
109 /* Initialize S3 operation
110  *
111  * As a requirement of C{curl_global_init}, which this function calls,
112  * s3_init I{must} be called before any other threads are started.
113  *
114  * If an error occurs in this function, diagnostic information is 
115  * printed to stderr.
116  *
117  * @returns: false if an error occurred
118  */
119 gboolean
120 s3_init(void);
121
122 /* Set up an S3Handle.
123  */
124 S3Handle *
125 s3_open(const char * access_key, const char *secret_key
126 #ifdef WANT_DEVPAY
127         , const char * user_token
128 #endif
129         );
130
131 /* Deallocate an S3Handle
132  *
133  * @param hdl: the S3Handle object
134  */
135 void
136 s3_free(S3Handle *hdl);
137
138 /* Reset the information about the last request, including
139  * freeing any allocated memory.  The S3Handle itself is not
140  * freed and may be used again.  This function is called
141  * automatically as needed, and should be called to free memory
142  * when the handle will not be used for some time.
143  *
144  * @param hdl: the S3Handle object
145  */
146 void
147 s3_reset(S3Handle *hdl);
148
149 /* Get the error information for the last operation
150  *
151  * All results are returned via result parameters.  If any parameter is
152  * NULL, that result will not be returned.  Caller is not responsible for
153  * freeing any returned strings, although the results are only valid until
154  * the next call to an S3 function with this handle.
155  * 
156  * @param hdl: the S3Handle object
157  * @param message: (result) the error message, or NULL if none exists
158  * @param response_code: (result) the HTTP response code (or 0 if none exists)
159  * @param s3_error_code: (result) the S3 error code (see constants, above)
160  * @param s3_error_name: (result) the S3 error name (e.g., "RequestTimeout"),
161  * or NULL if none exists
162  * @param curl_code: (result) the curl error code (or 0 if none exists)
163  * @param num_retries: (result) number of retries
164  */
165 void
166 s3_error(S3Handle *hdl,
167          const char **message,
168          guint *response_code,
169          s3_error_code_t *s3_error_code,
170          const char **s3_error_name,
171          CURLcode *curl_code,
172          guint *num_retries);
173
174 /* Control verbose output of HTTP transactions, etc.
175  *
176  * @param hdl: the S3Handle object
177  * @param verbose: if true, send HTTP transactions, etc. to debug output
178  */
179 void
180 s3_verbose(S3Handle *hdl,
181            gboolean verbose);
182
183 /* Get the error information from the last operation on this handle,
184  * formatted as a string.
185  *
186  * Caller is responsible for freeing the resulting string.
187  *
188  * @param hdl: the S3Handle object
189  * @returns: string, or NULL if no error occurred
190  */
191 char *
192 s3_strerror(S3Handle *hdl);
193
194 /* Perform an upload.
195  * 
196  * When this function returns, KEY and BUFFER remain the
197  * responsibility of the caller.
198  *
199  * @param hdl: the S3Handle object
200  * @param bucket: the bucket to which the upload should be made
201  * @param key: the key to which the upload should be made
202  * @param buffer: the data to be uploaded
203  * @param buffer_len: the length of the data to upload
204  * @returns: false if an error ocurred
205  */
206 gboolean
207 s3_upload(S3Handle *hdl,
208           const char *bucket,
209           const char *key, 
210           gpointer buffer,
211           guint buffer_len);
212
213 /* List all of the files matching the pseudo-glob C{PREFIX*DELIMITER*}, 
214  * returning only that portion which matches C{PREFIX*DELIMITER}.  S3 supports
215  * this particular semantics, making it quite efficient.  The returned list
216  * should be freed by the caller.
217  *
218  * @param hdl: the S3Handle object
219  * @param bucket: the bucket to list
220  * @param prefix: the prefix
221  * @param delimiter: delimiter (any length string)
222  * @param list: (output) the list of files
223  * @returns: FALSE if an error occurs
224  */
225 gboolean
226 s3_list_keys(S3Handle *hdl,
227               const char *bucket,
228               const char *prefix,
229               const char *delimiter,
230               GSList **list);
231
232 /* Read an entire file.  The buffer returned is the responsibility of the caller.  A
233  * buffer is only returned if no error occurred, and will be NULL otherwise.
234  *
235  * @param hdl: the S3Handle object
236  * @param bucket: the bucket to read from
237  * @param key: the key to read from
238  * @param buf_ptr: (result) a pointer to a C{gpointer} which will contain a pointer to
239  * the block read
240  * @param buf_size: (result) a pointer to a C{guint} which will contain the size of the
241  * block read
242  * @param max_size: maximum size of the file
243  * @returns: FALSE if an error occurs
244  */
245 gboolean
246 s3_read(S3Handle *hdl,
247         const char *bucket,
248         const char *key,
249         gpointer *buf_ptr,
250         guint *buf_size,
251         guint max_size);
252
253 /* Delete a file.
254  *
255  * @param hdl: the S3Handle object
256  * @param bucket: the bucket to delete from
257  * @param key: the key to delete
258  * @returns: FALSE if an error occurs; a non-existent file is I{not} considered an error.
259  */
260 gboolean
261 s3_delete(S3Handle *hdl,
262           const char *bucket,
263           const char *key);
264
265 /* Create a bucket.
266  *
267  * @param hdl: the S3Handle object
268  * @param bucket: the bucket to create
269  * @returns: FALSE if an error occurs
270  */
271 gboolean
272 s3_make_bucket(S3Handle *hdl,
273                const char *bucket);
274
275 /* Attempt a RefreshAWSSecurityToken on a token; if it succeeds, the old
276  * token will be freed and replaced by the new. If it fails, the old
277  * token is left unchanged and FALSE is returned. */
278 gboolean sts_refresh_token(char ** token, const char * directory);
279
280 /* These functions are for if you want to use curl on your own. You get more
281  * control, but it's a lot of work that way: */
282 typedef struct {
283     char *buffer;
284     guint buffer_len;
285     guint buffer_pos;
286     guint max_buffer_size;
287 } CurlBuffer;
288
289 /* a CURLOPT_READFUNCTION to read data from a buffer. */
290 size_t buffer_readfunction(void *ptr, size_t size,
291                            size_t nmemb, void * stream);
292
293 /* a CURLOPT_WRITEFUNCTION to write data to a buffer. */
294 size_t
295 buffer_writefunction(void *ptr, size_t size, size_t nmemb, void *stream);
296
297 /* Adds a null termination to a buffer. */
298 void terminate_buffer(CurlBuffer *);
299
300 #endif