struct link * s3_send_message(struct s3_message *mesg, struct link *server, time_t stoptime) { char *message_text; char address[16]; int message_length, data_sent; if(!server) { if(!domain_name_cache_lookup(s3_endpoint, address)) return NULL; server = link_connect(address, 80, stoptime); } if(!server) return NULL; message_length = s3_message_to_string(mesg, &message_text); if(message_length <= 0) { link_close(server); return NULL; } data_sent = link_write(server, message_text, message_length, stoptime); debug(D_TCP, "S3 Message Sent:\n%s\n", message_text); free(message_text); if(data_sent < message_length) { link_close(server); server = NULL; } return server; }
int s3_mk_bucket(char* bucketname, enum amz_base_perm perms, const char* access_key_id, const char* access_key) { struct link* server; char path[] = "/"; struct s3_header_object *head; time_t stoptime = time(0)+s3_timeout; struct s3_message mesg; char response[HEADER_LINE_MAX]; if(!access_key_id || !access_key || !s3_endpoint) return -1; mesg.type = S3_MESG_PUT; mesg.path = path; mesg.bucket = bucketname; mesg.content_length = 0; mesg.content_type = NULL; mesg.content_md5 = NULL; mesg.date = time(0); mesg.expect = 0; switch(perms) { case AMZ_PERM_PRIVATE: head = s3_new_header_object(S3_HEADER_AMZ_ACL, NULL, "private"); break; case AMZ_PERM_PUBLIC_READ: head = s3_new_header_object(S3_HEADER_AMZ_ACL, NULL, "public-read"); break; case AMZ_PERM_PUBLIC_WRITE: head = s3_new_header_object(S3_HEADER_AMZ_ACL, NULL, "public-read-write"); break; case AMZ_PERM_AUTH_READ: head = s3_new_header_object(S3_HEADER_AMZ_ACL, NULL, "authenticated-read"); break; case AMZ_PERM_BUCKET_READ: head = s3_new_header_object(S3_HEADER_AMZ_ACL, NULL, "bucket-owner-read"); break; case AMZ_PERM_BUCKET_FULL: head = s3_new_header_object(S3_HEADER_AMZ_ACL, NULL, "bucket-owner-full-control"); break; default: return -1; } mesg.amz_headers = list_create(); list_push_tail(mesg.amz_headers, head); sign_message(&mesg, access_key_id, access_key); server = s3_send_message(&mesg, NULL, stoptime); list_free(mesg.amz_headers); list_delete(mesg.amz_headers); if(!server) return -1; link_readline(server, response, HEADER_LINE_MAX, stoptime); if(strcmp(response, "HTTP/1.1 200 OK")) { // Error: transfer failed; close connection and return failure //fprintf(stderr, "Error: create bucket failed\nResponse: %s\n", response); link_close(server); return -1; } do { if(!strcmp(response, "Server: AmazonS3")) break; } while(link_readline(server, response, HEADER_LINE_MAX, stoptime)); link_close(server); return 0; }
struct link *link_accept(struct link *master, time_t stoptime) { struct link *link = 0; link = link_create(); if(!link) goto failure; while(1) { if(!link_sleep(master, stoptime, 1, 0)) goto failure; link->fd = accept(master->fd, 0, 0); break; } if(!link_nonblocking(link, 1)) goto failure; if(!link_address_remote(link, link->raddr, &link->rport)) goto failure; link_squelch(); debug(D_TCP, "got connection from %s:%d", link->raddr, link->rport); return link; failure: if(link) link_close(link); return 0; }
int main(int argc, char **argv) { int e; if( argc < 3 ) error("usage: sarun link bootfile"); link = atoi(argv[1]); /* open the link for raw I/O */ if( !link_open(link) ) error("failed to open link %d",link); /* boot the program through it */ if( (e=link_boot(link,argv[2]))!=0 ) error("link_boot error %d",e); /* now spool stdin into the link and */ /* anything from the link to stdout */ InitSemaphore(&sync,0); Fork(2000,input,4,link); Fork(2000,output,4,link); Wait(&sync); Wait(&sync); if( !link_close(link) ) error("failed to close link %d",link); }
INT64_T http_fetch_to_file(const char *url, const char *filename, time_t stoptime) { FILE *file; INT64_T size; INT64_T actual; struct link *link; file = fopen(filename, "w"); if(file) { link = http_query_size(url, "GET", &size, stoptime, 1); if(link) { actual = link_stream_to_file(link, file, size, stoptime); link_close(link); fclose(file); if(actual == size) { return actual; } else { unlink(filename); return -1; } } else { fclose(file); return -1; } } else { return -1; } }
int Periph::close(){ int ret = 0; if ( fd[port_] != -1 ){ //see if the port is already closed ret = link_close(this->handle, fd[port_]); fd[port_] = -1; } return ret; }
struct link *link_serve_address(const char *addr, int port) { struct link *link = 0; struct sockaddr_in address; int success; int value; link = link_create(); if(!link) goto failure; link->fd = socket(AF_INET, SOCK_STREAM, 0); if(link->fd < 0) goto failure; value = 1; setsockopt(link->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &value, sizeof(value)); link_window_configure(link); if(addr != 0 || port != LINK_PORT_ANY) { memset(&address, 0, sizeof(address)); #if defined(CCTOOLS_OPSYS_DARWIN) address.sin_len = sizeof(address); #endif address.sin_family = AF_INET; address.sin_port = htons(port); if(addr) { string_to_ip_address(addr, (unsigned char *) &address.sin_addr.s_addr); } else { address.sin_addr.s_addr = htonl(INADDR_ANY); } success = bind(link->fd, (struct sockaddr *) &address, sizeof(address)); if(success < 0) goto failure; } success = listen(link->fd, 5); if(success < 0) goto failure; if(!link_nonblocking(link, 1)) goto failure; debug(D_TCP, "listening on port %d", port); return link; failure: if(link) link_close(link); return 0; }
struct link *link_attach_to_fd(int fd) { struct link *l = link_create(); if(fd < 0) { link_close(l); return NULL; } l->fd = fd; l->type = LINK_TYPE_FILE; return l; }
int s3_rm_bucket(char* bucketname, const char* access_key_id, const char* access_key) { struct s3_message mesg; struct link* server; time_t stoptime = time(0)+s3_timeout; char response[HEADER_LINE_MAX]; char path[] = "/"; if(!access_key_id || !access_key || !s3_endpoint) return -1; mesg.type = S3_MESG_DELETE; mesg.path = path; mesg.bucket = bucketname; mesg.content_type = NULL; mesg.content_md5 = NULL; mesg.content_length = 0; mesg.date = time(0); mesg.expect = 0; mesg.amz_headers = NULL; sign_message(&mesg, access_key_id, access_key); server = s3_send_message(&mesg, NULL, stoptime); if(!server) return -1; link_readline(server, response, HEADER_LINE_MAX, stoptime); if(strcmp(response, "HTTP/1.1 204 No Content")) { // Error: transfer failed; close connection and return failure //fprintf(stderr, "Error: delete bucket failed\nResponse: %s\n", response); link_close(server); return -1; } do { if(!strcmp(response, "Server: AmazonS3")) break; } while(link_readline(server, response, HEADER_LINE_MAX, stoptime)); link_close(server); return 0; }
static int error(char *f,...) { va_list a; va_start(a,f); vfprintf(stderr,f,a); putc( '\n', stderr ); if( link != -1 ) link_close(link); exit(1); }
static int catalog_update_tcp( const char *host, const char *address, int port, const char *text ) { debug(D_DEBUG, "sending update via tcp to %s(%s):%d", host, address, port); time_t stoptime = time(0) + 15; struct link *l = link_connect(address,port,stoptime); if(!l) { debug(D_DEBUG, "failed to connect to %s(%s):%d: %s",host,address,port,strerror(errno)); return 0; } link_write(l,text,strlen(text),stoptime); link_close(l); return 1; }
int son_phy_close(son_phy_t * phy){ if( phy->message ){ return phy_close_message(phy); } if( phy->driver == 0 ){ int ret; ret = fclose(phy->f); phy->f = 0; return ret; } else { #if defined __link return link_close(phy->driver, phy->fd); #else return -1; #endif } }
struct link *link_attach(int fd) { struct link *l = link_create(); if(!l) return 0; l->fd = fd; if(link_address_remote(l, l->raddr, &l->rport)) { debug(D_TCP, "attached to %s:%d", l->raddr, l->rport); return l; } else { l->fd = -1; link_close(l); return 0; } }
/* * get_hardware_address -- Get the Ethernet MAC address associated * with the given device. * Inputs: * * if_name The name of the network interface * hw_address (output) the Ethernet MAC address * * Returns: * * None */ void get_hardware_address(const char *if_name, unsigned char hw_address[]) { union DL_primitives *dlp; unsigned char buf[MAXDLBUF]; link_t *handle; handle = link_open(if_name); dlp = (union DL_primitives*) buf; dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ; dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR; if (dlpi_msg(handle->fd, dlp, DL_PHYS_ADDR_REQ_SIZE, 0, DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE, sizeof(buf)) < 0) { err_msg("dlpi_msg failed"); } link_close(handle); memcpy(hw_address, buf + dlp->physaddr_ack.dl_addr_offset, ETH_ALEN); }
void mpi_queue_delete(struct mpi_queue *q) { if(q) { UINT64_T key; void *value; list_free(q->ready_list); list_delete(q->ready_list); list_free(q->complete_list); list_delete(q->complete_list); itable_firstkey(q->active_list); while(itable_nextkey(q->active_list, &key, &value)) { free(value); itable_remove(q->active_list, key); } itable_delete(q->active_list); link_close(q->master_link); free(q); } }
void handle_tcp_update( struct link *update_port ) { char data[TCP_PAYLOAD_MAX]; time_t stoptime = time(0) + HANDLE_TCP_UPDATE_TIMEOUT; struct link *l = link_accept(update_port,stoptime); if(!l) return; char addr[LINK_ADDRESS_MAX]; int port; link_address_remote(l,addr,&port); int length = link_read(l,data,sizeof(data)-1,stoptime); if(length>0) { data[length] = 0; handle_update(addr,port,data,length,"tcp"); } link_close(l); }
struct list* do_direct_query( const char *master_host, int master_port ) { const char * query_string = "queue"; struct link *l; char master_addr[LINK_ADDRESS_MAX]; time_t stoptime = time(0) + work_queue_status_timeout; if(!domain_name_cache_lookup(master_host,master_addr)) { fprintf(stderr,"couldn't find address of %s\n",master_host); return 0; } l = link_connect(master_addr,master_port,stoptime); if(!l) { fprintf(stderr,"couldn't connect to %s port %d: %s\n",master_host,master_port,strerror(errno)); return 0; } link_putfstring(l,"%s_status\n",stoptime,query_string); struct jx *jarray = jx_parse_link(l,stoptime); struct jx *j = jarray->u.items->value; link_close(l); if(!j) { fprintf(stderr,"couldn't read from %s port %d: %s\n",master_host,master_port,strerror(errno)); return 0; } j->type = JX_OBJECT; struct list* master_list = list_create(); list_push_head(master_list, j); return master_list; }
struct jx *catalog_query_send_query(const char *url, time_t stoptime) { struct link *link = http_query(url, "GET", stoptime); if(!link) { return NULL; } struct jx *j = jx_parse_link(link,stoptime); link_close(link); if(!j) { debug(D_DEBUG,"query result failed to parse as JSON"); return NULL; } if(!jx_istype(j,JX_ARRAY)) { debug(D_DEBUG,"query result is not a JSON array"); jx_delete(j); return NULL; } return j; }
/* * link_open -- Open the specified link-level device * * Inputs: * * device The name of the device to open * * Returns: * * A pointer to a link handle structure. */ static link_t * link_open(const char *device) { union DL_primitives *dlp; unsigned char buf[MAXDLBUF]; char *p; char dev[16]; link_t *handle; int ppa; handle = Malloc(sizeof(*handle)); memset(handle, '\0', sizeof(*handle)); #ifdef HAVE_SYS_DLPIHDR_H if ((handle->fd = open("/dev/streams/dlb", O_RDWR)) < 0) { free(handle); return NULL; } if ((ppa = link_match_ppa(handle, device)) < 0) { link_close(handle); return NULL; } #else handle->fd = -1; snprintf(dev, sizeof(dev), "/dev/%s", device); if ((p = strpbrk(dev, "0123456789")) == NULL) { link_close(handle); return NULL; } ppa = atoi(p); *p = '\0'; if ((handle->fd = open(dev, O_RDWR)) < 0) { snprintf(dev, sizeof(dev), "/dev/%s", device); if ((handle->fd = open(dev, O_RDWR)) < 0) { link_close(handle); return NULL; } } #endif memset(&(handle->ifr), 0, sizeof(struct ifreq)); strlcpy(handle->ifr.ifr_name, device, sizeof(handle->ifr.ifr_name)); dlp = (union DL_primitives *)buf; dlp->info_req.dl_primitive = DL_INFO_REQ; if (dlpi_msg(handle->fd, dlp, DL_INFO_REQ_SIZE, RS_HIPRI, DL_INFO_ACK, DL_INFO_ACK_SIZE, sizeof(buf)) < 0) { link_close(handle); return NULL; } handle->sap_first = (dlp->info_ack.dl_sap_length > 0); if (dlp->info_ack.dl_provider_style == DL_STYLE2) { dlp->attach_req.dl_primitive = DL_ATTACH_REQ; dlp->attach_req.dl_ppa = ppa; if (dlpi_msg(handle->fd, dlp, DL_ATTACH_REQ_SIZE, 0, DL_OK_ACK, DL_OK_ACK_SIZE, sizeof(buf)) < 0) { link_close(handle); return NULL; } } memset(&dlp->bind_req, 0, DL_BIND_REQ_SIZE); dlp->bind_req.dl_primitive = DL_BIND_REQ; #ifdef DL_HP_RAWDLS dlp->bind_req.dl_sap = 24; /* from HP-UX DLPI programmers guide */ dlp->bind_req.dl_service_mode = DL_HP_RAWDLS; #else dlp->bind_req.dl_sap = DL_ETHER; dlp->bind_req.dl_service_mode = DL_CLDLS; #endif if (dlpi_msg(handle->fd, dlp, DL_BIND_REQ_SIZE, 0, DL_BIND_ACK, DL_BIND_ACK_SIZE, sizeof(buf)) < 0) { link_close(handle); return NULL; } #ifdef DLIOCRAW if (strioctl(handle->fd, DLIOCRAW, 0, NULL) < 0) { link_close(handle); return NULL; } #endif return (handle); }
struct link *http_query_size_via_proxy(const char *proxy, const char *urlin, const char *action, INT64_T * size, time_t stoptime, int cache_reload) { char url[HTTP_LINE_MAX]; char newurl[HTTP_LINE_MAX]; char line[HTTP_LINE_MAX]; char addr[LINK_ADDRESS_MAX]; struct link *link; int save_errno; int response; char actual_host[HTTP_LINE_MAX]; int actual_port; *size = 0; url_encode(urlin, url, sizeof(url)); if(proxy && !strcmp(proxy, "DIRECT")) proxy = 0; if(proxy) { int fields = sscanf(proxy, "http://%[^:]:%d", actual_host, &actual_port); if(fields == 2) { /* host and port are good */ } else if(fields == 1) { actual_port = HTTP_PORT; } else { debug(D_HTTP, "invalid proxy syntax: %s", proxy); return 0; } } else { int fields = sscanf(url, "http://%[^:]:%d", actual_host, &actual_port); if(fields != 2) { fields = sscanf(url, "http://%[^/]", actual_host); if(fields == 1) { actual_port = HTTP_PORT; } else { debug(D_HTTP, "malformed url: %s", url); return 0; } } } debug(D_HTTP, "connect %s port %d", actual_host, actual_port); if(!domain_name_lookup(actual_host, addr)) return 0; link = link_connect(addr, actual_port, stoptime); if(!link) { errno = ECONNRESET; return 0; } { buffer_t B; buffer_init(&B); buffer_abortonfailure(&B, 1); buffer_printf(&B, "%s %s HTTP/1.1\r\n", action, url); if(cache_reload) buffer_putliteral(&B, "Cache-Control: max-age=0\r\n"); buffer_putliteral(&B, "Connection: close\r\n"); buffer_printf(&B, "Host: %s\r\n", actual_host); if(getenv("HTTP_USER_AGENT")) buffer_printf(&B, "User-Agent: Mozilla/5.0 (compatible; CCTools %d.%d.%s Parrot; http://www.nd.edu/~ccl/ %s)\r\n", CCTOOLS_VERSION_MAJOR, CCTOOLS_VERSION_MINOR, CCTOOLS_VERSION_MICRO, getenv("HTTP_USER_AGENT")); else buffer_printf(&B, "User-Agent: Mozilla/5.0 (compatible; CCTools %d.%d.%s Parrot; http://www.nd.edu/~ccl/)\r\n", CCTOOLS_VERSION_MAJOR, CCTOOLS_VERSION_MINOR, CCTOOLS_VERSION_MICRO); buffer_putliteral(&B, "\r\n"); /* header terminator */ debug(D_HTTP, "%s", buffer_tostring(&B, NULL)); link_putstring(link, buffer_tostring(&B, NULL), stoptime); buffer_free(&B); } if(link_readline(link, line, HTTP_LINE_MAX, stoptime)) { string_chomp(line); debug(D_HTTP, "%s", line); if(sscanf(line, "HTTP/%*d.%*d %d", &response) == 1) { newurl[0] = 0; while(link_readline(link, line, HTTP_LINE_MAX, stoptime)) { string_chomp(line); debug(D_HTTP, "%s", line); sscanf(line, "Location: %s", newurl); sscanf(line, "Content-Length: %" SCNd64, size); if(strlen(line) <= 2) { break; } } switch (response) { case 200: return link; break; case 301: case 302: case 303: case 307: link_close(link); if(newurl[0]) { if(!strcmp(url, newurl)) { debug(D_HTTP, "error: server gave %d redirect from %s back to the same url!", response, url); errno = EIO; return 0; } else { return http_query_size_via_proxy(proxy,newurl,action,size,stoptime,cache_reload); } } else { errno = ENOENT; return 0; } break; default: link_close(link); errno = http_response_to_errno(response); return 0; break; } } else { debug(D_HTTP, "malformed response"); save_errno = ECONNRESET; } } else { debug(D_HTTP, "malformed response"); save_errno = ECONNRESET; } link_close(link); errno = save_errno; return 0; }
struct link *link_connect(const char *addr, int port, time_t stoptime) { struct sockaddr_in address; struct link *link = 0; int result; int save_errno; link = link_create(); if(!link) goto failure; link_squelch(); memset(&address, 0, sizeof(address)); #if defined(CCTOOLS_OPSYS_DARWIN) address.sin_len = sizeof(address); #endif address.sin_family = AF_INET; address.sin_port = htons(port); if(!string_to_ip_address(addr, (unsigned char *) &address.sin_addr)) goto failure; link->fd = socket(AF_INET, SOCK_STREAM, 0); if(link->fd < 0) goto failure; link_window_configure(link); /* sadly, cygwin does not do non-blocking connect correctly */ #ifdef CCTOOLS_OPSYS_CYGWIN if(!link_nonblocking(link, 0)) goto failure; #else if(!link_nonblocking(link, 1)) goto failure; #endif debug(D_TCP, "connecting to %s:%d", addr, port); while(1) { // First attempt a non-blocking connect result = connect(link->fd, (struct sockaddr *) &address, sizeof(address)); // On many platforms, non-blocking connect sets errno in unexpected ways: // On OSX, result=-1 and errno==EISCONN indicates a successful connection. if(result<0 && errno==EISCONN) result=0; // On BSD-derived systems, failure to connect is indicated by errno = EINVAL. // Set it to something more explanatory. if(result<0 && errno==EINVAL) errno=ECONNREFUSED; // Otherwise, a non-temporary errno should cause us to bail out. if(result<0 && !errno_is_temporary(errno)) break; // If the remote address is valid, we are connected no matter what. if(link_address_remote(link, link->raddr, &link->rport)) { debug(D_TCP, "made connection to %s:%d", link->raddr, link->rport); #ifdef CCTOOLS_OPSYS_CYGWIN link_nonblocking(link, 1); #endif return link; } // if the time has expired, bail out if( time(0) >= stoptime ) { errno = ETIMEDOUT; break; } // wait for some activity on the socket. link_sleep(link, stoptime, 0, 1); // No matter how the sleep ends, we want to go back to the top // and call connect again to get a proper errno. } debug(D_TCP, "connection to %s:%d failed (%s)", addr, port, strerror(errno)); failure: save_errno = errno; if(link) link_close(link); errno = save_errno; return 0; }
int main(int argc, char *argv[]) { struct link *link, *list_port = 0; signed char ch; time_t current; int is_daemon = 0; char *pidfile = NULL; char *interface = NULL; outgoing_host_list = list_create(); debug_config(argv[0]); static const struct option long_options[] = { {"background", no_argument, 0, 'b'}, {"pid-file", required_argument, 0, 'B'}, {"debug", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"history", required_argument, 0, 'H'}, {"lifetime", required_argument, 0, 'l'}, {"update-log", required_argument, 0, 'L'}, {"max-jobs", required_argument, 0, 'm'}, {"server-size", required_argument, 0, 'M'}, {"name", required_argument, 0, 'n'}, {"interface", required_argument, 0, 'I'}, {"debug-file", required_argument, 0, 'o'}, {"debug-rotate-max", required_argument, 0, 'O'}, {"port", required_argument, 0, 'p'}, {"single", no_argument, 0, 'S'}, {"timeout", required_argument, 0, 'T'}, {"update-host", required_argument, 0, 'u'}, {"update-interval", required_argument, 0, 'U'}, {"version", no_argument, 0, 'v'}, {"port-file", required_argument, 0, 'Z'}, {0,0,0,0}}; while((ch = getopt_long(argc, argv, "bB:d:hH:I:l:L:m:M:n:o:O:p:ST:u:U:vZ:", long_options, NULL)) > -1) { switch (ch) { case 'b': is_daemon = 1; break; case 'B': free(pidfile); pidfile = strdup(optarg); break; case 'd': debug_flags_set(optarg); break; case 'h': default: show_help(argv[0]); return 1; case 'l': lifetime = string_time_parse(optarg); break; case 'L': logfilename = strdup(optarg); break; case 'H': history_dir = strdup(optarg); break; case 'I': free(interface); interface = strdup(optarg); break; case 'm': child_procs_max = atoi(optarg); break; case 'M': max_server_size = string_metric_parse(optarg); break; case 'n': preferred_hostname = optarg; break; case 'o': debug_config_file(optarg); break; case 'O': debug_config_file_size(string_metric_parse(optarg)); break; case 'p': port = atoi(optarg); break; case 'S': fork_mode = 0; break; case 'T': child_procs_timeout = string_time_parse(optarg); break; case 'u': list_push_head(outgoing_host_list, xxstrdup(optarg)); break; case 'U': outgoing_timeout = string_time_parse(optarg); break; case 'v': cctools_version_print(stdout, argv[0]); return 0; case 'Z': port_file = optarg; port = 0; break; } } if (is_daemon) daemonize(0, pidfile); cctools_version_debug(D_DEBUG, argv[0]); if(logfilename) { logfile = fopen(logfilename,"a"); if(!logfile) fatal("couldn't open %s: %s\n",optarg,strerror(errno)); } current = time(0); debug(D_NOTICE, "*** %s starting at %s", argv[0], ctime(¤t)); if(!list_size(outgoing_host_list)) { list_push_head(outgoing_host_list, CATALOG_HOST_DEFAULT); } install_handler(SIGPIPE, ignore_signal); install_handler(SIGHUP, ignore_signal); install_handler(SIGCHLD, ignore_signal); install_handler(SIGINT, shutdown_clean); install_handler(SIGTERM, shutdown_clean); install_handler(SIGQUIT, shutdown_clean); install_handler(SIGALRM, shutdown_clean); if(!preferred_hostname) { domain_name_cache_guess(hostname); preferred_hostname = hostname; } username_get(owner); starttime = time(0); table = nvpair_database_create(history_dir); if(!table) fatal("couldn't create directory %s: %s\n",history_dir,strerror(errno)); list_port = link_serve_address(interface, port); if(list_port) { /* If a port was chosen automatically, read it back so that the same one can be used for the update port. There is the possibility that the UDP listen will fail because that port is in use. */ if(port==0) { char addr[LINK_ADDRESS_MAX]; link_address_local(list_port,addr,&port); } } else { if(interface) fatal("couldn't listen on TCP address %s port %d", interface, port); else fatal("couldn't listen on TCP port %d", port); } outgoing_dgram = datagram_create(0); if(!outgoing_dgram) fatal("couldn't create outgoing udp port"); update_dgram = datagram_create_address(interface, port); if(!update_dgram) { if(interface) fatal("couldn't listen on UDP address %s port %d", interface, port); else fatal("couldn't listen on UDP port %d", port); } opts_write_port_file(port_file,port); while(1) { fd_set rfds; int ufd = datagram_fd(update_dgram); int lfd = link_fd(list_port); int result, maxfd; struct timeval timeout; remove_expired_records(); if(time(0) > outgoing_alarm) { update_all_catalogs(outgoing_dgram); outgoing_alarm = time(0) + outgoing_timeout; } while(1) { int status; pid_t pid = waitpid(-1, &status, WNOHANG); if(pid>0) { child_procs_count--; continue; } else { break; } } FD_ZERO(&rfds); FD_SET(ufd, &rfds); if(child_procs_count < child_procs_max) { FD_SET(lfd, &rfds); } maxfd = MAX(ufd, lfd) + 1; timeout.tv_sec = 5; timeout.tv_usec = 0; result = select(maxfd, &rfds, 0, 0, &timeout); if(result <= 0) continue; if(FD_ISSET(ufd, &rfds)) { handle_updates(update_dgram); } if(FD_ISSET(lfd, &rfds)) { link = link_accept(list_port, time(0) + 5); if(link) { if(fork_mode) { pid_t pid = fork(); if(pid == 0) { alarm(child_procs_timeout); handle_query(link); _exit(0); } else if (pid>0) { child_procs_count++; } } else { handle_query(link); } link_close(link); } } } return 1; }
int s3_ls_bucket(char* bucketname, struct list* dirents, const char* access_key_id, const char* access_key) { struct s3_message mesg; struct link* server = NULL; time_t stoptime = time(0)+s3_timeout; char response[HEADER_LINE_MAX]; char path[HEADER_LINE_MAX]; int length; char done = 0; if(!access_key_id || !access_key || !s3_endpoint) return -1; sprintf(path, "/"); mesg.type = S3_MESG_GET; mesg.path = path; mesg.bucket = bucketname; mesg.content_type = NULL; mesg.content_md5 = NULL; mesg.content_length = 0; mesg.date = time(0); mesg.expect = 0; mesg.amz_headers = NULL; do { char *buffer, *temp, *start, *end; char trunc[25]; int keys; sign_message(&mesg, access_key_id, access_key); server = s3_send_message(&mesg, server, stoptime); if(!server) return -1; link_readline(server, response, HEADER_LINE_MAX, stoptime); if(strcmp(response, "HTTP/1.1 200 OK")) { // Error: transfer failed; close connection and return failure fprintf(stderr, "Error: list bucket failed\nResponse: %s\n", response); link_close(server); return -1; } length = 0; do { if(!strncmp(response, "Content-Length:", 14)) sscanf(response, "Content-Length: %d", &length); if(!strcmp(response, "Transfer-Encoding: chunked")) length = 0; if(!strcmp(response, "Server: AmazonS3")) break; } while(link_readline(server, response, HEADER_LINE_MAX, stoptime)); link_readline(server, response, HEADER_LINE_MAX, stoptime); if(length) { buffer = malloc(length+1); link_read(server, buffer, length, stoptime); } else { struct list *buf; unsigned int clen = 0; buf = list_create(); do { link_readline(server, response, HEADER_LINE_MAX, stoptime); sscanf(response, "%x", &clen); //link_readline(server, response, HEADER_LINE_MAX, stoptime); if(clen) { buffer = malloc(clen+1); link_read(server, buffer, clen, stoptime); link_readline(server, response, HEADER_LINE_MAX, stoptime); list_push_tail(buf, buffer); length += clen; } } while(clen); buffer = malloc(length+1); buffer[0] = '\0'; while((temp = list_pop_head(buf))) { sprintf(buffer, "%s%s", buffer, temp); free(temp); } list_delete(buf); } sscanf(buffer, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>%*[^<]</Name><Prefix></Prefix><Marker></Marker><MaxKeys>%d</MaxKeys><IsTruncated>%[^<]</IsTruncated>", &keys, trunc); if(!strcmp(trunc, "false")) done = 1; temp = buffer; while( (start = strstr(temp, "<Contents>")) ) { struct s3_dirent_object *dirent; struct tm date; char display_name[1024]; end = strstr(start, "</Contents>"); end[10] = '\0'; temp = end + 11; dirent = malloc(sizeof(*dirent)); date.tm_isdst = -1; sscanf(strstr(start, "<Key>"), "<Key>%[^<]</Key>", dirent->key); sscanf(strstr(start, "<LastModified>"), "<LastModified>%d-%d-%dT%d:%d:%d.%*dZ</LastModified>", &date.tm_year, &date.tm_mon, &date.tm_mday, &date.tm_hour, &date.tm_min, &date.tm_sec); sscanf(strstr(start, "<ETag>"), "<ETag>"%[^&]"</ETag>", dirent->digest); sscanf(strstr(start, "<Size>"), "<Size>%d</Size>", &dirent->size); sscanf(strstr(start, "<Owner>"), "<Owner><ID>%*[^<]</ID><DisplayName>%[^<]</DisplayName></Owner>", display_name); if(strlen(display_name)) dirent->display_name = strdup(display_name); date.tm_mon -= 1; dirent->last_modified = mktime(&date); list_push_tail(dirents, dirent); } free(buffer); } while(!done); link_close(server); return 0; }
int s3_getacl(char* bucketname, char* filename, char* owner, struct hash_table* acls, const char* access_key_id, const char* access_key) { struct s3_message mesg; struct link* server; time_t stoptime = time(0)+s3_timeout; char path[HEADER_LINE_MAX]; char response[HEADER_LINE_MAX]; char * text; char * start; char * temp; int length; if(!s3_endpoint) return -1; if(filename) sprintf(path, "%s?acl", filename); else sprintf(path, "/?acl"); mesg.type = S3_MESG_GET; mesg.path = path; mesg.bucket = bucketname; mesg.content_type = NULL; mesg.content_md5 = NULL; mesg.content_length = 0; mesg.date = time(0); mesg.expect = 0; mesg.amz_headers = NULL; //server = link_connect(s3_address, 80, stoptime); sign_message(&mesg, access_key_id, access_key); server = s3_send_message(&mesg, NULL, stoptime); if(!server) return -1; //length = s3_message_to_string(&mesg, &text); //link_putlstring(server, text, length, stoptime); //free(text); link_readline(server, response, HEADER_LINE_MAX, stoptime); if(strcmp(response, "HTTP/1.1 200 OK")) { // Error: transfer failed; close connection and return failure //fprintf(stderr, "Error: request file failed\nResponse: %s\n", response); link_close(server); return -1; } do { if(!strncmp(response, "Content-Length:", 14)) sscanf(response, "Content-Length: %d", &length); if(!strcmp(response, "Transfer-Encoding: chunked")) length = 0; if(!strcmp(response, "Server: AmazonS3")) break; } while(link_readline(server, response, HEADER_LINE_MAX, stoptime)); link_readline(server, response, HEADER_LINE_MAX, stoptime); if(length) { text = malloc(length+1); link_read(server, text, length, stoptime); } else { struct list *buf; char *temp; unsigned int clen = 0; buf = list_create(); do { link_readline(server, response, HEADER_LINE_MAX, stoptime); sscanf(response, "%x", &clen); //link_readline(server, response, HEADER_LINE_MAX, stoptime); if(clen) { text = malloc(clen+1); link_read(server, text, clen, stoptime); link_readline(server, response, HEADER_LINE_MAX, stoptime); list_push_tail(buf, text); length += clen; } } while(clen); text = malloc(length+1); text[0] = '\0'; while((temp = list_pop_head(buf))) { sprintf(text, "%s%s", text, temp); free(temp); } list_delete(buf); } link_close(server); if(owner) sscanf(strstr(text, "<Owner>"), "<Owner><ID>%[^<]</ID>", owner); temp = text; while( (start = strstr(temp, "<Grant>")) ) { char id[1024]; char display_name[1024]; char permission[1024]; char type; struct s3_acl_object *acl; char *end; end = strstr(start, "</Grant>"); end[7] = '\0'; temp = end + 8; memset(display_name, 0, 1024); type = S3_ACL_ID; if( sscanf(start, "<Grant><Grantee %*[^>]><ID>%[^<]</ID><DisplayName>%[^<]</DisplayName></Grantee><Permission>%[^<]</Permission></Grantee>", id, display_name, permission) != 3 ) { type = S3_ACL_URI; sscanf(start, "<Grant><Grantee %*[^>]><URI>http://acs.amazonaws.com/groups/global/%[^<]</URI></Grantee><Permission>%[^<]</Permission></Grantee>", id, permission); } if( !(acl = hash_table_lookup(acls, id)) ) { acl = malloc(sizeof(*acl)); acl->acl_type = type; if(*display_name) acl->display_name = strdup(display_name); else acl->display_name = NULL; acl->perm = 0; hash_table_insert(acls, id, acl); } if(!strcmp(permission, "FULL_CONTROL")) { acl->perm = acl->perm | S3_ACL_FULL_CONTROL; } else if(!strcmp(permission, "READ")) { acl->perm = acl->perm | S3_ACL_READ; } else if(!strcmp(permission, "WRITE")) { acl->perm = acl->perm | S3_ACL_WRITE; } else if(!strcmp(permission, "READ_ACP")) { acl->perm = acl->perm | S3_ACL_READ_ACP; } else if(!strcmp(permission, "WRITE_ACP")) { acl->perm = acl->perm | S3_ACL_WRITE_ACP; } } free(text); return 0; }
struct link *http_query_size_via_proxy(const char *proxy, const char *urlin, const char *action, INT64_T * size, time_t stoptime, int cache_reload) { char url[HTTP_LINE_MAX]; char newurl[HTTP_LINE_MAX]; char line[HTTP_LINE_MAX]; char addr[LINK_ADDRESS_MAX]; struct link *link; int save_errno; int response; char actual_host[HTTP_LINE_MAX]; int actual_port; *size = 0; url_encode(urlin, url, sizeof(url)); if(proxy && !strcmp(proxy, "DIRECT")) proxy = 0; if(proxy) { int fields = sscanf(proxy, "http://%[^:]:%d", actual_host, &actual_port); if(fields == 2) { /* host and port are good */ } else if(fields == 1) { actual_port = HTTP_PORT; } else { debug(D_HTTP, "invalid proxy syntax: %s", proxy); return 0; } } else { int fields = sscanf(url, "http://%[^:]:%d", actual_host, &actual_port); if(fields != 2) { fields = sscanf(url, "http://%[^/]", actual_host); if(fields == 1) { actual_port = HTTP_PORT; } else { debug(D_HTTP, "malformed url: %s", url); return 0; } } } debug(D_HTTP, "connect %s port %d", actual_host, actual_port); if(!domain_name_lookup(actual_host, addr)) return 0; link = link_connect(addr, actual_port, stoptime); if(!link) { errno = ECONNRESET; return 0; } if(cache_reload == 0) { debug(D_HTTP, "%s %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n", action, url, actual_host); link_putfstring(link, "%s %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n", stoptime, action, url, actual_host); } else { // force refresh of cache end-to-end (RFC 2616) debug(D_HTTP, "%s %s HTTP/1.1\r\nHost: %s\r\nCache-Control: max-age=0\r\nConnection: close\r\n\r\n", action, url, actual_host); link_putfstring(link, "%s %s HTTP/1.1\r\nHost: %s\r\nCache-Control: max-age=0\r\nConnection: close\r\n\r\n", stoptime, action, url, actual_host); } if(link_readline(link, line, HTTP_LINE_MAX, stoptime)) { string_chomp(line); debug(D_HTTP, "%s", line); if(sscanf(line, "HTTP/%*d.%*d %d", &response) == 1) { newurl[0] = 0; while(link_readline(link, line, HTTP_LINE_MAX, stoptime)) { string_chomp(line); debug(D_HTTP, "%s", line); sscanf(line, "Location: %s", newurl); sscanf(line, "Content-Length: %lld", size); if(strlen(line) <= 2) { break; } } switch (response) { case 200: return link; break; case 301: case 302: case 303: case 307: link_close(link); if(newurl[0]) { if(!strcmp(url, newurl)) { debug(D_HTTP, "error: server gave %d redirect from %s back to the same url!", response, url); errno = EIO; return 0; } else { return http_query(newurl, action, stoptime); } } else { errno = ENOENT; return 0; } break; default: link_close(link); errno = http_response_to_errno(response); return 0; break; } } else { debug(D_HTTP, "malformed response"); save_errno = ECONNRESET; } } else { debug(D_HTTP, "malformed response"); save_errno = ECONNRESET; } link_close(link); errno = save_errno; return 0; }
void chirp_client_disconnect(struct chirp_client *c) { link_close(c->link); free(c); }
int main(int argc, char *argv[]) { struct link *link, *list_port = 0; char ch; time_t current; int is_daemon = 0; char *pidfile = NULL; outgoing_host_list = list_create(); debug_config(argv[0]); while((ch = getopt(argc, argv, "bB:d:hH:l:L:m:M:n:o:O:p:ST:u:U:v")) != (char) -1) { switch (ch) { case 'b': is_daemon = 1; break; case 'B': free(pidfile); pidfile = strdup(optarg); break; case 'd': debug_flags_set(optarg); break; case 'h': default: show_help(argv[0]); return 1; case 'l': lifetime = string_time_parse(optarg); break; case 'L': logfilename = strdup(optarg); break; case 'H': history_dir = strdup(optarg); break; case 'm': child_procs_max = atoi(optarg); break; case 'M': max_server_size = string_metric_parse(optarg); break; case 'n': preferred_hostname = optarg; break; case 'o': free(debug_filename); debug_filename = strdup(optarg); break; case 'O': debug_config_file_size(string_metric_parse(optarg)); break; case 'p': port = atoi(optarg); break; case 'S': fork_mode = 0; break; case 'T': child_procs_timeout = string_time_parse(optarg); break; case 'u': list_push_head(outgoing_host_list, xxstrdup(optarg)); break; case 'U': outgoing_timeout = string_time_parse(optarg); break; case 'v': cctools_version_print(stdout, argv[0]); return 0; } } if (is_daemon) daemonize(0, pidfile); debug_config_file(debug_filename); cctools_version_debug(D_DEBUG, argv[0]); if(logfilename) { logfile = fopen(logfilename,"a"); if(!logfile) fatal("couldn't open %s: %s\n",optarg,strerror(errno)); } current = time(0); debug(D_ALL, "*** %s starting at %s", argv[0], ctime(¤t)); if(!list_size(outgoing_host_list)) { list_push_head(outgoing_host_list, CATALOG_HOST_DEFAULT); } install_handler(SIGPIPE, ignore_signal); install_handler(SIGHUP, ignore_signal); install_handler(SIGCHLD, ignore_signal); install_handler(SIGINT, shutdown_clean); install_handler(SIGTERM, shutdown_clean); install_handler(SIGQUIT, shutdown_clean); install_handler(SIGALRM, shutdown_clean); if(!preferred_hostname) { domain_name_cache_guess(hostname); preferred_hostname = hostname; } username_get(owner); starttime = time(0); table = nvpair_database_create(history_dir); if(!table) fatal("couldn't create directory %s: %s\n",history_dir,strerror(errno)); update_dgram = datagram_create(port); if(!update_dgram) fatal("couldn't listen on udp port %d", port); outgoing_dgram = datagram_create(0); if(!outgoing_dgram) fatal("couldn't create outgoing udp port"); list_port = link_serve(port); if(!list_port) fatal("couldn't listen on tcp port %d", port); while(1) { fd_set rfds; int ufd = datagram_fd(update_dgram); int lfd = link_fd(list_port); int result, maxfd; struct timeval timeout; remove_expired_records(); if(time(0) > outgoing_alarm) { update_all_catalogs(outgoing_dgram); outgoing_alarm = time(0) + outgoing_timeout; } while(1) { int status; pid_t pid = waitpid(-1, &status, WNOHANG); if(pid>0) { child_procs_count--; continue; } else { break; } } FD_ZERO(&rfds); FD_SET(ufd, &rfds); if(child_procs_count < child_procs_max) { FD_SET(lfd, &rfds); } maxfd = MAX(ufd, lfd) + 1; timeout.tv_sec = 5; timeout.tv_usec = 0; result = select(maxfd, &rfds, 0, 0, &timeout); if(result <= 0) continue; if(FD_ISSET(ufd, &rfds)) { handle_updates(update_dgram); } if(FD_ISSET(lfd, &rfds)) { link = link_accept(list_port, time(0) + 5); if(link) { if(fork_mode) { pid_t pid = fork(); if(pid == 0) { alarm(child_procs_timeout); handle_query(link); _exit(0); } else if (pid>0) { child_procs_count++; } } else { handle_query(link); } link_close(link); } } } return 1; }
struct link *link_serve_address(const char *addr, int port) { struct link *link = 0; struct sockaddr_in address; int success; int value; link = link_create(); if(!link) goto failure; link->fd = socket(AF_INET, SOCK_STREAM, 0); if(link->fd < 0) goto failure; value = fcntl(link->fd, F_GETFD); if (value == -1) goto failure; value |= FD_CLOEXEC; if (fcntl(link->fd, F_SETFD, value) == -1) goto failure; value = 1; setsockopt(link->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &value, sizeof(value)); link_window_configure(link); memset(&address, 0, sizeof(address)); #if defined(CCTOOLS_OPSYS_DARWIN) address.sin_len = sizeof(address); #endif address.sin_family = AF_INET; if(addr) { string_to_ip_address(addr, (unsigned char *) &address.sin_addr.s_addr); } else { address.sin_addr.s_addr = htonl(INADDR_ANY); } int low = TCP_LOW_PORT_DEFAULT; int high = TCP_HIGH_PORT_DEFAULT; if(port < 1) { const char *lowstr = getenv("TCP_LOW_PORT"); if (lowstr) low = atoi(lowstr); const char *highstr = getenv("TCP_HIGH_PORT"); if (highstr) high = atoi(highstr); } else { low = high = port; } if(high < low) fatal("high port %d is less than low port %d in range", high, low); for (port = low; port <= high; port++) { address.sin_port = htons(port); success = bind(link->fd, (struct sockaddr *) &address, sizeof(address)); if(success == -1) { if(errno == EADDRINUSE) { //If a port is specified, fail! if (low == high) { goto failure; } else { continue; } } else { goto failure; } } break; } success = listen(link->fd, 5); if(success < 0) goto failure; if(!link_nonblocking(link, 1)) goto failure; debug(D_TCP, "listening on port %d", port); return link; failure: if(link) link_close(link); return 0; }
struct link *link_connect(const char *addr, int port, time_t stoptime) { struct sockaddr_in address; struct link *link = 0; int result; int save_errno; link = link_create(); if(!link) goto failure; link_squelch(); memset(&address, 0, sizeof(address)); #if defined(CCTOOLS_OPSYS_DARWIN) address.sin_len = sizeof(address); #endif address.sin_family = AF_INET; address.sin_port = htons(port); if(!string_to_ip_address(addr, (unsigned char *) &address.sin_addr)) goto failure; link->fd = socket(AF_INET, SOCK_STREAM, 0); if(link->fd < 0) goto failure; link_window_configure(link); /* sadly, cygwin does not do non-blocking connect correctly */ #ifdef CCTOOLS_OPSYS_CYGWIN if(!link_nonblocking(link, 0)) goto failure; #else if(!link_nonblocking(link, 1)) goto failure; #endif debug(D_TCP, "connecting to %s:%d", addr, port); do { result = connect(link->fd, (struct sockaddr *) &address, sizeof(address)); /* On some platforms, errno is not set correctly. */ /* If the remote address can be found, then we are really connected. */ /* Also, on bsd-derived systems, failure to connect is indicated by a second connect returning EINVAL. */ if(result < 0 && !errno_is_temporary(errno)) { if(errno == EINVAL) errno = ECONNREFUSED; break; } if(link_address_remote(link, link->raddr, &link->rport)) { debug(D_TCP, "made connection to %s:%d", link->raddr, link->rport); #ifdef CCTOOLS_OPSYS_CYGWIN link_nonblocking(link, 1); #endif return link; } } while(link_sleep(link, stoptime, 0, 1)); debug(D_TCP, "connection to %s:%d failed (%s)", addr, port, strerror(errno)); failure: save_errno = errno; if(link) link_close(link); errno = save_errno; return 0; }
// NOT IMPLEMENTED YET int s3_setacl(char* bucketname, char *filename, const char* owner, struct hash_table* acls, const char* access_key_id, const char* access_key) { struct s3_message mesg; struct link* server; time_t stoptime = time(0)+s3_timeout; char path[HEADER_LINE_MAX]; char response[HEADER_LINE_MAX]; //char * text; //int length; char *id; struct s3_acl_object *acl; if(!s3_endpoint) return -1; if(filename) sprintf(path, "%s?acl", filename); else sprintf(path, "/?acl"); mesg.content_length = 39 + 32 + strlen(owner) + 32; hash_table_firstkey(acls); while(hash_table_nextkey(acls, &id, (void**)&acl)) { int glength; switch(acl->acl_type) { case S3_ACL_URI: glength = 140+strlen(id); break; case S3_ACL_EMAIL: glength = 135+strlen(id); break; default: glength = 107+strlen(id); } if(acl->perm & S3_ACL_FULL_CONTROL) mesg.content_length += 40 + glength + 12; if(acl->perm & S3_ACL_READ) mesg.content_length += 40 + glength + 4; if(acl->perm & S3_ACL_WRITE) mesg.content_length += 40 + glength + 5; if(acl->perm & S3_ACL_READ_ACP) mesg.content_length += 40 + glength + 8; if(acl->perm & S3_ACL_WRITE_ACP) mesg.content_length += 40 + glength + 9; } mesg.content_length += 43; mesg.type = S3_MESG_PUT; mesg.path = path; mesg.bucket = bucketname; mesg.content_type = NULL; mesg.content_md5 = NULL; mesg.date = time(0); mesg.expect = 0; mesg.amz_headers = NULL; //server = link_connect(s3_address, 80, stoptime); sign_message(&mesg, access_key_id, access_key); server = s3_send_message(&mesg, NULL, stoptime); if(!server) return -1; //length = s3_message_to_string(&mesg, &text); //fprintf(stderr, "Message:\n%s\n", text); //link_putlstring(server, text, length, stoptime); //free(text); link_putliteral(server, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", stoptime); link_putliteral(server, "<AccessControlPolicy><Owner><ID>", stoptime); link_putstring(server, owner, stoptime); link_putliteral(server, "</ID></Owner><AccessControlList>", stoptime); hash_table_firstkey(acls); while(hash_table_nextkey(acls, &id, (void**)&acl)) { char grantee[HEADER_LINE_MAX]; switch(acl->acl_type) { case S3_ACL_URI: sprintf(grantee, "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/%s</URI></Grantee>", id); break; case S3_ACL_EMAIL: sprintf(grantee, "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"AmazonCustomerByEmail\"><EmailAddress>%s</EmailAddress></Grantee>", id); break; default: sprintf(grantee, "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>%s</ID></Grantee>", id); } if(acl->perm & S3_ACL_FULL_CONTROL) { link_putfstring(server, "<Grant>%s<Permission>FULL_CONTROL</Permission></Grant>", stoptime, grantee); } if(acl->perm & S3_ACL_READ) { link_putfstring(server, "<Grant>%s<Permission>READ</Permission></Grant>", stoptime, grantee); } if(acl->perm & S3_ACL_WRITE) { link_putfstring(server, "<Grant>%s<Permission>WRITE</Permission></Grant>", stoptime, grantee); } if(acl->perm & S3_ACL_READ_ACP) { link_putfstring(server, "<Grant>%s<Permission>READ_ACP</Permission></Grant>", stoptime, grantee); } if(acl->perm & S3_ACL_WRITE_ACP) { link_putfstring(server, "<Grant>%s<Permission>WRITE_ACP</Permission></Grant>", stoptime, grantee); } } link_putliteral(server, "</AccessControlList></AccessControlPolicy>\n", stoptime); link_readline(server, response, HEADER_LINE_MAX, stoptime); if(strcmp(response, "HTTP/1.1 200 OK")) { // Error: transfer failed; close connection and return failure fprintf(stderr, "Error: send file failed\nResponse: %s\n", response); link_close(server); return -1; } // fprintf(stderr, "Response:\n"); do { // fprintf(stderr, "\t%s\n", response); if(!strcmp(response, "Server: AmazonS3")) break; } while(link_readline(server, response, HEADER_LINE_MAX, stoptime)); link_close(server); return 0; }