2 * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved.
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.
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.
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.
17 * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120
18 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
24 #include <curl/curl.h>
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;
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="
45 /* This preprocessor magic will enumerate constants named S3_ERROR_XxxYyy for
46 * each of the errors in parentheses.
48 * see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorCodeList.html
49 * for Amazon's breakdown of error responses.
51 #define S3_ERROR_LIST \
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), \
100 #define S3_ERROR(NAME) S3_ERROR_ ## NAME
109 /* Initialize S3 operation
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.
114 * If an error occurs in this function, diagnostic information is
117 * @returns: false if an error occurred
122 /* Set up an S3Handle.
125 s3_open(const char * access_key, const char *secret_key
127 , const char * user_token
131 /* Deallocate an S3Handle
133 * @param hdl: the S3Handle object
136 s3_free(S3Handle *hdl);
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.
144 * @param hdl: the S3Handle object
147 s3_reset(S3Handle *hdl);
149 /* Get the error information for the last operation
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.
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
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,
174 /* Control verbose output of HTTP transactions, etc.
176 * @param hdl: the S3Handle object
177 * @param verbose: if true, send HTTP transactions, etc. to debug output
180 s3_verbose(S3Handle *hdl,
183 /* Get the error information from the last operation on this handle,
184 * formatted as a string.
186 * Caller is responsible for freeing the resulting string.
188 * @param hdl: the S3Handle object
189 * @returns: string, or NULL if no error occurred
192 s3_strerror(S3Handle *hdl);
194 /* Perform an upload.
196 * When this function returns, KEY and BUFFER remain the
197 * responsibility of the caller.
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
207 s3_upload(S3Handle *hdl,
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.
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
226 s3_list_keys(S3Handle *hdl,
229 const char *delimiter,
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.
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
240 * @param buf_size: (result) a pointer to a C{guint} which will contain the size of the
242 * @param max_size: maximum size of the file
243 * @returns: FALSE if an error occurs
246 s3_read(S3Handle *hdl,
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.
261 s3_delete(S3Handle *hdl,
267 * @param hdl: the S3Handle object
268 * @param bucket: the bucket to create
269 * @returns: FALSE if an error occurs
272 s3_make_bucket(S3Handle *hdl,
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);
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: */
286 guint max_buffer_size;
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);
293 /* a CURLOPT_WRITEFUNCTION to write data to a buffer. */
295 buffer_writefunction(void *ptr, size_t size, size_t nmemb, void *stream);
297 /* Adds a null termination to a buffer. */
298 void terminate_buffer(CurlBuffer *);