diff options
Diffstat (limited to 'src/s3.c')
-rw-r--r-- | src/s3.c | 4642 |
1 files changed, 2321 insertions, 2321 deletions
@@ -102,7 +102,7 @@ static char errorDetailsG[4096] = { 0 }; #define MD5_PREFIX_LEN (sizeof(MD5_PREFIX) - 1) #define CONTENT_DISPOSITION_FILENAME_PREFIX "contentDispositionFilename=" #define CONTENT_DISPOSITION_FILENAME_PREFIX_LEN \ - (sizeof(CONTENT_DISPOSITION_FILENAME_PREFIX) - 1) + (sizeof(CONTENT_DISPOSITION_FILENAME_PREFIX) - 1) #define CONTENT_ENCODING_PREFIX "contentEncoding=" #define CONTENT_ENCODING_PREFIX_LEN (sizeof(CONTENT_ENCODING_PREFIX) - 1) #define EXPIRES_PREFIX "expires=" @@ -113,7 +113,7 @@ static char errorDetailsG[4096] = { 0 }; #define IF_MODIFIED_SINCE_PREFIX_LEN (sizeof(IF_MODIFIED_SINCE_PREFIX) - 1) #define IF_NOT_MODIFIED_SINCE_PREFIX "ifNotmodifiedSince=" #define IF_NOT_MODIFIED_SINCE_PREFIX_LEN \ - (sizeof(IF_NOT_MODIFIED_SINCE_PREFIX) - 1) + (sizeof(IF_NOT_MODIFIED_SINCE_PREFIX) - 1) #define IF_MATCH_PREFIX "ifMatch=" #define IF_MATCH_PREFIX_LEN (sizeof(IF_MATCH_PREFIX) - 1) #define IF_NOT_MATCH_PREFIX "ifNotMatch=" @@ -138,176 +138,176 @@ static char errorDetailsG[4096] = { 0 }; static void S3_init() { - S3Status status; - if ((status = S3_initialize("s3", S3_INIT_ALL)) - != S3StatusOK) { - fprintf(stderr, "Failed to initialize libs3: %s\n", - S3_get_status_name(status)); - exit(-1); - } + S3Status status; + if ((status = S3_initialize("s3", S3_INIT_ALL)) + != S3StatusOK) { + fprintf(stderr, "Failed to initialize libs3: %s\n", + S3_get_status_name(status)); + exit(-1); + } } static void printError() { - if (statusG < S3StatusErrorAccessDenied) { - fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); - } - else { - fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); - fprintf(stderr, "%s\n", errorDetailsG); - } + if (statusG < S3StatusErrorAccessDenied) { + fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); + } + else { + fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); + fprintf(stderr, "%s\n", errorDetailsG); + } } static void usageExit(FILE *out) { - fprintf(out, + fprintf(out, "\n Options:\n" "\n" -" Command Line:\n" +" Command Line:\n" "\n" -" -f/--force : force operation despite warnings\n" -" -h/--vhost-style : use virtual-host-style URIs (default is " - "path-style)\n" -" -u/--unencrypted : unencrypted (use HTTP instead of HTTPS)\n" -" -s/--show-properties : show response properties on stdout\n" -" -r/--retries : retry retryable failures this number of times\n" -" (default is 5)\n" +" -f/--force : force operation despite warnings\n" +" -h/--vhost-style : use virtual-host-style URIs (default is " + "path-style)\n" +" -u/--unencrypted : unencrypted (use HTTP instead of HTTPS)\n" +" -s/--show-properties : show response properties on stdout\n" +" -r/--retries : retry retryable failures this number of times\n" +" (default is 5)\n" "\n" -" Environment:\n" +" Environment:\n" "\n" -" S3_ACCESS_KEY_ID : S3 access key ID (required)\n" -" S3_SECRET_ACCESS_KEY : S3 secret access key (required)\n" +" S3_ACCESS_KEY_ID : S3 access key ID (required)\n" +" S3_SECRET_ACCESS_KEY : S3 secret access key (required)\n" "\n" " Commands (with <required parameters> and [optional parameters]) :\n" "\n" -" (NOTE: all command parameters take a value and are specified using the\n" -" pattern parameter=value)\n" +" (NOTE: all command parameters take a value and are specified using the\n" +" pattern parameter=value)\n" "\n" -" help : Prints this help text\n" +" help : Prints this help text\n" "\n" -" list : Lists owned buckets\n" -" [allDetails] : Show full details\n" +" list : Lists owned buckets\n" +" [allDetails] : Show full details\n" "\n" -" test : Tests a bucket for existence and accessibility\n" -" <bucket> : Bucket to test\n" +" test : Tests a bucket for existence and accessibility\n" +" <bucket> : Bucket to test\n" "\n" -" create : Create a new bucket\n" -" <bucket> : Bucket to create\n" -" [cannedAcl] : Canned ACL for the bucket (see Canned ACLs)\n" -" [location] : Location for bucket (for example, EU)\n" +" create : Create a new bucket\n" +" <bucket> : Bucket to create\n" +" [cannedAcl] : Canned ACL for the bucket (see Canned ACLs)\n" +" [location] : Location for bucket (for example, EU)\n" "\n" -" delete : Delete a bucket or key\n" -" <bucket>[/<key>] : Bucket or bucket/key to delete\n" +" delete : Delete a bucket or key\n" +" <bucket>[/<key>] : Bucket or bucket/key to delete\n" "\n" -" list : List bucket contents\n" -" <bucket> : Bucket to list\n" -" [prefix] : Prefix for results set\n" -" [marker] : Where in results set to start listing\n" -" [delimiter] : Delimiter for rolling up results set\n" -" [maxkeys] : Maximum number of keys to return in results set\n" -" [allDetails] : Show full details for each key\n" +" list : List bucket contents\n" +" <bucket> : Bucket to list\n" +" [prefix] : Prefix for results set\n" +" [marker] : Where in results set to start listing\n" +" [delimiter] : Delimiter for rolling up results set\n" +" [maxkeys] : Maximum number of keys to return in results set\n" +" [allDetails] : Show full details for each key\n" "\n" -" getacl : Get the ACL of a bucket or key\n" -" <bucket>[/<key>] : Bucket or bucket/key to get the ACL of\n" -" [filename] : Output filename for ACL (default is stdout)\n" +" getacl : Get the ACL of a bucket or key\n" +" <bucket>[/<key>] : Bucket or bucket/key to get the ACL of\n" +" [filename] : Output filename for ACL (default is stdout)\n" "\n" -" setacl : Set the ACL of a bucket or key\n" -" <bucket>[/<key>] : Bucket or bucket/key to set the ACL of\n" -" [filename] : Input filename for ACL (default is stdin)\n" +" setacl : Set the ACL of a bucket or key\n" +" <bucket>[/<key>] : Bucket or bucket/key to set the ACL of\n" +" [filename] : Input filename for ACL (default is stdin)\n" "\n" -" getlogging : Get the logging status of a bucket\n" -" <bucket> : Bucket to get the logging status of\n" -" [filename] : Output filename for ACL (default is stdout)\n" +" getlogging : Get the logging status of a bucket\n" +" <bucket> : Bucket to get the logging status of\n" +" [filename] : Output filename for ACL (default is stdout)\n" "\n" -" setlogging : Set the logging status of a bucket\n" -" <bucket> : Bucket to set the logging status of\n" -" [targetBucket] : Target bucket to log to; if not present, disables\n" -" logging\n" -" [targetPrefix] : Key prefix to use for logs\n" -" [filename] : Input filename for ACL (default is stdin)\n" +" setlogging : Set the logging status of a bucket\n" +" <bucket> : Bucket to set the logging status of\n" +" [targetBucket] : Target bucket to log to; if not present, disables\n" +" logging\n" +" [targetPrefix] : Key prefix to use for logs\n" +" [filename] : Input filename for ACL (default is stdin)\n" "\n" -" put : Puts an object\n" -" <bucket>/<key> : Bucket/key to put object to\n" -" [filename] : Filename to read source data from " - "(default is stdin)\n" -" [contentLength] : How many bytes of source data to put (required if\n" -" source file is stdin)\n" -" [cacheControl] : Cache-Control HTTP header string to associate with\n" -" object\n" -" [contentType] : Content-Type HTTP header string to associate with\n" -" object\n" -" [md5] : MD5 for validating source data\n" -" [contentDispositionFilename] : Content-Disposition filename string to\n" -" associate with object\n" -" [contentEncoding] : Content-Encoding HTTP header string to associate\n" -" with object\n" -" [expires] : Expiration date to associate with object\n" -" [cannedAcl] : Canned ACL for the object (see Canned ACLs)\n" -" [x-amz-meta-...]] : Metadata headers to associate with the object\n" +" put : Puts an object\n" +" <bucket>/<key> : Bucket/key to put object to\n" +" [filename] : Filename to read source data from " + "(default is stdin)\n" +" [contentLength] : How many bytes of source data to put (required if\n" +" source file is stdin)\n" +" [cacheControl] : Cache-Control HTTP header string to associate with\n" +" object\n" +" [contentType] : Content-Type HTTP header string to associate with\n" +" object\n" +" [md5] : MD5 for validating source data\n" +" [contentDispositionFilename] : Content-Disposition filename string to\n" +" associate with object\n" +" [contentEncoding] : Content-Encoding HTTP header string to associate\n" +" with object\n" +" [expires] : Expiration date to associate with object\n" +" [cannedAcl] : Canned ACL for the object (see Canned ACLs)\n" +" [x-amz-meta-...]] : Metadata headers to associate with the object\n" "\n" -" copy : Copies an object; if any options are set, the " - "entire\n" -" metadata of the object is replaced\n" -" <sourcebucket>/<sourcekey> : Source bucket/key\n" -" <destbucket>/<destkey> : Destination bucket/key\n" -" [cacheControl] : Cache-Control HTTP header string to associate with\n" -" object\n" -" [contentType] : Content-Type HTTP header string to associate with\n" -" object\n" -" [contentDispositionFilename] : Content-Disposition filename string to\n" -" associate with object\n" -" [contentEncoding] : Content-Encoding HTTP header string to associate\n" -" with object\n" -" [expires] : Expiration date to associate with object\n" -" [cannedAcl] : Canned ACL for the object (see Canned ACLs)\n" -" [x-amz-meta-...]] : Metadata headers to associate with the object\n" +" copy : Copies an object; if any options are set, the " + "entire\n" +" metadata of the object is replaced\n" +" <sourcebucket>/<sourcekey> : Source bucket/key\n" +" <destbucket>/<destkey> : Destination bucket/key\n" +" [cacheControl] : Cache-Control HTTP header string to associate with\n" +" object\n" +" [contentType] : Content-Type HTTP header string to associate with\n" +" object\n" +" [contentDispositionFilename] : Content-Disposition filename string to\n" +" associate with object\n" +" [contentEncoding] : Content-Encoding HTTP header string to associate\n" +" with object\n" +" [expires] : Expiration date to associate with object\n" +" [cannedAcl] : Canned ACL for the object (see Canned ACLs)\n" +" [x-amz-meta-...]] : Metadata headers to associate with the object\n" "\n" -" get : Gets an object\n" -" <buckey>/<key> : Bucket/key of object to get\n" -" [filename] : Filename to write object data to (required if -s\n" -" command line parameter was used)\n" -" [ifModifiedSince] : Only return the object if it has been modified " - "since\n" -" this date\n" -" [ifNotmodifiedSince] : Only return the object if it has not been " - "modified\n" -" since this date\n" -" [ifMatch] : Only return the object if its ETag header matches\n" -" this string\n" -" [ifNotMatch] : Only return the object if its ETag header does " - "not\n" -" match this string\n" -" [startByte] : First byte of byte range to return\n" -" [byteCount] : Number of bytes of byte range to return\n" +" get : Gets an object\n" +" <buckey>/<key> : Bucket/key of object to get\n" +" [filename] : Filename to write object data to (required if -s\n" +" command line parameter was used)\n" +" [ifModifiedSince] : Only return the object if it has been modified " + "since\n" +" this date\n" +" [ifNotmodifiedSince] : Only return the object if it has not been " + "modified\n" +" since this date\n" +" [ifMatch] : Only return the object if its ETag header matches\n" +" this string\n" +" [ifNotMatch] : Only return the object if its ETag header does " + "not\n" +" match this string\n" +" [startByte] : First byte of byte range to return\n" +" [byteCount] : Number of bytes of byte range to return\n" "\n" -" head : Gets only the headers of an object, implies -s\n" -" <bucket>/<key> : Bucket/key of object to get headers of\n" +" head : Gets only the headers of an object, implies -s\n" +" <bucket>/<key> : Bucket/key of object to get headers of\n" "\n" -" gqs : Generates an authenticated query string\n" -" <bucket>[/<key>] : Bucket or bucket/key to generate query string for\n" -" [expires] : Expiration date for query string\n" -" [resource] : Sub-resource of key for query string, without a\n" -" leading '?', for example, \"torrent\"\n" +" gqs : Generates an authenticated query string\n" +" <bucket>[/<key>] : Bucket or bucket/key to generate query string for\n" +" [expires] : Expiration date for query string\n" +" [resource] : Sub-resource of key for query string, without a\n" +" leading '?', for example, \"torrent\"\n" "\n" " Canned ACLs:\n" "\n" " The following canned ACLs are supported:\n" -" private (default), public-read, public-read-write, authenticated-read\n" +" private (default), public-read, public-read-write, authenticated-read\n" "\n" " ACL Format:\n" "\n" " For the getacl and setacl commands, the format of the ACL list is:\n" " 1) An initial line giving the owner id in this format:\n" -" OwnerID <Owner ID> <Owner Display Name>\n" +" OwnerID <Owner ID> <Owner Display Name>\n" " 2) Optional header lines, giving column headers, starting with the\n" -" word \"Type\", or with some number of dashes\n" +" word \"Type\", or with some number of dashes\n" " 3) Grant lines, of the form:\n" -" <Grant Type> (whitespace) <Grantee> (whitespace) <Permission>\n" -" where Grant Type is one of: Email, UserID, or Group, and\n" -" Grantee is the identification of the grantee based on this type,\n" -" and Permission is one of: READ, WRITE, READ_ACP, or FULL_CONTROL.\n" +" <Grant Type> (whitespace) <Grantee> (whitespace) <Permission>\n" +" where Grant Type is one of: Email, UserID, or Group, and\n" +" Grantee is the identification of the grantee based on this type,\n" +" and Permission is one of: READ, WRITE, READ_ACP, or FULL_CONTROL.\n" "\n" " Note that the easiest way to modify an ACL is to first get it, saving it\n" " into a file, then modifying the file, and then setting the modified file\n" @@ -317,217 +317,217 @@ static void usageExit(FILE *out) "\n" " The format for dates used in parameters is as ISO 8601 dates, i.e.\n" " YYYY-MM-DDTHH:MM:SS[.s...][T/+-dd:dd]. Examples:\n" -" 2008-07-29T20:36:14.0023T\n" -" 2008-07-29T20:36:14.0023+06:00\n" -" 2008-07-29T20:36:14.0023-10:00\n" +" 2008-07-29T20:36:14.0023T\n" +" 2008-07-29T20:36:14.0023+06:00\n" +" 2008-07-29T20:36:14.0023-10:00\n" "\n"); - exit(-1); + exit(-1); } static uint64_t convertInt(const char *str, const char *paramName) { - uint64_t ret = 0; - - while (*str) { - if (!isdigit(*str)) { - fprintf(stderr, "\nERROR: Nondigit in %s parameter: %c\n", - paramName, *str); - usageExit(stderr); - } - ret *= 10; - ret += (*str++ - '0'); - } - - return ret; + uint64_t ret = 0; + + while (*str) { + if (!isdigit(*str)) { + fprintf(stderr, "\nERROR: Nondigit in %s parameter: %c\n", + paramName, *str); + usageExit(stderr); + } + ret *= 10; + ret += (*str++ - '0'); + } + + return ret; } typedef struct growbuffer { - // The total number of bytes, and the start byte - int size; - // The start byte - int start; - // The blocks - char data[64 * 1024]; - struct growbuffer *prev, *next; + // The total number of bytes, and the start byte + int size; + // The start byte + int start; + // The blocks + char data[64 * 1024]; + struct growbuffer *prev, *next; } growbuffer; // returns nonzero on success, zero on out of memory static int growbuffer_append(growbuffer **gb, const char *data, int dataLen) { - while (dataLen) { - growbuffer *buf = *gb ? (*gb)->prev : 0; - if (!buf || (buf->size == sizeof(buf->data))) { - buf = (growbuffer *) malloc(sizeof(growbuffer)); - if (!buf) { - return 0; - } - buf->size = 0; - buf->start = 0; - if (*gb) { - buf->prev = (*gb)->prev; - buf->next = *gb; - (*gb)->prev->next = buf; - (*gb)->prev = buf; - } - else { - buf->prev = buf->next = buf; - *gb = buf; - } - } - - int toCopy = (sizeof(buf->data) - buf->size); - if (toCopy > dataLen) { - toCopy = dataLen; - } - - memcpy(&(buf->data[buf->size]), data, toCopy); - - buf->size += toCopy, data += toCopy, dataLen -= toCopy; - } - - return 1; + while (dataLen) { + growbuffer *buf = *gb ? (*gb)->prev : 0; + if (!buf || (buf->size == sizeof(buf->data))) { + buf = (growbuffer *) malloc(sizeof(growbuffer)); + if (!buf) { + return 0; + } + buf->size = 0; + buf->start = 0; + if (*gb) { + buf->prev = (*gb)->prev; + buf->next = *gb; + (*gb)->prev->next = buf; + (*gb)->prev = buf; + } + else { + buf->prev = buf->next = buf; + *gb = buf; + } + } + + int toCopy = (sizeof(buf->data) - buf->size); + if (toCopy > dataLen) { + toCopy = dataLen; + } + + memcpy(&(buf->data[buf->size]), data, toCopy); + + buf->size += toCopy, data += toCopy, dataLen -= toCopy; + } + + return 1; } static void growbuffer_read(growbuffer **gb, int amt, int *amtReturn, - char *buffer) + char *buffer) { - *amtReturn = 0; + *amtReturn = 0; - growbuffer *buf = *gb; + growbuffer *buf = *gb; - if (!buf) { - return; - } + if (!buf) { + return; + } - *amtReturn = (buf->size > amt) ? amt : buf->size; + *amtReturn = (buf->size > amt) ? amt : buf->size; - memcpy(buffer, &(buf->data[buf->start]), *amtReturn); - - buf->start += *amtReturn, buf->size -= *amtReturn; + memcpy(buffer, &(buf->data[buf->start]), *amtReturn); + + buf->start += *amtReturn, buf->size -= *amtReturn; - if (buf->size == 0) { - if (buf->next == buf) { - *gb = 0; - } - else { - *gb = buf->next; - } - free(buf); - } + if (buf->size == 0) { + if (buf->next == buf) { + *gb = 0; + } + else { + *gb = buf->next; + } + free(buf); + } } static void growbuffer_destroy(growbuffer *gb) { - growbuffer *start = gb; + growbuffer *start = gb; - while (gb) { - growbuffer *next = gb->next; - free(gb); - gb = (next == start) ? 0 : next; - } + while (gb) { + growbuffer *next = gb->next; + free(gb); + gb = (next == start) ? 0 : next; + } } -// Convenience utility for making the code look nicer. Tests a string +// Convenience utility for making the code look nicer. Tests a string // against a format; only the characters specified in the format are // checked (i.e. if the string is longer than the format, the string still -// checks out ok). Format characters are: +// checks out ok). Format characters are: // d - is a digit // anything else - is that character // Returns nonzero the string checks out, zero if it does not. static int checkString(const char *str, const char *format) { - while (*format) { - if (*format == 'd') { - if (!isdigit(*str)) { - return 0; - } - } - else if (*str != *format) { - return 0; - } - str++, format++; - } - - return 1; + while (*format) { + if (*format == 'd') { + if (!isdigit(*str)) { + return 0; + } + } + else if (*str != *format) { + return 0; + } + str++, format++; + } + + return 1; } static int64_t parseIso8601Time(const char *str) { - // Check to make sure that it has a valid format - if (!checkString(str, "dddd-dd-ddTdd:dd:dd")) { - return -1; - } + // Check to make sure that it has a valid format + if (!checkString(str, "dddd-dd-ddTdd:dd:dd")) { + return -1; + } #define nextnum() (((*str - '0') * 10) + (*(str + 1) - '0')) - // Convert it - struct tm stm; - memset(&stm, 0, sizeof(stm)); - - stm.tm_year = (nextnum() - 19) * 100; - str += 2; - stm.tm_year += nextnum(); - str += 3; - - stm.tm_mon = nextnum() - 1; - str += 3; - - stm.tm_mday = nextnum(); - str += 3; - - stm.tm_hour = nextnum(); - str += 3; - - stm.tm_min = nextnum(); - str += 3; - - stm.tm_sec = nextnum(); - str += 2; - - stm.tm_isdst = -1; - - // This is hokey but it's the recommended way ... - char *tz = getenv("TZ"); - setenv("TZ", "UTC", 1); - - int64_t ret = mktime(&stm); - - if (tz) { - setenv("TZ", tz, 1); - } - else { - unsetenv("TZ"); - } - - // Skip the millis - - if (*str == '.') { - str++; - while (isdigit(*str)) { - str++; - } - } - - if (checkString(str, "-dd:dd") || checkString(str, "+dd:dd")) { - int sign = (*str++ == '-') ? -1 : 1; - int hours = nextnum(); - str += 3; - int minutes = nextnum(); - ret += (-sign * (((hours * 60) + minutes) * 60)); - } - // Else it should be Z to be a conformant time string, but we just assume - // that it is rather than enforcing that - - return ret; + // Convert it + struct tm stm; + memset(&stm, 0, sizeof(stm)); + + stm.tm_year = (nextnum() - 19) * 100; + str += 2; + stm.tm_year += nextnum(); + str += 3; + + stm.tm_mon = nextnum() - 1; + str += 3; + + stm.tm_mday = nextnum(); + str += 3; + + stm.tm_hour = nextnum(); + str += 3; + + stm.tm_min = nextnum(); + str += 3; + + stm.tm_sec = nextnum(); + str += 2; + + stm.tm_isdst = -1; + + // This is hokey but it's the recommended way ... + char *tz = getenv("TZ"); + setenv("TZ", "UTC", 1); + + int64_t ret = mktime(&stm); + + if (tz) { + setenv("TZ", tz, 1); + } + else { + unsetenv("TZ"); + } + + // Skip the millis + + if (*str == '.') { + str++; + while (isdigit(*str)) { + str++; + } + } + + if (checkString(str, "-dd:dd") || checkString(str, "+dd:dd")) { + int sign = (*str++ == '-') ? -1 : 1; + int hours = nextnum(); + str += 3; + int minutes = nextnum(); + ret += (-sign * (((hours * 60) + minutes) * 60)); + } + // Else it should be Z to be a conformant time string, but we just assume + // that it is rather than enforcing that + + return ret; } @@ -537,161 +537,161 @@ static int64_t parseIso8601Time(const char *str) // Email email_address permission // UserID user_id (display_name) permission // Group Authenticated AWS Users permission -// Group All Users permission +// Group All Users permission // permission is one of READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL static int convert_simple_acl(char *aclXml, char *ownerId, - char *ownerDisplayName, - int *aclGrantCountReturn, - S3AclGrant *aclGrants) + char *ownerDisplayName, + int *aclGrantCountReturn, + S3AclGrant *aclGrants) { - *aclGrantCountReturn = 0; - *ownerId = 0; - *ownerDisplayName = 0; - -#define SKIP_SPACE(require_more) \ - do { \ - while (isspace(*aclXml)) { \ - aclXml++; \ - } \ - if (require_more && !*aclXml) { \ - return 0; \ - } \ - } while (0) - -#define COPY_STRING_MAXLEN(field, maxlen) \ - do { \ - SKIP_SPACE(1); \ - int len = 0; \ - while ((len < maxlen) && !isspace(*aclXml)) { \ - field[len++] = *aclXml++; \ - } \ - field[len] = 0; \ - } while (0) - -#define COPY_STRING(field) \ - COPY_STRING_MAXLEN(field, (int) (sizeof(field) - 1)) - - while (1) { - SKIP_SPACE(0); - - if (!*aclXml) { - break; - } - - // Skip Type lines and dash lines - if (!strncmp(aclXml, "Type", sizeof("Type") - 1) || - (*aclXml == '-')) { - while (*aclXml && ((*aclXml != '\n') && (*aclXml != '\r'))) { - aclXml++; - } - continue; - } - - if (!strncmp(aclXml, "OwnerID", sizeof("OwnerID") - 1)) { - aclXml += sizeof("OwnerID") - 1; - COPY_STRING_MAXLEN(ownerId, S3_MAX_GRANTEE_USER_ID_SIZE); - SKIP_SPACE(1); - COPY_STRING_MAXLEN(ownerDisplayName, - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE); - continue; - } - - if (*aclGrantCountReturn == S3_MAX_ACL_GRANT_COUNT) { - return 0; - } - - S3AclGrant *grant = &(aclGrants[(*aclGrantCountReturn)++]); - - if (!strncmp(aclXml, "Email", sizeof("Email") - 1)) { - grant->granteeType = S3GranteeTypeAmazonCustomerByEmail; - aclXml += sizeof("Email") - 1; - COPY_STRING(grant->grantee.amazonCustomerByEmail.emailAddress); - } - else if (!strncmp(aclXml, "UserID", sizeof("UserID") - 1)) { - grant->granteeType = S3GranteeTypeCanonicalUser; - aclXml += sizeof("UserID") - 1; - COPY_STRING(grant->grantee.canonicalUser.id); - SKIP_SPACE(1); - // Now do display name - COPY_STRING(grant->grantee.canonicalUser.displayName); - } - else if (!strncmp(aclXml, "Group", sizeof("Group") - 1)) { - aclXml += sizeof("Group") - 1; - SKIP_SPACE(1); - if (!strncmp(aclXml, "Authenticated AWS Users", - sizeof("Authenticated AWS Users") - 1)) { - grant->granteeType = S3GranteeTypeAllAwsUsers; - aclXml += (sizeof("Authenticated AWS Users") - 1); - } - else if (!strncmp(aclXml, "All Users", sizeof("All Users") - 1)) { - grant->granteeType = S3GranteeTypeAllUsers; - aclXml += (sizeof("All Users") - 1); - } - else if (!strncmp(aclXml, "Log Delivery", - sizeof("Log Delivery") - 1)) { - grant->granteeType = S3GranteeTypeLogDelivery; - aclXml += (sizeof("Log Delivery") - 1); - } - else { - return 0; - } - } - else { - return 0; - } - - SKIP_SPACE(1); - - if (!strncmp(aclXml, "READ_ACP", sizeof("READ_ACP") - 1)) { - grant->permission = S3PermissionReadACP; - aclXml += (sizeof("READ_ACP") - 1); - } - else if (!strncmp(aclXml, "READ", sizeof("READ") - 1)) { - grant->permission = S3PermissionRead; - aclXml += (sizeof("READ") - 1); - } - else if (!strncmp(aclXml, "WRITE_ACP", sizeof("WRITE_ACP") - 1)) { - grant->permission = S3PermissionWriteACP; - aclXml += (sizeof("WRITE_ACP") - 1); - } - else if (!strncmp(aclXml, "WRITE", sizeof("WRITE") - 1)) { - grant->permission = S3PermissionWrite; - aclXml += (sizeof("WRITE") - 1); - } - else if (!strncmp(aclXml, "FULL_CONTROL", - sizeof("FULL_CONTROL") - 1)) { - grant->permission = S3PermissionFullControl; - aclXml += (sizeof("FULL_CONTROL") - 1); - } - } - - return 1; + *aclGrantCountReturn = 0; + *ownerId = 0; + *ownerDisplayName = 0; + +#define SKIP_SPACE(require_more) \ + do { \ + while (isspace(*aclXml)) { \ + aclXml++; \ + } \ + if (require_more && !*aclXml) { \ + return 0; \ + } \ + } while (0) + +#define COPY_STRING_MAXLEN(field, maxlen) \ + do { \ + SKIP_SPACE(1); \ + int len = 0; \ + while ((len < maxlen) && !isspace(*aclXml)) { \ + field[len++] = *aclXml++; \ + } \ + field[len] = 0; \ + } while (0) + +#define COPY_STRING(field) \ + COPY_STRING_MAXLEN(field, (int) (sizeof(field) - 1)) + + while (1) { + SKIP_SPACE(0); + + if (!*aclXml) { + break; + } + + // Skip Type lines and dash lines + if (!strncmp(aclXml, "Type", sizeof("Type") - 1) || + (*aclXml == '-')) { + while (*aclXml && ((*aclXml != '\n') && (*aclXml != '\r'))) { + aclXml++; + } + continue; + } + + if (!strncmp(aclXml, "OwnerID", sizeof("OwnerID") - 1)) { + aclXml += sizeof("OwnerID") - 1; + COPY_STRING_MAXLEN(ownerId, S3_MAX_GRANTEE_USER_ID_SIZE); + SKIP_SPACE(1); + COPY_STRING_MAXLEN(ownerDisplayName, + S3_MAX_GRANTEE_DISPLAY_NAME_SIZE); + continue; + } + + if (*aclGrantCountReturn == S3_MAX_ACL_GRANT_COUNT) { + return 0; + } + + S3AclGrant *grant = &(aclGrants[(*aclGrantCountReturn)++]); + + if (!strncmp(aclXml, "Email", sizeof("Email") - 1)) { + grant->granteeType = S3GranteeTypeAmazonCustomerByEmail; + aclXml += sizeof("Email") - 1; + COPY_STRING(grant->grantee.amazonCustomerByEmail.emailAddress); + } + else if (!strncmp(aclXml, "UserID", sizeof("UserID") - 1)) { + grant->granteeType = S3GranteeTypeCanonicalUser; + aclXml += sizeof("UserID") - 1; + COPY_STRING(grant->grantee.canonicalUser.id); + SKIP_SPACE(1); + // Now do display name + COPY_STRING(grant->grantee.canonicalUser.displayName); + } + else if (!strncmp(aclXml, "Group", sizeof("Group") - 1)) { + aclXml += sizeof("Group") - 1; + SKIP_SPACE(1); + if (!strncmp(aclXml, "Authenticated AWS Users", + sizeof("Authenticated AWS Users") - 1)) { + grant->granteeType = S3GranteeTypeAllAwsUsers; + aclXml += (sizeof("Authenticated AWS Users") - 1); + } + else if (!strncmp(aclXml, "All Users", sizeof("All Users") - 1)) { + grant->granteeType = S3GranteeTypeAllUsers; + aclXml += (sizeof("All Users") - 1); + } + else if (!strncmp(aclXml, "Log Delivery", + sizeof("Log Delivery") - 1)) { + grant->granteeType = S3GranteeTypeLogDelivery; + aclXml += (sizeof("Log Delivery") - 1); + } + else { + return 0; + } + } + else { + return 0; + } + + SKIP_SPACE(1); + + if (!strncmp(aclXml, "READ_ACP", sizeof("READ_ACP") - 1)) { + grant->permission = S3PermissionReadACP; + aclXml += (sizeof("READ_ACP") - 1); + } + else if (!strncmp(aclXml, "READ", sizeof("READ") - 1)) { + grant->permission = S3PermissionRead; + aclXml += (sizeof("READ") - 1); + } + else if (!strncmp(aclXml, "WRITE_ACP", sizeof("WRITE_ACP") - 1)) { + grant->permission = S3PermissionWriteACP; + aclXml += (sizeof("WRITE_ACP") - 1); + } + else if (!strncmp(aclXml, "WRITE", sizeof("WRITE") - 1)) { + grant->permission = S3PermissionWrite; + aclXml += (sizeof("WRITE") - 1); + } + else if (!strncmp(aclXml, "FULL_CONTROL", + sizeof("FULL_CONTROL") - 1)) { + grant->permission = S3PermissionFullControl; + aclXml += (sizeof("FULL_CONTROL") - 1); + } + } + + return 1; } static int should_retry() { - if (retriesG--) { - // Sleep before next retry; start out with a 1 second sleep - static int retrySleepInterval = 1; - sleep(retrySleepInterval); - // Next sleep 1 second longer - retrySleepInterval++; - return 1; - } - - return 0; + if (retriesG--) { + // Sleep before next retry; start out with a 1 second sleep + static int retrySleepInterval = 1; + sleep(retrySleepInterval); + // Next sleep 1 second longer + retrySleepInterval++; + return 1; + } + + return 0; } static struct option longOptionsG[] = { - { "force", no_argument, 0, 'f' }, - { "vhost-style", no_argument, 0, 'h' }, - { "unencrypted", no_argument, 0, 'u' }, - { "show-properties", no_argument, 0, 's' }, - { "retries", required_argument, 0, 'r' }, - { 0, 0, 0, 0 } + { "force", no_argument, 0, 'f' }, + { "vhost-style", no_argument, 0, 'h' }, + { "unencrypted", no_argument, 0, 'u' }, + { "show-properties", no_argument, 0, 's' }, + { "retries", required_argument, 0, 'r' }, + { 0, 0, 0, 0 } }; @@ -700,44 +700,44 @@ static struct option longOptionsG[] = // This callback does the same thing for every request type: prints out the // properties if the user has requested them to be so static S3Status responsePropertiesCallback - (const S3ResponseProperties *properties, void *callbackData) + (const S3ResponseProperties *properties, void *callbackData) { - (void) callbackData; - - if (!showResponsePropertiesG) { - return S3StatusOK; - } - -#define print_nonnull(name, field) \ - do { \ - if (properties-> field) { \ - printf("%s: %s\n", name, properties-> field); \ - } \ - } while (0) - - print_nonnull("Content-Type", contentType); - print_nonnull("Request-Id", requestId); - print_nonnull("Request-Id-2", requestId2); - if (properties->contentLength > 0) { - printf("Content-Length: %lld\n", - (unsigned long long) properties->contentLength); - } - print_nonnull("Server", server); - print_nonnull("ETag", eTag); - if (properties->lastModified > 0) { - char timebuf[256]; - time_t t = (time_t) properties->lastModified; - // gmtime is not thread-safe but we don't care here. - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); - printf("Last-Modified: %s\n", timebuf); - } - int i; - for (i = 0; i < properties->metaDataCount; i++) { - printf("x-amz-meta-%s: %s\n", properties->metaData[i].name, - properties->metaData[i].value); - } - - return S3StatusOK; + (void) callbackData; + + if (!showResponsePropertiesG) { + return S3StatusOK; + } + +#define print_nonnull(name, field) \ + do { \ + if (properties-> field) { \ + printf("%s: %s\n", name, properties-> field); \ + } \ + } while (0) + + print_nonnull("Content-Type", contentType); + print_nonnull("Request-Id", requestId); + print_nonnull("Request-Id-2", requestId2); + if (properties->contentLength > 0) { + printf("Content-Length: %lld\n", + (unsigned long long) properties->contentLength); + } + print_nonnull("Server", server); + print_nonnull("ETag", eTag); + if (properties->lastModified > 0) { + char timebuf[256]; + time_t t = (time_t) properties->lastModified; + // gmtime is not thread-safe but we don't care here. + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); + printf("Last-Modified: %s\n", timebuf); + } + int i; + for (i = 0; i < properties->metaDataCount; i++) { + printf("x-amz-meta-%s: %s\n", properties->metaData[i].name, + properties->metaData[i].value); + } + + return S3StatusOK; } @@ -746,39 +746,39 @@ static S3Status responsePropertiesCallback // This callback does the same thing for every request type: saves the status // and error stuff in global variables static void responseCompleteCallback(S3Status status, - const S3ErrorDetails *error, - void *callbackData) + const S3ErrorDetails *error, + void *callbackData) { - (void) callbackData; - - statusG = status; - // Compose the error details message now, although we might not use it. - // Can't just save a pointer to [error] since it's not guaranteed to last - // beyond this callback - int len = 0; - if (error && error->message) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - " Message: %s\n", error->message); - } - if (error && error->resource) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - " Resource: %s\n", error->resource); - } - if (error && error->furtherDetails) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - " Further Details: %s\n", error->furtherDetails); - } - if (error && error->extraDetailsCount) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - "%s", " Extra Details:\n"); - int i; - for (i = 0; i < error->extraDetailsCount; i++) { - len += snprintf(&(errorDetailsG[len]), - sizeof(errorDetailsG) - len, " %s: %s\n", - error->extraDetails[i].name, - error->extraDetails[i].value); - } - } + (void) callbackData; + + statusG = status; + // Compose the error details message now, although we might not use it. + // Can't just save a pointer to [error] since it's not guaranteed to last + // beyond this callback + int len = 0; + if (error && error->message) { + len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, + " Message: %s\n", error->message); + } + if (error && error->resource) { + len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, + " Resource: %s\n", error->resource); + } + if (error && error->furtherDetails) { + len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, + " Further Details: %s\n", error->furtherDetails); + } + if (error && error->extraDetailsCount) { + len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, + "%s", " Extra Details:\n"); + int i; + for (i = 0; i < error->extraDetailsCount; i++) { + len += snprintf(&(errorDetailsG[len]), + sizeof(errorDetailsG) - len, " %s: %s\n", + error->extraDetails[i].name, + error->extraDetails[i].value); + } + } } @@ -786,93 +786,93 @@ static void responseCompleteCallback(S3Status status, typedef struct list_service_data { - int headerPrinted; - int allDetails; + int headerPrinted; + int allDetails; } list_service_data; static void printListServiceHeader(int allDetails) { - printf("%-56s %-20s", " Bucket", - " Created"); - if (allDetails) { - printf(" %-64s %-12s", - " Owner ID", - "Display Name"); - } - printf("\n"); - printf("-------------------------------------------------------- " - "--------------------"); - if (allDetails) { - printf(" -------------------------------------------------" - "--------------- ------------"); - } - printf("\n"); + printf("%-56s %-20s", " Bucket", + " Created"); + if (allDetails) { + printf(" %-64s %-12s", + " Owner ID", + "Display Name"); + } + printf("\n"); + printf("-------------------------------------------------------- " + "--------------------"); + if (allDetails) { + printf(" -------------------------------------------------" + "--------------- ------------"); + } + printf("\n"); } static S3Status listServiceCallback(const char *ownerId, - const char *ownerDisplayName, - const char *bucketName, - int64_t creationDate, void *callbackData) + const char *ownerDisplayName, + const char *bucketName, + int64_t creationDate, void *callbackData) { - list_service_data *data = (list_service_data *) callbackData; - - if (!data->headerPrinted) { - data->headerPrinted = 1; - printListServiceHeader(data->allDetails); - } - - char timebuf[256]; - if (creationDate >= 0) { - time_t t = (time_t) creationDate; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); - } - else { - timebuf[0] = 0; - } - - printf("%-56s %-20s", bucketName, timebuf); - if (data->allDetails) { - printf(" %-64s %-12s", ownerId ? ownerId : "", - ownerDisplayName ? ownerDisplayName : ""); - } - printf("\n"); - - return S3StatusOK; + list_service_data *data = (list_service_data *) callbackData; + + if (!data->headerPrinted) { + data->headerPrinted = 1; + printListServiceHeader(data->allDetails); + } + + char timebuf[256]; + if (creationDate >= 0) { + time_t t = (time_t) creationDate; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); + } + else { + timebuf[0] = 0; + } + + printf("%-56s %-20s", bucketName, timebuf); + if (data->allDetails) { + printf(" %-64s %-12s", ownerId ? ownerId : "", + ownerDisplayName ? ownerDisplayName : ""); + } + printf("\n"); + + return S3StatusOK; } static void list_service(int allDetails) { - list_service_data data; - - data.headerPrinted = 0; - data.allDetails = allDetails; - - S3_init(); - - S3ListServiceHandler listServiceHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &listServiceCallback - }; - - do { - S3_list_service(protocolG, accessKeyIdG, secretAccessKeyG, 0, - &listServiceHandler, &data); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - if (!data.headerPrinted) { - printListServiceHeader(allDetails); - } - } - else { - printError(); - } - - S3_deinitialize(); + list_service_data data; + + data.headerPrinted = 0; + data.allDetails = allDetails; + + S3_init(); + + S3ListServiceHandler listServiceHandler = + { + { &responsePropertiesCallback, &responseCompleteCallback }, + &listServiceCallback + }; + + do { + S3_list_service(protocolG, accessKeyIdG, secretAccessKeyG, 0, + &listServiceHandler, &data); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG == S3StatusOK) { + if (!data.headerPrinted) { + printListServiceHeader(allDetails); + } + } + else { + printError(); + } + + S3_deinitialize(); } @@ -880,63 +880,63 @@ static void list_service(int allDetails) static void test_bucket(int argc, char **argv, int optindex) { - // test bucket - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - - if (optindex != argc) { - fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); - usageExit(stderr); - } - - S3_init(); - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, &responseCompleteCallback - }; - - char locationConstraint[64]; - do { - S3_test_bucket(protocolG, uriStyleG, accessKeyIdG, secretAccessKeyG, - bucketName, sizeof(locationConstraint), - locationConstraint, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - const char *result; - - switch (statusG) { - case S3StatusOK: - // bucket exists - result = locationConstraint[0] ? locationConstraint : "USA"; - break; - case S3StatusErrorNoSuchBucket: - result = "Does Not Exist"; - break; - case S3StatusErrorAccessDenied: - result = "Access Denied"; - break; - default: - result = 0; - break; - } - - if (result) { - printf("%-56s %-20s\n", " Bucket", - " Status"); - printf("-------------------------------------------------------- " - "--------------------\n"); - printf("%-56s %-20s\n", bucketName, result); - } - else { - printError(); - } - - S3_deinitialize(); + // test bucket + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); + usageExit(stderr); + } + + const char *bucketName = argv[optindex++]; + + if (optindex != argc) { + fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); + usageExit(stderr); + } + + S3_init(); + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, &responseCompleteCallback + }; + + char locationConstraint[64]; + do { + S3_test_bucket(protocolG, uriStyleG, accessKeyIdG, secretAccessKeyG, + bucketName, sizeof(locationConstraint), + locationConstraint, 0, &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + const char *result; + + switch (statusG) { + case S3StatusOK: + // bucket exists + result = locationConstraint[0] ? locationConstraint : "USA"; + break; + case S3StatusErrorNoSuchBucket: + result = "Does Not Exist"; + break; + case S3StatusErrorAccessDenied: + result = "Access Denied"; + break; + default: + result = 0; + break; + } + + if (result) { + printf("%-56s %-20s\n", " Bucket", + " Status"); + printf("-------------------------------------------------------- " + "--------------------\n"); + printf("%-56s %-20s\n", bucketName, result); + } + else { + printError(); + } + + S3_deinitialize(); } @@ -944,76 +944,76 @@ static void test_bucket(int argc, char **argv, int optindex) static void create_bucket(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - - if (!forceG && (S3_validate_bucket_name - (bucketName, S3UriStyleVirtualHost) != S3StatusOK)) { - fprintf(stderr, "\nWARNING: Bucket name is not valid for " - "virtual-host style URI access.\n"); - fprintf(stderr, "Bucket not created. Use -f option to force the " - "bucket to be created despite\n"); - fprintf(stderr, "this warning.\n\n"); - exit(-1); - } - - const char *locationConstraint = 0; - S3CannedAcl cannedAcl = S3CannedAclPrivate; - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, LOCATION_PREFIX, LOCATION_PREFIX_LEN)) { - locationConstraint = &(param[LOCATION_PREFIX_LEN]); - } - else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { - char *val = &(param[CANNED_ACL_PREFIX_LEN]); - if (!strcmp(val, "private")) { - cannedAcl = S3CannedAclPrivate; - } - else if (!strcmp(val, "public-read")) { - cannedAcl = S3CannedAclPublicRead; - } - else if (!strcmp(val, "public-read-write")) { - cannedAcl = S3CannedAclPublicReadWrite; - } - else if (!strcmp(val, "authenticated-read")) { - cannedAcl = S3CannedAclAuthenticatedRead; - } - else { - fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); - usageExit(stderr); - } - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - S3_init(); - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, &responseCompleteCallback - }; - - do { - S3_create_bucket(protocolG, accessKeyIdG, secretAccessKeyG, - bucketName, cannedAcl, locationConstraint, 0, - &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - printf("Bucket successfully created.\n"); - } - else { - printError(); - } - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); + usageExit(stderr); + } + + const char *bucketName = argv[optindex++]; + + if (!forceG && (S3_validate_bucket_name + (bucketName, S3UriStyleVirtualHost) != S3StatusOK)) { + fprintf(stderr, "\nWARNING: Bucket name is not valid for " + "virtual-host style URI access.\n"); + fprintf(stderr, "Bucket not created. Use -f option to force the " + "bucket to be created despite\n"); + fprintf(stderr, "this warning.\n\n"); + exit(-1); + } + + const char *locationConstraint = 0; + S3CannedAcl cannedAcl = S3CannedAclPrivate; + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, LOCATION_PREFIX, LOCATION_PREFIX_LEN)) { + locationConstraint = &(param[LOCATION_PREFIX_LEN]); + } + else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { + char *val = &(param[CANNED_ACL_PREFIX_LEN]); + if (!strcmp(val, "private")) { + cannedAcl = S3CannedAclPrivate; + } + else if (!strcmp(val, "public-read")) { + cannedAcl = S3CannedAclPublicRead; + } + else if (!strcmp(val, "public-read-write")) { + cannedAcl = S3CannedAclPublicReadWrite; + } + else if (!strcmp(val, "authenticated-read")) { + cannedAcl = S3CannedAclAuthenticatedRead; + } + else { + fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); + usageExit(stderr); + } + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + S3_init(); + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, &responseCompleteCallback + }; + + do { + S3_create_bucket(protocolG, accessKeyIdG, secretAccessKeyG, + bucketName, cannedAcl, locationConstraint, 0, + &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG == S3StatusOK) { + printf("Bucket successfully created.\n"); + } + else { + printError(); + } + + S3_deinitialize(); } @@ -1021,35 +1021,35 @@ static void create_bucket(int argc, char **argv, int optindex) static void delete_bucket(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); + usageExit(stderr); + } - const char *bucketName = argv[optindex++]; + const char *bucketName = argv[optindex++]; - if (optindex != argc) { - fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); - usageExit(stderr); - } + if (optindex != argc) { + fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); + usageExit(stderr); + } - S3_init(); + S3_init(); - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, &responseCompleteCallback - }; + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, &responseCompleteCallback + }; - do { - S3_delete_bucket(protocolG, uriStyleG, accessKeyIdG, secretAccessKeyG, - bucketName, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); + do { + S3_delete_bucket(protocolG, uriStyleG, accessKeyIdG, secretAccessKeyG, + bucketName, 0, &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); - if (statusG != S3StatusOK) { - printError(); - } + if (statusG != S3StatusOK) { + printError(); + } - S3_deinitialize(); + S3_deinitialize(); } @@ -1057,285 +1057,285 @@ static void delete_bucket(int argc, char **argv, int optindex) typedef struct list_bucket_callback_data { - int isTruncated; - char nextMarker[1024]; - int keyCount; - int allDetails; + int isTruncated; + char nextMarker[1024]; + int keyCount; + int allDetails; } list_bucket_callback_data; static void printListBucketHeader(int allDetails) { - printf("%-50s %-20s %-5s", - " Key", - " Last Modified", "Size"); - if (allDetails) { - printf(" %-34s %-64s %-12s", - " ETag", - " Owner ID", - "Display Name"); - } - printf("\n"); - printf("-------------------------------------------------- " - "-------------------- -----"); - if (allDetails) { - printf(" ---------------------------------- " - "-------------------------------------------------" - "--------------- ------------"); - } - printf("\n"); + printf("%-50s %-20s %-5s", + " Key", + " Last Modified", "Size"); + if (allDetails) { + printf(" %-34s %-64s %-12s", + " ETag", + " Owner ID", + "Display Name"); + } + printf("\n"); + printf("-------------------------------------------------- " + "-------------------- -----"); + if (allDetails) { + printf(" ---------------------------------- " + "-------------------------------------------------" + "--------------- ------------"); + } + printf("\n"); } static S3Status listBucketCallback(int isTruncated, const char *nextMarker, - int contentsCount, - const S3ListBucketContent *contents, - int commonPrefixesCount, - const char **commonPrefixes, - void *callbackData) + int contentsCount, + const S3ListBucketContent *contents, + int commonPrefixesCount, + const char **commonPrefixes, + void *callbackData) { - list_bucket_callback_data *data = - (list_bucket_callback_data *) callbackData; - - data->isTruncated = isTruncated; - // This is tricky. S3 doesn't return the NextMarker if there is no - // delimiter. Why, I don't know, since it's still useful for paging - // through results. We want NextMarker to be the last content in the - // list, so set it to that if necessary. - if ((!nextMarker || !nextMarker[0]) && contentsCount) { - nextMarker = contents[contentsCount - 1].key; - } - if (nextMarker) { - snprintf(data->nextMarker, sizeof(data->nextMarker), "%s", - nextMarker); - } - else { - data->nextMarker[0] = 0; - } - - if (contentsCount && !data->keyCount) { - printListBucketHeader(data->allDetails); - } - - int i; - for (i = 0; i < contentsCount; i++) { - const S3ListBucketContent *content = &(contents[i]); - char timebuf[256]; - if (0) { - time_t t = (time_t) content->lastModified; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&t)); - printf("\nKey: %s\n", content->key); - printf("Last Modified: %s\n", timebuf); - printf("ETag: %s\n", content->eTag); - printf("Size: %llu\n", (unsigned long long) content->size); - if (content->ownerId) { - printf("Owner ID: %s\n", content->ownerId); - } - if (content->ownerDisplayName) { - printf("Owner Display Name: %s\n", content->ownerDisplayName); - } - } - else { - time_t t = (time_t) content->lastModified; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&t)); - char sizebuf[16]; - if (content->size < 100000) { - sprintf(sizebuf, "%5llu", (unsigned long long) content->size); - } - else if (content->size < (1024 * 1024)) { - sprintf(sizebuf, "%4lluK", - ((unsigned long long) content->size) / 1024ULL); - } - else if (content->size < (10 * 1024 * 1024)) { - float f = content->size; - f /= (1024 * 1024); - sprintf(sizebuf, "%1.2fM", f); - } - else if (content->size < (1024 * 1024 * 1024)) { - sprintf(sizebuf, "%4lluM", - ((unsigned long long) content->size) / - (1024ULL * 1024ULL)); - } - else { - float f = (content->size / 1024); - f /= (1024 * 1024); - sprintf(sizebuf, "%1.2fG", f); - } - printf("%-50s %s %s", content->key, timebuf, sizebuf); - if (data->allDetails) { - printf(" %-34s %-64s %-12s", - content->eTag, - content->ownerId ? content->ownerId : "", - content->ownerDisplayName ? - content->ownerDisplayName : ""); - } - printf("\n"); - } - } - - data->keyCount += contentsCount; - - for (i = 0; i < commonPrefixesCount; i++) { - printf("\nCommon Prefix: %s\n", commonPrefixes[i]); - } - - return S3StatusOK; + list_bucket_callback_data *data = + (list_bucket_callback_data *) callbackData; + + data->isTruncated = isTruncated; + // This is tricky. S3 doesn't return the NextMarker if there is no + // delimiter. Why, I don't know, since it's still useful for paging + // through results. We want NextMarker to be the last content in the + // list, so set it to that if necessary. + if ((!nextMarker || !nextMarker[0]) && contentsCount) { + nextMarker = contents[contentsCount - 1].key; + } + if (nextMarker) { + snprintf(data->nextMarker, sizeof(data->nextMarker), "%s", + nextMarker); + } + else { + data->nextMarker[0] = 0; + } + + if (contentsCount && !data->keyCount) { + printListBucketHeader(data->allDetails); + } + + int i; + for (i = 0; i < contentsCount; i++) { + const S3ListBucketContent *content = &(contents[i]); + char timebuf[256]; + if (0) { + time_t t = (time_t) content->lastModified; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", + gmtime(&t)); + printf("\nKey: %s\n", content->key); + printf("Last Modified: %s\n", timebuf); + printf("ETag: %s\n", content->eTag); + printf("Size: %llu\n", (unsigned long long) content->size); + if (content->ownerId) { + printf("Owner ID: %s\n", content->ownerId); + } + if (content->ownerDisplayName) { + printf("Owner Display Name: %s\n", content->ownerDisplayName); + } + } + else { + time_t t = (time_t) content->lastModified; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", + gmtime(&t)); + char sizebuf[16]; + if (content->size < 100000) { + sprintf(sizebuf, "%5llu", (unsigned long long) content->size); + } + else if (content->size < (1024 * 1024)) { + sprintf(sizebuf, "%4lluK", + ((unsigned long long) content->size) / 1024ULL); + } + else if (content->size < (10 * 1024 * 1024)) { + float f = content->size; + f /= (1024 * 1024); + sprintf(sizebuf, "%1.2fM", f); + } + else if (content->size < (1024 * 1024 * 1024)) { + sprintf(sizebuf, "%4lluM", + ((unsigned long long) content->size) / + (1024ULL * 1024ULL)); + } + else { + float f = (content->size / 1024); + f /= (1024 * 1024); + sprintf(sizebuf, "%1.2fG", f); + } + printf("%-50s %s %s", content->key, timebuf, sizebuf); + if (data->allDetails) { + printf(" %-34s %-64s %-12s", + content->eTag, + content->ownerId ? content->ownerId : "", + content->ownerDisplayName ? + content->ownerDisplayName : ""); + } + printf("\n"); + } + } + + data->keyCount += contentsCount; + + for (i = 0; i < commonPrefixesCount; i++) { + printf("\nCommon Prefix: %s\n", commonPrefixes[i]); + } + + return S3StatusOK; } static void list_bucket(const char *bucketName, const char *prefix, - const char *marker, const char *delimiter, - int maxkeys, int allDetails) + const char *marker, const char *delimiter, + int maxkeys, int allDetails) { - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ListBucketHandler listBucketHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &listBucketCallback - }; - - list_bucket_callback_data data; - - snprintf(data.nextMarker, sizeof(data.nextMarker), "%s", marker); - data.keyCount = 0; - data.allDetails = allDetails; - - do { - data.isTruncated = 0; - do { - S3_list_bucket(&bucketContext, prefix, data.nextMarker, - delimiter, maxkeys, 0, &listBucketHandler, &data); - } while (S3_status_is_retryable(statusG) && should_retry()); - if (statusG != S3StatusOK) { - break; - } - marker = data.nextMarker; - } while (data.isTruncated && (!maxkeys || (data.keyCount < maxkeys))); - - if (statusG == S3StatusOK) { - if (!data.keyCount) { - printListBucketHeader(allDetails); - } - } - else { - printError(); - } - - S3_deinitialize(); + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3ListBucketHandler listBucketHandler = + { + { &responsePropertiesCallback, &responseCompleteCallback }, + &listBucketCallback + }; + + list_bucket_callback_data data; + + snprintf(data.nextMarker, sizeof(data.nextMarker), "%s", marker); + data.keyCount = 0; + data.allDetails = allDetails; + + do { + data.isTruncated = 0; + do { + S3_list_bucket(&bucketContext, prefix, data.nextMarker, + delimiter, maxkeys, 0, &listBucketHandler, &data); + } while (S3_status_is_retryable(statusG) && should_retry()); + if (statusG != S3StatusOK) { + break; + } + marker = data.nextMarker; + } while (data.isTruncated && (!maxkeys || (data.keyCount < maxkeys))); + + if (statusG == S3StatusOK) { + if (!data.keyCount) { + printListBucketHeader(allDetails); + } + } + else { + printError(); + } + + S3_deinitialize(); } static void list(int argc, char **argv, int optindex) { - if (optindex == argc) { - list_service(0); - return; - } - - const char *bucketName = 0; - - const char *prefix = 0, *marker = 0, *delimiter = 0; - int maxkeys = 0, allDetails = 0; - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, PREFIX_PREFIX, PREFIX_PREFIX_LEN)) { - prefix = &(param[PREFIX_PREFIX_LEN]); - } - else if (!strncmp(param, MARKER_PREFIX, MARKER_PREFIX_LEN)) { - marker = &(param[MARKER_PREFIX_LEN]); - } - else if (!strncmp(param, DELIMITER_PREFIX, DELIMITER_PREFIX_LEN)) { - delimiter = &(param[DELIMITER_PREFIX_LEN]); - } - else if (!strncmp(param, MAXKEYS_PREFIX, MAXKEYS_PREFIX_LEN)) { - maxkeys = convertInt(&(param[MAXKEYS_PREFIX_LEN]), "maxkeys"); - } - else if (!strncmp(param, ALL_DETAILS_PREFIX, - ALL_DETAILS_PREFIX_LEN)) { - const char *ad = &(param[ALL_DETAILS_PREFIX_LEN]); - if (!strcmp(ad, "true") || !strcmp(ad, "TRUE") || - !strcmp(ad, "yes") || !strcmp(ad, "YES") || - !strcmp(ad, "1")) { - allDetails = 1; - } - } - else if (!bucketName) { - bucketName = param; - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - if (bucketName) { - list_bucket(bucketName, prefix, marker, delimiter, maxkeys, - allDetails); - } - else { - list_service(allDetails); - } + if (optindex == argc) { + list_service(0); + return; + } + + const char *bucketName = 0; + + const char *prefix = 0, *marker = 0, *delimiter = 0; + int maxkeys = 0, allDetails = 0; + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, PREFIX_PREFIX, PREFIX_PREFIX_LEN)) { + prefix = &(param[PREFIX_PREFIX_LEN]); + } + else if (!strncmp(param, MARKER_PREFIX, MARKER_PREFIX_LEN)) { + marker = &(param[MARKER_PREFIX_LEN]); + } + else if (!strncmp(param, DELIMITER_PREFIX, DELIMITER_PREFIX_LEN)) { + delimiter = &(param[DELIMITER_PREFIX_LEN]); + } + else if (!strncmp(param, MAXKEYS_PREFIX, MAXKEYS_PREFIX_LEN)) { + maxkeys = convertInt(&(param[MAXKEYS_PREFIX_LEN]), "maxkeys"); + } + else if (!strncmp(param, ALL_DETAILS_PREFIX, + ALL_DETAILS_PREFIX_LEN)) { + const char *ad = &(param[ALL_DETAILS_PREFIX_LEN]); + if (!strcmp(ad, "true") || !strcmp(ad, "TRUE") || + !strcmp(ad, "yes") || !strcmp(ad, "YES") || + !strcmp(ad, "1")) { + allDetails = 1; + } + } + else if (!bucketName) { + bucketName = param; + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + if (bucketName) { + list_bucket(bucketName, prefix, marker, delimiter, maxkeys, + allDetails); + } + else { + list_service(allDetails); + } } - + // delete object ------------------------------------------------------------- static void delete_object(int argc, char **argv, int optindex) { - (void) argc; - - // Split bucket/key - char *slash = argv[optindex]; - - // We know there is a slash in there, put_object is only called if so - while (*slash && (*slash != '/')) { - slash++; - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - 0, - &responseCompleteCallback - }; - - do { - S3_delete_object(&bucketContext, key, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if ((statusG != S3StatusOK) && - (statusG != S3StatusErrorPreconditionFailed)) { - printError(); - } - - S3_deinitialize(); + (void) argc; + + // Split bucket/key + char *slash = argv[optindex]; + + // We know there is a slash in there, put_object is only called if so + while (*slash && (*slash != '/')) { + slash++; + } + *slash++ = 0; + + const char *bucketName = argv[optindex++]; + const char *key = slash; + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3ResponseHandler responseHandler = + { + 0, + &responseCompleteCallback + }; + + do { + S3_delete_object(&bucketContext, key, 0, &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if ((statusG != S3StatusOK) && + (statusG != S3StatusErrorPreconditionFailed)) { + printError(); + } + + S3_deinitialize(); } @@ -1343,283 +1343,283 @@ static void delete_object(int argc, char **argv, int optindex) typedef struct put_object_callback_data { - FILE *infile; - growbuffer *gb; - uint64_t contentLength, originalContentLength; - int noStatus; + FILE *infile; + growbuffer *gb; + uint64_t contentLength, originalContentLength; + int noStatus; } put_object_callback_data; static int putObjectDataCallback(int bufferSize, char *buffer, - void *callbackData) + void *callbackData) { - put_object_callback_data *data = - (put_object_callback_data *) callbackData; - - int ret = 0; - - if (data->contentLength) { - int toRead = ((data->contentLength > (unsigned) bufferSize) ? - (unsigned) bufferSize : data->contentLength); - if (data->gb) { - growbuffer_read(&(data->gb), toRead, &ret, buffer); - } - else if (data->infile) { - ret = fread(buffer, 1, toRead, data->infile); - } - } - - data->contentLength -= ret; - - if (data->contentLength && !data->noStatus) { - // Avoid a weird bug in MingW, which won't print the second integer - // value properly when it's in the same call, so print separately - printf("%llu bytes remaining ", - (unsigned long long) data->contentLength); - printf("(%d%% complete) ...\n", - (int) (((data->originalContentLength - - data->contentLength) * 100) / - data->originalContentLength)); - } - - return ret; + put_object_callback_data *data = + (put_object_callback_data *) callbackData; + + int ret = 0; + + if (data->contentLength) { + int toRead = ((data->contentLength > (unsigned) bufferSize) ? + (unsigned) bufferSize : data->contentLength); + if (data->gb) { + growbuffer_read(&(data->gb), toRead, &ret, buffer); + } + else if (data->infile) { + ret = fread(buffer, 1, toRead, data->infile); + } + } + + data->contentLength -= ret; + + if (data->contentLength && !data->noStatus) { + // Avoid a weird bug in MingW, which won't print the second integer + // value properly when it's in the same call, so print separately + printf("%llu bytes remaining ", + (unsigned long long) data->contentLength); + printf("(%d%% complete) ...\n", + (int) (((data->originalContentLength - + data->contentLength) * 100) / + data->originalContentLength)); + } + + return ret; } static void put_object(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - char *slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - const char *filename = 0; - uint64_t contentLength = 0; - const char *cacheControl = 0, *contentType = 0, *md5 = 0; - const char *contentDispositionFilename = 0, *contentEncoding = 0; - int64_t expires = -1; - S3CannedAcl cannedAcl = S3CannedAclPrivate; - int metaPropertiesCount = 0; - S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; - int noStatus = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_LENGTH_PREFIX, - CONTENT_LENGTH_PREFIX_LEN)) { - contentLength = convertInt(&(param[CONTENT_LENGTH_PREFIX_LEN]), - "contentLength"); - if (contentLength > (5LL * 1024 * 1024 * 1024)) { - fprintf(stderr, "\nERROR: contentLength must be no greater " - "than 5 GB\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, CACHE_CONTROL_PREFIX, - CACHE_CONTROL_PREFIX_LEN)) { - cacheControl = &(param[CACHE_CONTROL_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_TYPE_PREFIX, - CONTENT_TYPE_PREFIX_LEN)) { - contentType = &(param[CONTENT_TYPE_PREFIX_LEN]); - } - else if (!strncmp(param, MD5_PREFIX, MD5_PREFIX_LEN)) { - md5 = &(param[MD5_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_DISPOSITION_FILENAME_PREFIX, - CONTENT_DISPOSITION_FILENAME_PREFIX_LEN)) { - contentDispositionFilename = - &(param[CONTENT_DISPOSITION_FILENAME_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_ENCODING_PREFIX, - CONTENT_ENCODING_PREFIX_LEN)) { - contentEncoding = &(param[CONTENT_ENCODING_PREFIX_LEN]); - } - else if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { - expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); - if (expires < 0) { - fprintf(stderr, "\nERROR: Invalid expires time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, X_AMZ_META_PREFIX, X_AMZ_META_PREFIX_LEN)) { - if (metaPropertiesCount == S3_MAX_METADATA_COUNT) { - fprintf(stderr, "\nERROR: Too many x-amz-meta- properties, " - "limit %lu: %s\n", - (unsigned long) S3_MAX_METADATA_COUNT, param); - usageExit(stderr); - } - char *name = &(param[X_AMZ_META_PREFIX_LEN]); - char *value = name; - while (*value && (*value != '=')) { - value++; - } - if (!*value || !*(value + 1)) { - fprintf(stderr, "\nERROR: Invalid parameter: %s\n", param); - usageExit(stderr); - } - *value++ = 0; - metaProperties[metaPropertiesCount].name = name; - metaProperties[metaPropertiesCount++].value = value; - } - else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { - char *val = &(param[CANNED_ACL_PREFIX_LEN]); - if (!strcmp(val, "private")) { - cannedAcl = S3CannedAclPrivate; - } - else if (!strcmp(val, "public-read")) { - cannedAcl = S3CannedAclPublicRead; - } - else if (!strcmp(val, "public-read-write")) { - cannedAcl = S3CannedAclPublicReadWrite; - } - else if (!strcmp(val, "authenticated-read")) { - cannedAcl = S3CannedAclAuthenticatedRead; - } - else { - fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); - usageExit(stderr); - } - } - else if (!strncmp(param, NO_STATUS_PREFIX, NO_STATUS_PREFIX_LEN)) { - const char *ns = &(param[NO_STATUS_PREFIX_LEN]); - if (!strcmp(ns, "true") || !strcmp(ns, "TRUE") || - !strcmp(ns, "yes") || !strcmp(ns, "YES") || - !strcmp(ns, "1")) { - noStatus = 1; - } - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - put_object_callback_data data; - - data.infile = 0; - data.gb = 0; - data.noStatus = noStatus; - - if (filename) { - if (!contentLength) { - struct stat statbuf; - // Stat the file to get its length - if (stat(filename, &statbuf) == -1) { - fprintf(stderr, "\nERROR: Failed to stat file %s: ", - filename); - perror(0); - exit(-1); - } - contentLength = statbuf.st_size; - } - // Open the file - if (!(data.infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { - fprintf(stderr, "\nERROR: Failed to open input file %s: ", - filename); - perror(0); - exit(-1); - } - } - else { - // Read from stdin. If contentLength is not provided, we have - // to read it all in to get contentLength. - if (!contentLength) { - // Read all if stdin to get the data - char buffer[64 * 1024]; - while (1) { - int amtRead = fread(buffer, 1, sizeof(buffer), stdin); - if (amtRead == 0) { - break; - } - if (!growbuffer_append(&(data.gb), buffer, amtRead)) { - fprintf(stderr, "\nERROR: Out of memory while reading " - "stdin\n"); - exit(-1); - } - contentLength += amtRead; - if (amtRead < (int) sizeof(buffer)) { - break; - } - } - } - else { - data.infile = stdin; - } - } - - data.contentLength = data.originalContentLength = contentLength; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3PutProperties putProperties = - { - contentType, - md5, - cacheControl, - contentDispositionFilename, - contentEncoding, - expires, - cannedAcl, - metaPropertiesCount, - metaProperties - }; - - S3PutObjectHandler putObjectHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &putObjectDataCallback - }; - - do { - S3_put_object(&bucketContext, key, contentLength, &putProperties, 0, - &putObjectHandler, &data); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (data.infile) { - fclose(data.infile); - } - else if (data.gb) { - growbuffer_destroy(data.gb); - } - - if (statusG != S3StatusOK) { - printError(); - } - else if (data.contentLength) { - fprintf(stderr, "\nERROR: Failed to read remaining %llu bytes from " - "input\n", (unsigned long long) data.contentLength); - } - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); + usageExit(stderr); + } + + // Split bucket/key + char *slash = argv[optindex]; + while (*slash && (*slash != '/')) { + slash++; + } + if (!*slash || !*(slash + 1)) { + fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", + argv[optindex]); + usageExit(stderr); + } + *slash++ = 0; + + const char *bucketName = argv[optindex++]; + const char *key = slash; + + const char *filename = 0; + uint64_t contentLength = 0; + const char *cacheControl = 0, *contentType = 0, *md5 = 0; + const char *contentDispositionFilename = 0, *contentEncoding = 0; + int64_t expires = -1; + S3CannedAcl cannedAcl = S3CannedAclPrivate; + int metaPropertiesCount = 0; + S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; + int noStatus = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { + filename = &(param[FILENAME_PREFIX_LEN]); + } + else if (!strncmp(param, CONTENT_LENGTH_PREFIX, + CONTENT_LENGTH_PREFIX_LEN)) { + contentLength = convertInt(&(param[CONTENT_LENGTH_PREFIX_LEN]), + "contentLength"); + if (contentLength > (5LL * 1024 * 1024 * 1024)) { + fprintf(stderr, "\nERROR: contentLength must be no greater " + "than 5 GB\n"); + usageExit(stderr); + } + } + else if (!strncmp(param, CACHE_CONTROL_PREFIX, + CACHE_CONTROL_PREFIX_LEN)) { + cacheControl = &(param[CACHE_CONTROL_PREFIX_LEN]); + } + else if (!strncmp(param, CONTENT_TYPE_PREFIX, + CONTENT_TYPE_PREFIX_LEN)) { + contentType = &(param[CONTENT_TYPE_PREFIX_LEN]); + } + else if (!strncmp(param, MD5_PREFIX, MD5_PREFIX_LEN)) { + md5 = &(param[MD5_PREFIX_LEN]); + } + else if (!strncmp(param, CONTENT_DISPOSITION_FILENAME_PREFIX, + CONTENT_DISPOSITION_FILENAME_PREFIX_LEN)) { + contentDispositionFilename = + &(param[CONTENT_DISPOSITION_FILENAME_PREFIX_LEN]); + } + else if (!strncmp(param, CONTENT_ENCODING_PREFIX, + CONTENT_ENCODING_PREFIX_LEN)) { + contentEncoding = &(param[CONTENT_ENCODING_PREFIX_LEN]); + } + else if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { + expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); + if (expires < 0) { + fprintf(stderr, "\nERROR: Invalid expires time " + "value; ISO 8601 time format required\n"); + usageExit(stderr); + } + } + else if (!strncmp(param, X_AMZ_META_PREFIX, X_AMZ_META_PREFIX_LEN)) { + if (metaPropertiesCount == S3_MAX_METADATA_COUNT) { + fprintf(stderr, "\nERROR: Too many x-amz-meta- properties, " + "limit %lu: %s\n", + (unsigned long) S3_MAX_METADATA_COUNT, param); + usageExit(stderr); + } + char *name = &(param[X_AMZ_META_PREFIX_LEN]); + char *value = name; + while (*value && (*value != '=')) { + value++; + } + if (!*value || !*(value + 1)) { + fprintf(stderr, "\nERROR: Invalid parameter: %s\n", param); + usageExit(stderr); + } + *value++ = 0; + metaProperties[metaPropertiesCount].name = name; + metaProperties[metaPropertiesCount++].value = value; + } + else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { + char *val = &(param[CANNED_ACL_PREFIX_LEN]); + if (!strcmp(val, "private")) { + cannedAcl = S3CannedAclPrivate; + } + else if (!strcmp(val, "public-read")) { + cannedAcl = S3CannedAclPublicRead; + } + else if (!strcmp(val, "public-read-write")) { + cannedAcl = S3CannedAclPublicReadWrite; + } + else if (!strcmp(val, "authenticated-read")) { + cannedAcl = S3CannedAclAuthenticatedRead; + } + else { + fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); + usageExit(stderr); + } + } + else if (!strncmp(param, NO_STATUS_PREFIX, NO_STATUS_PREFIX_LEN)) { + const char *ns = &(param[NO_STATUS_PREFIX_LEN]); + if (!strcmp(ns, "true") || !strcmp(ns, "TRUE") || + !strcmp(ns, "yes") || !strcmp(ns, "YES") || + !strcmp(ns, "1")) { + noStatus = 1; + } + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + put_object_callback_data data; + + data.infile = 0; + data.gb = 0; + data.noStatus = noStatus; + + if (filename) { + if (!contentLength) { + struct stat statbuf; + // Stat the file to get its length + if (stat(filename, &statbuf) == -1) { + fprintf(stderr, "\nERROR: Failed to stat file %s: ", + filename); + perror(0); + exit(-1); + } + contentLength = statbuf.st_size; + } + // Open the file + if (!(data.infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { + fprintf(stderr, "\nERROR: Failed to open input file %s: ", + filename); + perror(0); + exit(-1); + } + } + else { + // Read from stdin. If contentLength is not provided, we have + // to read it all in to get contentLength. + if (!contentLength) { + // Read all if stdin to get the data + char buffer[64 * 1024]; + while (1) { + int amtRead = fread(buffer, 1, sizeof(buffer), stdin); + if (amtRead == 0) { + break; + } + if (!growbuffer_append(&(data.gb), buffer, amtRead)) { + fprintf(stderr, "\nERROR: Out of memory while reading " + "stdin\n"); + exit(-1); + } + contentLength += amtRead; + if (amtRead < (int) sizeof(buffer)) { + break; + } + } + } + else { + data.infile = stdin; + } + } + + data.contentLength = data.originalContentLength = contentLength; + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3PutProperties putProperties = + { + contentType, + md5, + cacheControl, + contentDispositionFilename, + contentEncoding, + expires, + cannedAcl, + metaPropertiesCount, + metaProperties + }; + + S3PutObjectHandler putObjectHandler = + { + { &responsePropertiesCallback, &responseCompleteCallback }, + &putObjectDataCallback + }; + + do { + S3_put_object(&bucketContext, key, contentLength, &putProperties, 0, + &putObjectHandler, &data); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (data.infile) { + fclose(data.infile); + } + else if (data.gb) { + growbuffer_destroy(data.gb); + } + + if (statusG != S3StatusOK) { + printError(); + } + else if (data.contentLength) { + fprintf(stderr, "\nERROR: Failed to read remaining %llu bytes from " + "input\n", (unsigned long long) data.contentLength); + } + + S3_deinitialize(); } @@ -1627,355 +1627,355 @@ static void put_object(int argc, char **argv, int optindex) static void copy_object(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: source bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - char *slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid source bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *sourceBucketName = argv[optindex++]; - const char *sourceKey = slash; - - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: " - "destination bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid destination bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *destinationBucketName = argv[optindex++]; - const char *destinationKey = slash; - - const char *cacheControl = 0, *contentType = 0; - const char *contentDispositionFilename = 0, *contentEncoding = 0; - int64_t expires = -1; - S3CannedAcl cannedAcl = S3CannedAclPrivate; - int metaPropertiesCount = 0; - S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; - int anyPropertiesSet = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, CACHE_CONTROL_PREFIX, - CACHE_CONTROL_PREFIX_LEN)) { - cacheControl = &(param[CACHE_CONTROL_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, CONTENT_TYPE_PREFIX, - CONTENT_TYPE_PREFIX_LEN)) { - contentType = &(param[CONTENT_TYPE_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, CONTENT_DISPOSITION_FILENAME_PREFIX, - CONTENT_DISPOSITION_FILENAME_PREFIX_LEN)) { - contentDispositionFilename = - &(param[CONTENT_DISPOSITION_FILENAME_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, CONTENT_ENCODING_PREFIX, - CONTENT_ENCODING_PREFIX_LEN)) { - contentEncoding = &(param[CONTENT_ENCODING_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { - expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); - if (expires < 0) { - fprintf(stderr, "\nERROR: Invalid expires time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - anyPropertiesSet = 1; - } - else if (!strncmp(param, X_AMZ_META_PREFIX, X_AMZ_META_PREFIX_LEN)) { - if (metaPropertiesCount == S3_MAX_METADATA_COUNT) { - fprintf(stderr, "\nERROR: Too many x-amz-meta- properties, " - "limit %lu: %s\n", - (unsigned long) S3_MAX_METADATA_COUNT, param); - usageExit(stderr); - } - char *name = &(param[X_AMZ_META_PREFIX_LEN]); - char *value = name; - while (*value && (*value != '=')) { - value++; - } - if (!*value || !*(value + 1)) { - fprintf(stderr, "\nERROR: Invalid parameter: %s\n", param); - usageExit(stderr); - } - *value++ = 0; - metaProperties[metaPropertiesCount].name = name; - metaProperties[metaPropertiesCount++].value = value; - anyPropertiesSet = 1; - } - else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { - char *val = &(param[CANNED_ACL_PREFIX_LEN]); - if (!strcmp(val, "private")) { - cannedAcl = S3CannedAclPrivate; - } - else if (!strcmp(val, "public-read")) { - cannedAcl = S3CannedAclPublicRead; - } - else if (!strcmp(val, "public-read-write")) { - cannedAcl = S3CannedAclPublicReadWrite; - } - else if (!strcmp(val, "authenticated-read")) { - cannedAcl = S3CannedAclAuthenticatedRead; - } - else { - fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); - usageExit(stderr); - } - anyPropertiesSet = 1; - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - S3_init(); - - S3BucketContext bucketContext = - { - sourceBucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3PutProperties putProperties = - { - contentType, - 0, - cacheControl, - contentDispositionFilename, - contentEncoding, - expires, - cannedAcl, - metaPropertiesCount, - metaProperties - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - int64_t lastModified; - char eTag[256]; - - do { - S3_copy_object(&bucketContext, sourceKey, destinationBucketName, - destinationKey, anyPropertiesSet ? &putProperties : 0, - &lastModified, sizeof(eTag), eTag, 0, - &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - if (lastModified >= 0) { - char timebuf[256]; - time_t t = (time_t) lastModified; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&t)); - printf("Last-Modified: %s\n", timebuf); - } - if (eTag[0]) { - printf("ETag: %s\n", eTag); - } - } - else { - printError(); - } - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: source bucket/key\n"); + usageExit(stderr); + } + + // Split bucket/key + char *slash = argv[optindex]; + while (*slash && (*slash != '/')) { + slash++; + } + if (!*slash || !*(slash + 1)) { + fprintf(stderr, "\nERROR: Invalid source bucket/key name: %s\n", + argv[optindex]); + usageExit(stderr); + } + *slash++ = 0; + + const char *sourceBucketName = argv[optindex++]; + const char *sourceKey = slash; + + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: " + "destination bucket/key\n"); + usageExit(stderr); + } + + // Split bucket/key + slash = argv[optindex]; + while (*slash && (*slash != '/')) { + slash++; + } + if (!*slash || !*(slash + 1)) { + fprintf(stderr, "\nERROR: Invalid destination bucket/key name: %s\n", + argv[optindex]); + usageExit(stderr); + } + *slash++ = 0; + + const char *destinationBucketName = argv[optindex++]; + const char *destinationKey = slash; + + const char *cacheControl = 0, *contentType = 0; + const char *contentDispositionFilename = 0, *contentEncoding = 0; + int64_t expires = -1; + S3CannedAcl cannedAcl = S3CannedAclPrivate; + int metaPropertiesCount = 0; + S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; + int anyPropertiesSet = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, CACHE_CONTROL_PREFIX, + CACHE_CONTROL_PREFIX_LEN)) { + cacheControl = &(param[CACHE_CONTROL_PREFIX_LEN]); + anyPropertiesSet = 1; + } + else if (!strncmp(param, CONTENT_TYPE_PREFIX, + CONTENT_TYPE_PREFIX_LEN)) { + contentType = &(param[CONTENT_TYPE_PREFIX_LEN]); + anyPropertiesSet = 1; + } + else if (!strncmp(param, CONTENT_DISPOSITION_FILENAME_PREFIX, + CONTENT_DISPOSITION_FILENAME_PREFIX_LEN)) { + contentDispositionFilename = + &(param[CONTENT_DISPOSITION_FILENAME_PREFIX_LEN]); + anyPropertiesSet = 1; + } + else if (!strncmp(param, CONTENT_ENCODING_PREFIX, + CONTENT_ENCODING_PREFIX_LEN)) { + contentEncoding = &(param[CONTENT_ENCODING_PREFIX_LEN]); + anyPropertiesSet = 1; + } + else if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { + expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); + if (expires < 0) { + fprintf(stderr, "\nERROR: Invalid expires time " + "value; ISO 8601 time format required\n"); + usageExit(stderr); + } + anyPropertiesSet = 1; + } + else if (!strncmp(param, X_AMZ_META_PREFIX, X_AMZ_META_PREFIX_LEN)) { + if (metaPropertiesCount == S3_MAX_METADATA_COUNT) { + fprintf(stderr, "\nERROR: Too many x-amz-meta- properties, " + "limit %lu: %s\n", + (unsigned long) S3_MAX_METADATA_COUNT, param); + usageExit(stderr); + } + char *name = &(param[X_AMZ_META_PREFIX_LEN]); + char *value = name; + while (*value && (*value != '=')) { + value++; + } + if (!*value || !*(value + 1)) { + fprintf(stderr, "\nERROR: Invalid parameter: %s\n", param); + usageExit(stderr); + } + *value++ = 0; + metaProperties[metaPropertiesCount].name = name; + metaProperties[metaPropertiesCount++].value = value; + anyPropertiesSet = 1; + } + else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { + char *val = &(param[CANNED_ACL_PREFIX_LEN]); + if (!strcmp(val, "private")) { + cannedAcl = S3CannedAclPrivate; + } + else if (!strcmp(val, "public-read")) { + cannedAcl = S3CannedAclPublicRead; + } + else if (!strcmp(val, "public-read-write")) { + cannedAcl = S3CannedAclPublicReadWrite; + } + else if (!strcmp(val, "authenticated-read")) { + cannedAcl = S3CannedAclAuthenticatedRead; + } + else { + fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); + usageExit(stderr); + } + anyPropertiesSet = 1; + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + S3_init(); + + S3BucketContext bucketContext = + { + sourceBucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3PutProperties putProperties = + { + contentType, + 0, + cacheControl, + contentDispositionFilename, + contentEncoding, + expires, + cannedAcl, + metaPropertiesCount, + metaProperties + }; + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, + &responseCompleteCallback + }; + + int64_t lastModified; + char eTag[256]; + + do { + S3_copy_object(&bucketContext, sourceKey, destinationBucketName, + destinationKey, anyPropertiesSet ? &putProperties : 0, + &lastModified, sizeof(eTag), eTag, 0, + &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG == S3StatusOK) { + if (lastModified >= 0) { + char timebuf[256]; + time_t t = (time_t) lastModified; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", + gmtime(&t)); + printf("Last-Modified: %s\n", timebuf); + } + if (eTag[0]) { + printf("ETag: %s\n", eTag); + } + } + else { + printError(); + } + + S3_deinitialize(); } // get object ---------------------------------------------------------------- static S3Status getObjectDataCallback(int bufferSize, const char *buffer, - void *callbackData) + void *callbackData) { - FILE *outfile = (FILE *) callbackData; + FILE *outfile = (FILE *) callbackData; - size_t wrote = fwrite(buffer, 1, bufferSize, outfile); - - return ((wrote < (size_t) bufferSize) ? - S3StatusAbortedByCallback : S3StatusOK); + size_t wrote = fwrite(buffer, 1, bufferSize, outfile); + + return ((wrote < (size_t) bufferSize) ? + S3StatusAbortedByCallback : S3StatusOK); } static void get_object(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - char *slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - const char *filename = 0; - int64_t ifModifiedSince = -1, ifNotModifiedSince = -1; - const char *ifMatch = 0, *ifNotMatch = 0; - uint64_t startByte = 0, byteCount = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else if (!strncmp(param, IF_MODIFIED_SINCE_PREFIX, - IF_MODIFIED_SINCE_PREFIX_LEN)) { - // Parse ifModifiedSince - ifModifiedSince = parseIso8601Time - (&(param[IF_MODIFIED_SINCE_PREFIX_LEN])); - if (ifModifiedSince < 0) { - fprintf(stderr, "\nERROR: Invalid ifModifiedSince time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, IF_NOT_MODIFIED_SINCE_PREFIX, - IF_NOT_MODIFIED_SINCE_PREFIX_LEN)) { - // Parse ifModifiedSince - ifNotModifiedSince = parseIso8601Time - (&(param[IF_NOT_MODIFIED_SINCE_PREFIX_LEN])); - if (ifNotModifiedSince < 0) { - fprintf(stderr, "\nERROR: Invalid ifNotModifiedSince time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, IF_MATCH_PREFIX, IF_MATCH_PREFIX_LEN)) { - ifMatch = &(param[IF_MATCH_PREFIX_LEN]); - } - else if (!strncmp(param, IF_NOT_MATCH_PREFIX, - IF_NOT_MATCH_PREFIX_LEN)) { - ifNotMatch = &(param[IF_NOT_MATCH_PREFIX_LEN]); - } - else if (!strncmp(param, START_BYTE_PREFIX, START_BYTE_PREFIX_LEN)) { - startByte = convertInt - (&(param[START_BYTE_PREFIX_LEN]), "startByte"); - } - else if (!strncmp(param, BYTE_COUNT_PREFIX, BYTE_COUNT_PREFIX_LEN)) { - byteCount = convertInt - (&(param[BYTE_COUNT_PREFIX_LEN]), "byteCount"); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *outfile = 0; - - if (filename) { - // Stat the file, and if it doesn't exist, open it in w mode - struct stat buf; - if (stat(filename, &buf) == -1) { - outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); - } - else { - // Open in r+ so that we don't truncate the file, just in case - // there is an error and we write no bytes, we leave the file - // unmodified - outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); - } - - if (!outfile) { - fprintf(stderr, "\nERROR: Failed to open output file %s: ", - filename); - perror(0); - exit(-1); - } - } - else if (showResponsePropertiesG) { - fprintf(stderr, "\nERROR: get -s requires a filename parameter\n"); - usageExit(stderr); - } - else { - outfile = stdout; - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3GetConditions getConditions = - { - ifModifiedSince, - ifNotModifiedSince, - ifMatch, - ifNotMatch - }; - - S3GetObjectHandler getObjectHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &getObjectDataCallback - }; - - do { - S3_get_object(&bucketContext, key, &getConditions, startByte, - byteCount, 0, &getObjectHandler, outfile); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - if (outfile != stdout) { - ftruncate(fileno(outfile), ftell(outfile)); - } - } - else { - printError(); - } - - fclose(outfile); - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); + usageExit(stderr); + } + + // Split bucket/key + char *slash = argv[optindex]; + while (*slash && (*slash != '/')) { + slash++; + } + if (!*slash || !*(slash + 1)) { + fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", + argv[optindex]); + usageExit(stderr); + } + *slash++ = 0; + + const char *bucketName = argv[optindex++]; + const char *key = slash; + + const char *filename = 0; + int64_t ifModifiedSince = -1, ifNotModifiedSince = -1; + const char *ifMatch = 0, *ifNotMatch = 0; + uint64_t startByte = 0, byteCount = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { + filename = &(param[FILENAME_PREFIX_LEN]); + } + else if (!strncmp(param, IF_MODIFIED_SINCE_PREFIX, + IF_MODIFIED_SINCE_PREFIX_LEN)) { + // Parse ifModifiedSince + ifModifiedSince = parseIso8601Time + (&(param[IF_MODIFIED_SINCE_PREFIX_LEN])); + if (ifModifiedSince < 0) { + fprintf(stderr, "\nERROR: Invalid ifModifiedSince time " + "value; ISO 8601 time format required\n"); + usageExit(stderr); + } + } + else if (!strncmp(param, IF_NOT_MODIFIED_SINCE_PREFIX, + IF_NOT_MODIFIED_SINCE_PREFIX_LEN)) { + // Parse ifModifiedSince + ifNotModifiedSince = parseIso8601Time + (&(param[IF_NOT_MODIFIED_SINCE_PREFIX_LEN])); + if (ifNotModifiedSince < 0) { + fprintf(stderr, "\nERROR: Invalid ifNotModifiedSince time " + "value; ISO 8601 time format required\n"); + usageExit(stderr); + } + } + else if (!strncmp(param, IF_MATCH_PREFIX, IF_MATCH_PREFIX_LEN)) { + ifMatch = &(param[IF_MATCH_PREFIX_LEN]); + } + else if (!strncmp(param, IF_NOT_MATCH_PREFIX, + IF_NOT_MATCH_PREFIX_LEN)) { + ifNotMatch = &(param[IF_NOT_MATCH_PREFIX_LEN]); + } + else if (!strncmp(param, START_BYTE_PREFIX, START_BYTE_PREFIX_LEN)) { + startByte = convertInt + (&(param[START_BYTE_PREFIX_LEN]), "startByte"); + } + else if (!strncmp(param, BYTE_COUNT_PREFIX, BYTE_COUNT_PREFIX_LEN)) { + byteCount = convertInt + (&(param[BYTE_COUNT_PREFIX_LEN]), "byteCount"); + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + FILE *outfile = 0; + + if (filename) { + // Stat the file, and if it doesn't exist, open it in w mode + struct stat buf; + if (stat(filename, &buf) == -1) { + outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); + } + else { + // Open in r+ so that we don't truncate the file, just in case + // there is an error and we write no bytes, we leave the file + // unmodified + outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); + } + + if (!outfile) { + fprintf(stderr, "\nERROR: Failed to open output file %s: ", + filename); + perror(0); + exit(-1); + } + } + else if (showResponsePropertiesG) { + fprintf(stderr, "\nERROR: get -s requires a filename parameter\n"); + usageExit(stderr); + } + else { + outfile = stdout; + } + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3GetConditions getConditions = + { + ifModifiedSince, + ifNotModifiedSince, + ifMatch, + ifNotMatch + }; + + S3GetObjectHandler getObjectHandler = + { + { &responsePropertiesCallback, &responseCompleteCallback }, + &getObjectDataCallback + }; + + do { + S3_get_object(&bucketContext, key, &getConditions, startByte, + byteCount, 0, &getObjectHandler, outfile); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG == S3StatusOK) { + if (outfile != stdout) { + ftruncate(fileno(outfile), ftell(outfile)); + } + } + else { + printError(); + } + + fclose(outfile); + + S3_deinitialize(); } @@ -1983,62 +1983,62 @@ static void get_object(int argc, char **argv, int optindex) static void head_object(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); - usageExit(stderr); - } - - // Head implies showing response properties - showResponsePropertiesG = 1; - - // Split bucket/key - char *slash = argv[optindex]; - - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - if (optindex != argc) { - fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); - usageExit(stderr); - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_head_object(&bucketContext, key, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if ((statusG != S3StatusOK) && - (statusG != S3StatusErrorPreconditionFailed)) { - printError(); - } - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); + usageExit(stderr); + } + + // Head implies showing response properties + showResponsePropertiesG = 1; + + // Split bucket/key + char *slash = argv[optindex]; + + while (*slash && (*slash != '/')) { + slash++; + } + if (!*slash || !*(slash + 1)) { + fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", + argv[optindex]); + usageExit(stderr); + } + *slash++ = 0; + + const char *bucketName = argv[optindex++]; + const char *key = slash; + + if (optindex != argc) { + fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); + usageExit(stderr); + } + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, + &responseCompleteCallback + }; + + do { + S3_head_object(&bucketContext, key, 0, &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if ((statusG != S3StatusOK) && + (statusG != S3StatusErrorPreconditionFailed)) { + printError(); + } + + S3_deinitialize(); } @@ -2046,75 +2046,75 @@ static void head_object(int argc, char **argv, int optindex) static void generate_query_string(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex]; - const char *key = 0; - - // Split bucket/key - char *slash = argv[optindex++]; - while (*slash && (*slash != '/')) { - slash++; - } - if (*slash) { - *slash++ = 0; - key = slash; - } - else { - key = 0; - } - - int64_t expires = -1; - - const char *resource = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { - expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); - if (expires < 0) { - fprintf(stderr, "\nERROR: Invalid expires time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, RESOURCE_PREFIX, RESOURCE_PREFIX_LEN)) { - resource = &(param[RESOURCE_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - char buffer[S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE]; - - S3Status status = S3_generate_authenticated_query_string - (buffer, &bucketContext, key, expires, resource); - - if (status != S3StatusOK) { - printf("Failed to generate authenticated query string: %s\n", - S3_get_status_name(status)); - } - else { - printf("%s\n", buffer); - } - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); + usageExit(stderr); + } + + const char *bucketName = argv[optindex]; + const char *key = 0; + + // Split bucket/key + char *slash = argv[optindex++]; + while (*slash && (*slash != '/')) { + slash++; + } + if (*slash) { + *slash++ = 0; + key = slash; + } + else { + key = 0; + } + + int64_t expires = -1; + + const char *resource = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { + expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); + if (expires < 0) { + fprintf(stderr, "\nERROR: Invalid expires time " + "value; ISO 8601 time format required\n"); + usageExit(stderr); + } + } + else if (!strncmp(param, RESOURCE_PREFIX, RESOURCE_PREFIX_LEN)) { + resource = &(param[RESOURCE_PREFIX_LEN]); + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + char buffer[S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE]; + + S3Status status = S3_generate_authenticated_query_string + (buffer, &bucketContext, key, expires, resource); + + if (status != S3StatusOK) { + printf("Failed to generate authenticated query string: %s\n", + S3_get_status_name(status)); + } + else { + printf("%s\n", buffer); + } + + S3_deinitialize(); } @@ -2122,166 +2122,166 @@ static void generate_query_string(int argc, char **argv, int optindex) void get_acl(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex]; - const char *key = 0; - - // Split bucket/key - char *slash = argv[optindex++]; - while (*slash && (*slash != '/')) { - slash++; - } - if (*slash) { - *slash++ = 0; - key = slash; - } - else { - key = 0; - } - - const char *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *outfile = 0; - - if (filename) { - // Stat the file, and if it doesn't exist, open it in w mode - struct stat buf; - if (stat(filename, &buf) == -1) { - outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); - } - else { - // Open in r+ so that we don't truncate the file, just in case - // there is an error and we write no bytes, we leave the file - // unmodified - outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); - } - - if (!outfile) { - fprintf(stderr, "\nERROR: Failed to open output file %s: ", - filename); - perror(0); - exit(-1); - } - } - else if (showResponsePropertiesG) { - fprintf(stderr, "\nERROR: getacl -s requires a filename parameter\n"); - usageExit(stderr); - } - else { - outfile = stdout; - } - - int aclGrantCount; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_get_acl(&bucketContext, key, ownerId, ownerDisplayName, - &aclGrantCount, aclGrants, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - fprintf(outfile, "OwnerID %s %s\n", ownerId, ownerDisplayName); - fprintf(outfile, "%-6s %-90s %-12s\n", " Type", - " User Identifier", - " Permission"); - fprintf(outfile, "------ " - "------------------------------------------------------------" - "------------------------------ ------------\n"); - int i; - for (i = 0; i < aclGrantCount; i++) { - S3AclGrant *grant = &(aclGrants[i]); - const char *type; - char composedId[S3_MAX_GRANTEE_USER_ID_SIZE + - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE + 16]; - const char *id; - - switch (grant->granteeType) { - case S3GranteeTypeAmazonCustomerByEmail: - type = "Email"; - id = grant->grantee.amazonCustomerByEmail.emailAddress; - break; - case S3GranteeTypeCanonicalUser: - type = "UserID"; - snprintf(composedId, sizeof(composedId), - "%s (%s)", grant->grantee.canonicalUser.id, - grant->grantee.canonicalUser.displayName); - id = composedId; - break; - case S3GranteeTypeAllAwsUsers: - type = "Group"; - id = "Authenticated AWS Users"; - break; - case S3GranteeTypeAllUsers: - type = "Group"; - id = "All Users"; - break; - default: - type = "Group"; - id = "Log Delivery"; - break; - } - const char *perm; - switch (grant->permission) { - case S3PermissionRead: - perm = "READ"; - break; - case S3PermissionWrite: - perm = "WRITE"; - break; - case S3PermissionReadACP: - perm = "READ_ACP"; - break; - case S3PermissionWriteACP: - perm = "WRITE_ACP"; - break; - default: - perm = "FULL_CONTROL"; - break; - } - fprintf(outfile, "%-6s %-90s %-12s\n", type, id, perm); - } - } - else { - printError(); - } - - fclose(outfile); - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); + usageExit(stderr); + } + + const char *bucketName = argv[optindex]; + const char *key = 0; + + // Split bucket/key + char *slash = argv[optindex++]; + while (*slash && (*slash != '/')) { + slash++; + } + if (*slash) { + *slash++ = 0; + key = slash; + } + else { + key = 0; + } + + const char *filename = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { + filename = &(param[FILENAME_PREFIX_LEN]); + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + FILE *outfile = 0; + + if (filename) { + // Stat the file, and if it doesn't exist, open it in w mode + struct stat buf; + if (stat(filename, &buf) == -1) { + outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); + } + else { + // Open in r+ so that we don't truncate the file, just in case + // there is an error and we write no bytes, we leave the file + // unmodified + outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); + } + + if (!outfile) { + fprintf(stderr, "\nERROR: Failed to open output file %s: ", + filename); + perror(0); + exit(-1); + } + } + else if (showResponsePropertiesG) { + fprintf(stderr, "\nERROR: getacl -s requires a filename parameter\n"); + usageExit(stderr); + } + else { + outfile = stdout; + } + + int aclGrantCount; + S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; + char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; + char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, + &responseCompleteCallback + }; + + do { + S3_get_acl(&bucketContext, key, ownerId, ownerDisplayName, + &aclGrantCount, aclGrants, 0, &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG == S3StatusOK) { + fprintf(outfile, "OwnerID %s %s\n", ownerId, ownerDisplayName); + fprintf(outfile, "%-6s %-90s %-12s\n", " Type", + " User Identifier", + " Permission"); + fprintf(outfile, "------ " + "------------------------------------------------------------" + "------------------------------ ------------\n"); + int i; + for (i = 0; i < aclGrantCount; i++) { + S3AclGrant *grant = &(aclGrants[i]); + const char *type; + char composedId[S3_MAX_GRANTEE_USER_ID_SIZE + + S3_MAX_GRANTEE_DISPLAY_NAME_SIZE + 16]; + const char *id; + + switch (grant->granteeType) { + case S3GranteeTypeAmazonCustomerByEmail: + type = "Email"; + id = grant->grantee.amazonCustomerByEmail.emailAddress; + break; + case S3GranteeTypeCanonicalUser: + type = "UserID"; + snprintf(composedId, sizeof(composedId), + "%s (%s)", grant->grantee.canonicalUser.id, + grant->grantee.canonicalUser.displayName); + id = composedId; + break; + case S3GranteeTypeAllAwsUsers: + type = "Group"; + id = "Authenticated AWS Users"; + break; + case S3GranteeTypeAllUsers: + type = "Group"; + id = "All Users"; + break; + default: + type = "Group"; + id = "Log Delivery"; + break; + } + const char *perm; + switch (grant->permission) { + case S3PermissionRead: + perm = "READ"; + break; + case S3PermissionWrite: + perm = "WRITE"; + break; + case S3PermissionReadACP: + perm = "READ_ACP"; + break; + case S3PermissionWriteACP: + perm = "WRITE_ACP"; + break; + default: + perm = "FULL_CONTROL"; + break; + } + fprintf(outfile, "%-6s %-90s %-12s\n", type, id, perm); + } + } + else { + printError(); + } + + fclose(outfile); + + S3_deinitialize(); } @@ -2289,99 +2289,99 @@ void get_acl(int argc, char **argv, int optindex) void set_acl(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex]; - const char *key = 0; - - // Split bucket/key - char *slash = argv[optindex++]; - while (*slash && (*slash != '/')) { - slash++; - } - if (*slash) { - *slash++ = 0; - key = slash; - } - else { - key = 0; - } - - const char *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *infile; - - if (filename) { - if (!(infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { - fprintf(stderr, "\nERROR: Failed to open input file %s: ", - filename); - perror(0); - exit(-1); - } - } - else { - infile = stdin; - } - - // Read in the complete ACL - char aclBuf[65536]; - aclBuf[fread(aclBuf, 1, sizeof(aclBuf), infile)] = 0; - char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; - - // Parse it - int aclGrantCount; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - if (!convert_simple_acl(aclBuf, ownerId, ownerDisplayName, - &aclGrantCount, aclGrants)) { - fprintf(stderr, "\nERROR: Failed to parse ACLs\n"); - fclose(infile); - exit(-1); - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_set_acl(&bucketContext, key, ownerId, ownerDisplayName, - aclGrantCount, aclGrants, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG != S3StatusOK) { - printError(); - } - - fclose(infile); - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); + usageExit(stderr); + } + + const char *bucketName = argv[optindex]; + const char *key = 0; + + // Split bucket/key + char *slash = argv[optindex++]; + while (*slash && (*slash != '/')) { + slash++; + } + if (*slash) { + *slash++ = 0; + key = slash; + } + else { + key = 0; + } + + const char *filename = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { + filename = &(param[FILENAME_PREFIX_LEN]); + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + FILE *infile; + + if (filename) { + if (!(infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { + fprintf(stderr, "\nERROR: Failed to open input file %s: ", + filename); + perror(0); + exit(-1); + } + } + else { + infile = stdin; + } + + // Read in the complete ACL + char aclBuf[65536]; + aclBuf[fread(aclBuf, 1, sizeof(aclBuf), infile)] = 0; + char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; + char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; + + // Parse it + int aclGrantCount; + S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; + if (!convert_simple_acl(aclBuf, ownerId, ownerDisplayName, + &aclGrantCount, aclGrants)) { + fprintf(stderr, "\nERROR: Failed to parse ACLs\n"); + fclose(infile); + exit(-1); + } + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, + &responseCompleteCallback + }; + + do { + S3_set_acl(&bucketContext, key, ownerId, ownerDisplayName, + aclGrantCount, aclGrants, 0, &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG != S3StatusOK) { + printError(); + } + + fclose(infile); + + S3_deinitialize(); } @@ -2389,157 +2389,157 @@ void set_acl(int argc, char **argv, int optindex) void get_logging(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - const char *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *outfile = 0; - - if (filename) { - // Stat the file, and if it doesn't exist, open it in w mode - struct stat buf; - if (stat(filename, &buf) == -1) { - outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); - } - else { - // Open in r+ so that we don't truncate the file, just in case - // there is an error and we write no bytes, we leave the file - // unmodified - outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); - } - - if (!outfile) { - fprintf(stderr, "\nERROR: Failed to open output file %s: ", - filename); - perror(0); - exit(-1); - } - } - else if (showResponsePropertiesG) { - fprintf(stderr, "\nERROR: getlogging -s requires a filename " - "parameter\n"); - usageExit(stderr); - } - else { - outfile = stdout; - } - - int aclGrantCount; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - char targetBucket[S3_MAX_BUCKET_NAME_SIZE]; - char targetPrefix[S3_MAX_KEY_SIZE]; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_get_server_access_logging(&bucketContext, targetBucket, targetPrefix, - &aclGrantCount, aclGrants, 0, - &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - if (targetBucket[0]) { - printf("Target Bucket: %s\n", targetBucket); - if (targetPrefix[0]) { - printf("Target Prefix: %s\n", targetPrefix); - } - fprintf(outfile, "%-6s %-90s %-12s\n", " Type", - " User Identifier", - " Permission"); - fprintf(outfile, "------ " - "---------------------------------------------------------" - "--------------------------------- ------------\n"); - int i; - for (i = 0; i < aclGrantCount; i++) { - S3AclGrant *grant = &(aclGrants[i]); - const char *type; - char composedId[S3_MAX_GRANTEE_USER_ID_SIZE + - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE + 16]; - const char *id; - - switch (grant->granteeType) { - case S3GranteeTypeAmazonCustomerByEmail: - type = "Email"; - id = grant->grantee.amazonCustomerByEmail.emailAddress; - break; - case S3GranteeTypeCanonicalUser: - type = "UserID"; - snprintf(composedId, sizeof(composedId), - "%s (%s)", grant->grantee.canonicalUser.id, - grant->grantee.canonicalUser.displayName); - id = composedId; - break; - case S3GranteeTypeAllAwsUsers: - type = "Group"; - id = "Authenticated AWS Users"; - break; - default: - type = "Group"; - id = "All Users"; - break; - } - const char *perm; - switch (grant->permission) { - case S3PermissionRead: - perm = "READ"; - break; - case S3PermissionWrite: - perm = "WRITE"; - break; - case S3PermissionReadACP: - perm = "READ_ACP"; - break; - case S3PermissionWriteACP: - perm = "WRITE_ACP"; - break; - default: - perm = "FULL_CONTROL"; - break; - } - fprintf(outfile, "%-6s %-90s %-12s\n", type, id, perm); - } - } - else { - printf("Service logging is not enabled for this bucket.\n"); - } - } - else { - printError(); - } - - fclose(outfile); - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); + usageExit(stderr); + } + + const char *bucketName = argv[optindex++]; + const char *filename = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { + filename = &(param[FILENAME_PREFIX_LEN]); + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + FILE *outfile = 0; + + if (filename) { + // Stat the file, and if it doesn't exist, open it in w mode + struct stat buf; + if (stat(filename, &buf) == -1) { + outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); + } + else { + // Open in r+ so that we don't truncate the file, just in case + // there is an error and we write no bytes, we leave the file + // unmodified + outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); + } + + if (!outfile) { + fprintf(stderr, "\nERROR: Failed to open output file %s: ", + filename); + perror(0); + exit(-1); + } + } + else if (showResponsePropertiesG) { + fprintf(stderr, "\nERROR: getlogging -s requires a filename " + "parameter\n"); + usageExit(stderr); + } + else { + outfile = stdout; + } + + int aclGrantCount; + S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; + char targetBucket[S3_MAX_BUCKET_NAME_SIZE]; + char targetPrefix[S3_MAX_KEY_SIZE]; + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, + &responseCompleteCallback + }; + + do { + S3_get_server_access_logging(&bucketContext, targetBucket, targetPrefix, + &aclGrantCount, aclGrants, 0, + &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG == S3StatusOK) { + if (targetBucket[0]) { + printf("Target Bucket: %s\n", targetBucket); + if (targetPrefix[0]) { + printf("Target Prefix: %s\n", targetPrefix); + } + fprintf(outfile, "%-6s %-90s %-12s\n", " Type", + " User Identifier", + " Permission"); + fprintf(outfile, "------ " + "---------------------------------------------------------" + "--------------------------------- ------------\n"); + int i; + for (i = 0; i < aclGrantCount; i++) { + S3AclGrant *grant = &(aclGrants[i]); + const char *type; + char composedId[S3_MAX_GRANTEE_USER_ID_SIZE + + S3_MAX_GRANTEE_DISPLAY_NAME_SIZE + 16]; + const char *id; + + switch (grant->granteeType) { + case S3GranteeTypeAmazonCustomerByEmail: + type = "Email"; + id = grant->grantee.amazonCustomerByEmail.emailAddress; + break; + case S3GranteeTypeCanonicalUser: + type = "UserID"; + snprintf(composedId, sizeof(composedId), + "%s (%s)", grant->grantee.canonicalUser.id, + grant->grantee.canonicalUser.displayName); + id = composedId; + break; + case S3GranteeTypeAllAwsUsers: + type = "Group"; + id = "Authenticated AWS Users"; + break; + default: + type = "Group"; + id = "All Users"; + break; + } + const char *perm; + switch (grant->permission) { + case S3PermissionRead: + perm = "READ"; + break; + case S3PermissionWrite: + perm = "WRITE"; + break; + case S3PermissionReadACP: + perm = "READ_ACP"; + break; + case S3PermissionWriteACP: + perm = "WRITE_ACP"; + break; + default: + perm = "FULL_CONTROL"; + break; + } + fprintf(outfile, "%-6s %-90s %-12s\n", type, id, perm); + } + } + else { + printf("Service logging is not enabled for this bucket.\n"); + } + } + else { + printError(); + } + + fclose(outfile); + + S3_deinitialize(); } @@ -2547,96 +2547,96 @@ void get_logging(int argc, char **argv, int optindex) void set_logging(int argc, char **argv, int optindex) { - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - - const char *targetBucket = 0, *targetPrefix = 0, *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, TARGET_BUCKET_PREFIX, TARGET_BUCKET_PREFIX_LEN)) { - targetBucket = &(param[TARGET_BUCKET_PREFIX_LEN]); - } - else if (!strncmp(param, TARGET_PREFIX_PREFIX, - TARGET_PREFIX_PREFIX_LEN)) { - targetPrefix = &(param[TARGET_PREFIX_PREFIX_LEN]); - } - else if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - int aclGrantCount = 0; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - - if (targetBucket) { - FILE *infile; - - if (filename) { - if (!(infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { - fprintf(stderr, "\nERROR: Failed to open input file %s: ", - filename); - perror(0); - exit(-1); - } - } - else { - infile = stdin; - } - - // Read in the complete ACL - char aclBuf[65536]; - aclBuf[fread(aclBuf, 1, sizeof(aclBuf), infile)] = 0; - char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; - - // Parse it - if (!convert_simple_acl(aclBuf, ownerId, ownerDisplayName, - &aclGrantCount, aclGrants)) { - fprintf(stderr, "\nERROR: Failed to parse ACLs\n"); - fclose(infile); - exit(-1); - } - - fclose(infile); - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_set_server_access_logging(&bucketContext, targetBucket, - targetPrefix, aclGrantCount, aclGrants, - 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG != S3StatusOK) { - printError(); - } - - S3_deinitialize(); + if (optindex == argc) { + fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); + usageExit(stderr); + } + + const char *bucketName = argv[optindex++]; + + const char *targetBucket = 0, *targetPrefix = 0, *filename = 0; + + while (optindex < argc) { + char *param = argv[optindex++]; + if (!strncmp(param, TARGET_BUCKET_PREFIX, TARGET_BUCKET_PREFIX_LEN)) { + targetBucket = &(param[TARGET_BUCKET_PREFIX_LEN]); + } + else if (!strncmp(param, TARGET_PREFIX_PREFIX, + TARGET_PREFIX_PREFIX_LEN)) { + targetPrefix = &(param[TARGET_PREFIX_PREFIX_LEN]); + } + else if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { + filename = &(param[FILENAME_PREFIX_LEN]); + } + else { + fprintf(stderr, "\nERROR: Unknown param: %s\n", param); + usageExit(stderr); + } + } + + int aclGrantCount = 0; + S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; + + if (targetBucket) { + FILE *infile; + + if (filename) { + if (!(infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { + fprintf(stderr, "\nERROR: Failed to open input file %s: ", + filename); + perror(0); + exit(-1); + } + } + else { + infile = stdin; + } + + // Read in the complete ACL + char aclBuf[65536]; + aclBuf[fread(aclBuf, 1, sizeof(aclBuf), infile)] = 0; + char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; + char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; + + // Parse it + if (!convert_simple_acl(aclBuf, ownerId, ownerDisplayName, + &aclGrantCount, aclGrants)) { + fprintf(stderr, "\nERROR: Failed to parse ACLs\n"); + fclose(infile); + exit(-1); + } + + fclose(infile); + } + + S3_init(); + + S3BucketContext bucketContext = + { + bucketName, + protocolG, + uriStyleG, + accessKeyIdG, + secretAccessKeyG + }; + + S3ResponseHandler responseHandler = + { + &responsePropertiesCallback, + &responseCompleteCallback + }; + + do { + S3_set_server_access_logging(&bucketContext, targetBucket, + targetPrefix, aclGrantCount, aclGrants, + 0, &responseHandler, 0); + } while (S3_status_is_retryable(statusG) && should_retry()); + + if (statusG != S3StatusOK) { + printError(); + } + + S3_deinitialize(); } @@ -2644,132 +2644,132 @@ void set_logging(int argc, char **argv, int optindex) int main(int argc, char **argv) { - // Parse args - while (1) { - int idx = 0; - int c = getopt_long(argc, argv, "fhusr:", longOptionsG, &idx); - - if (c == -1) { - // End of options - break; - } - - switch (c) { - case 'f': - forceG = 1; - break; - case 'h': - uriStyleG = S3UriStyleVirtualHost; - break; - case 'u': - protocolG = S3ProtocolHTTP; - break; - case 's': - showResponsePropertiesG = 1; - break; - case 'r': { - const char *v = optarg; - while (*v) { - retriesG *= 10; - retriesG += *v - '0'; - v++; - } - break; - } - default: - fprintf(stderr, "\nERROR: Unknown option: -%c\n", c); - // Usage exit - usageExit(stderr); - } - } - - // The first non-option argument gives the operation to perform - if (optind == argc) { - fprintf(stderr, "\n\nERROR: Missing argument: command\n\n"); - usageExit(stderr); - } - - const char *command = argv[optind++]; - - if (!strcmp(command, "help")) { - fprintf(stdout, "\ns3 is a program for performing single requests " - "to Amazon S3.\n"); - usageExit(stdout); - } - - accessKeyIdG = getenv("S3_ACCESS_KEY_ID"); - if (!accessKeyIdG) { - fprintf(stderr, "Missing environment variable: S3_ACCESS_KEY_ID\n"); - return -1; - } - secretAccessKeyG = getenv("S3_SECRET_ACCESS_KEY"); - if (!secretAccessKeyG) { - fprintf(stderr, - "Missing environment variable: S3_SECRET_ACCESS_KEY\n"); - return -1; - } - - if (!strcmp(command, "list")) { - list(argc, argv, optind); - } - else if (!strcmp(command, "test")) { - test_bucket(argc, argv, optind); - } - else if (!strcmp(command, "create")) { - create_bucket(argc, argv, optind); - } - else if (!strcmp(command, "delete")) { - if (optind == argc) { - fprintf(stderr, - "\nERROR: Missing parameter: bucket or bucket/key\n"); - usageExit(stderr); - } - char *val = argv[optind]; - int hasSlash = 0; - while (*val) { - if (*val++ == '/') { - hasSlash = 1; - break; - } - } - if (hasSlash) { - delete_object(argc, argv, optind); - } - else { - delete_bucket(argc, argv, optind); - } - } - else if (!strcmp(command, "put")) { - put_object(argc, argv, optind); - } - else if (!strcmp(command, "copy")) { - copy_object(argc, argv, optind); - } - else if (!strcmp(command, "get")) { - get_object(argc, argv, optind); - } - else if (!strcmp(command, "head")) { - head_object(argc, argv, optind); - } - else if (!strcmp(command, "gqs")) { - generate_query_string(argc, argv, optind); - } - else if (!strcmp(command, "getacl")) { - get_acl(argc, argv, optind); - } - else if (!strcmp(command, "setacl")) { - set_acl(argc, argv, optind); - } - else if (!strcmp(command, "getlogging")) { - get_logging(argc, argv, optind); - } - else if (!strcmp(command, "setlogging")) { - set_logging(argc, argv, optind); - } - else { - fprintf(stderr, "Unknown command: %s\n", command); - return -1; - } - - return 0; + // Parse args + while (1) { + int idx = 0; + int c = getopt_long(argc, argv, "fhusr:", longOptionsG, &idx); + + if (c == -1) { + // End of options + break; + } + + switch (c) { + case 'f': + forceG = 1; + break; + case 'h': + uriStyleG = S3UriStyleVirtualHost; + break; + case 'u': + protocolG = S3ProtocolHTTP; + break; + case 's': + showResponsePropertiesG = 1; + break; + case 'r': { + const char *v = optarg; + while (*v) { + retriesG *= 10; + retriesG += *v - '0'; + v++; + } + break; + } + default: + fprintf(stderr, "\nERROR: Unknown option: -%c\n", c); + // Usage exit + usageExit(stderr); + } + } + + // The first non-option argument gives the operation to perform + if (optind == argc) { + fprintf(stderr, "\n\nERROR: Missing argument: command\n\n"); + usageExit(stderr); + } + + const char *command = argv[optind++]; + + if (!strcmp(command, "help")) { + fprintf(stdout, "\ns3 is a program for performing single requests " + "to Amazon S3.\n"); + usageExit(stdout); + } + + accessKeyIdG = getenv("S3_ACCESS_KEY_ID"); + if (!accessKeyIdG) { + fprintf(stderr, "Missing environment variable: S3_ACCESS_KEY_ID\n"); + return -1; + } + secretAccessKeyG = getenv("S3_SECRET_ACCESS_KEY"); + if (!secretAccessKeyG) { + fprintf(stderr, + "Missing environment variable: S3_SECRET_ACCESS_KEY\n"); + return -1; + } + + if (!strcmp(command, "list")) { + list(argc, argv, optind); + } + else if (!strcmp(command, "test")) { + test_bucket(argc, argv, optind); + } + else if (!strcmp(command, "create")) { + create_bucket(argc, argv, optind); + } + else if (!strcmp(command, "delete")) { + if (optind == argc) { + fprintf(stderr, + "\nERROR: Missing parameter: bucket or bucket/key\n"); + usageExit(stderr); + } + char *val = argv[optind]; + int hasSlash = 0; + while (*val) { + if (*val++ == '/') { + hasSlash = 1; + break; + } + } + if (hasSlash) { + delete_object(argc, argv, optind); + } + else { + delete_bucket(argc, argv, optind); + } + } + else if (!strcmp(command, "put")) { + put_object(argc, argv, optind); + } + else if (!strcmp(command, "copy")) { + copy_object(argc, argv, optind); + } + else if (!strcmp(command, "get")) { + get_object(argc, argv, optind); + } + else if (!strcmp(command, "head")) { + head_object(argc, argv, optind); + } + else if (!strcmp(command, "gqs")) { + generate_query_string(argc, argv, optind); + } + else if (!strcmp(command, "getacl")) { + get_acl(argc, argv, optind); + } + else if (!strcmp(command, "setacl")) { + set_acl(argc, argv, optind); + } + else if (!strcmp(command, "getlogging")) { + get_logging(argc, argv, optind); + } + else if (!strcmp(command, "setlogging")) { + set_logging(argc, argv, optind); + } + else { + fprintf(stderr, "Unknown command: %s\n", command); + return -1; + } + + return 0; } |