/* PUT's from fd to URI */ int ne_put(ne_session *sess, const char *uri, int fd) { ne_request *req; struct stat st; int ret; if (fstat(fd, &st)) { int errnum = errno; char buf[200]; ne_set_error(sess, _("Could not determine file size: %s"), ne_strerror(errnum, buf, sizeof buf)); return NE_ERROR; } req = ne_request_create(sess, "PUT", uri); #ifdef NE_HAVE_DAV ne_lock_using_resource(req, uri, 0); ne_lock_using_parent(req, uri); #endif ne_set_request_body_fd(req, fd, 0, st.st_size); ret = ne_request_dispatch(req); if (ret == NE_OK && ne_get_status(req)->klass != 2) ret = NE_ERROR; ne_request_destroy(req); return ret; }
static Hbf_State _hbf_transfer_no_chunk(ne_session *session, hbf_transfer_t *transfer, const char *verb) { int res; const ne_status* req_status; ne_request *req = ne_request_create(session, verb ? verb : "PUT", transfer->url); if (!req) return HBF_MEMORY_FAIL; ne_add_request_header( req, "Content-Type", "application/octet-stream"); ne_set_request_body_fd(req, transfer->fd, 0, transfer->stat_size); DEBUG_HBF("HBF: chunking not supported for %s", transfer->url); res = ne_request_dispatch(req); req_status = ne_get_status( req ); if (res == NE_OK && req_status->klass == 2) { ne_request_destroy(req); return HBF_SUCCESS; } if( transfer->error_string ) free( transfer->error_string ); transfer->error_string = strdup( ne_get_error(session) ); transfer->status_code = req_status->code; ne_request_destroy(req); return HBF_FAIL; }
/* Perform a conditional PUT request with given If: header value, * placing response status-code in *code and class in *klass. Fails * if requests cannot be dispatched. */ static int conditional_put(const char *ifhdr, int *klass, int *code) { ne_request *req; req = ne_request_create(i_session, "PUT", res); ne_set_request_body_fd(req, i_foo_fd, 0, i_foo_len); ne_print_request_header(req, "If", "%s", ifhdr); ONMREQ("PUT", res, ne_request_dispatch(req)); if (code) *code = ne_get_status(req)->code; if (klass) *klass = ne_get_status(req)->klass; ne_request_destroy(req); return OK; }
/* * perform one transfer of one block. * returns HBF_TRANSFER_SUCCESS if the transfer of this block was a success * returns HBF_SUCCESS if the server aknoweldge that he received all the blocks */ static int _hbf_dav_request(hbf_transfer_t *transfer, ne_request *req, int fd, hbf_block_t *blk ) { Hbf_State state = HBF_TRANSFER_SUCCESS; int res; const ne_status *req_status = NULL; const char *etag = NULL; (void) transfer; if( ! (blk && req) ) return HBF_PARAM_FAIL; ne_set_request_body_fd(req, fd, blk->start, blk->size); DEBUG_HBF("Block: %d , Start: %" PRId64 " and Size: %" PRId64 "", blk->seq_number, blk->start, blk->size ); res = ne_request_dispatch(req); req_status = ne_get_status( req ); switch(res) { case NE_OK: blk->state = HBF_TRANSFER_FAILED; state = HBF_FAIL; etag = 0; if( req_status->klass == 2 ) { state = HBF_TRANSFER_SUCCESS; blk->state = HBF_TRANSFER_SUCCESS; etag = ne_get_response_header(req, "ETag"); if (etag && etag[0]) { /* When there is an etag, it means the transfer was complete */ state = HBF_SUCCESS; if( etag[0] == '"' && etag[ strlen(etag)-1] == '"') { int len = strlen( etag )-2; blk->etag = malloc( len+1 ); strncpy( blk->etag, etag+1, len ); blk->etag[len] = '\0'; } else { blk->etag = strdup( etag ); } } else { /* DEBUG_HBF("OOOOOOOO No etag returned!"); */ } /* check if the server was able to set the mtime already. */ etag = ne_get_response_header(req, "X-OC-MTime"); if( etag && strcmp(etag, "accepted") == 0 ) { /* the server acknowledged that the mtime was set. */ transfer->modtime_accepted = 1; } etag = ne_get_response_header(req, "OC-FileID"); if( etag ) { transfer->file_id = strdup( etag ); } } break; case NE_AUTH: state = HBF_AUTH_FAIL; blk->state = HBF_TRANSFER_FAILED; break; case NE_PROXYAUTH: state = HBF_PROXY_AUTH_FAIL; blk->state = HBF_TRANSFER_FAILED; break; case NE_CONNECT: state = HBF_CONNECT_FAIL; blk->state = HBF_TRANSFER_FAILED; break; case NE_TIMEOUT: state = HBF_TIMEOUT_FAIL; blk->state = HBF_TRANSFER_FAILED; break; case NE_ERROR: state = HBF_FAIL; blk->state = HBF_TRANSFER_FAILED; break; } blk->http_result_code = req_status->code; if( req_status->reason_phrase ) { blk->http_error_msg = strdup(req_status->reason_phrase); } return state; }
/* * Puts a file read from the open file descriptor to the ownCloud URL. */ static int owncloud_put(csync_vio_method_handle_t *flocal, csync_vio_method_handle_t *fremote, csync_vio_file_stat_t *vfs) { int rc = 0; int neon_stat; const ne_status *status; csync_stat_t sb; struct transfer_context *write_ctx = (struct transfer_context*) fremote; int fd; ne_request *request = NULL; fd = csync_vio_getfd(flocal); if (fd == -1) { errno = EINVAL; return -1; } if( write_ctx == NULL ) { errno = EINVAL; return -1; } request = write_ctx->req; if( request == NULL) { errno = EINVAL; return -1; } /* stat the source-file to get the file size. */ if( fstat( fd, &sb ) == 0 ) { if( sb.st_size != vfs->size ) { DEBUG_WEBDAV("WRN: Stat size differs from vfs size!"); } /* Attach the request to the file descriptor */ ne_set_request_body_fd(request, fd, 0, sb.st_size); DEBUG_WEBDAV("Put file size: %lld, variable sizeof: %ld", (long long int) sb.st_size, sizeof(sb.st_size)); /* Start the request. */ neon_stat = ne_request_dispatch( write_ctx->req ); set_errno_from_neon_errcode( neon_stat ); status = ne_get_status( request ); if( status->klass != 2 ) { DEBUG_WEBDAV("sendfile request failed with http status %d!", status->code); set_errno_from_http_errcode( status->code ); /* decide if soft error or hard error that stops the whole sync. */ /* Currently all problems concerning one file are soft errors */ if( status->klass == 4 /* Forbidden and stuff, soft error */ ) { rc = 1; } else if( status->klass == 5 /* Server errors and such */ ) { rc = 1; /* No Abort on individual file errors. */ } else { rc = 1; } } else { DEBUG_WEBDAV("http request all cool, result code %d", status->code); } } else { DEBUG_WEBDAV("Could not stat file descriptor"); rc = 1; } return rc; }
static int owncloud_close(csync_vio_method_handle_t *fhandle) { struct transfer_context *writeCtx; csync_stat_t st; int rc; int ret = 0; size_t len = 0; writeCtx = (struct transfer_context*) fhandle; if (fhandle == NULL) { errno = EBADF; ret = -1; } /* handle the PUT request, means write to the WebDAV server */ if( ret != -1 && strcmp( writeCtx->method, "PUT" ) == 0 ) { /* if there is a valid file descriptor, close it, reopen in read mode and start the PUT request */ if( writeCtx->fd > -1 ) { if( writeCtx->fileWritten && writeCtx->bytes_written > 0 ) { /* was content written to file? */ /* push the rest of the buffer to file as well. */ DEBUG_WEBDAV(("Write remaining %lu bytes to disk.\n", (unsigned long) writeCtx->bytes_written )); len = write( writeCtx->fd, _buffer, writeCtx->bytes_written ); if( len != writeCtx->bytes_written ) { DEBUG_WEBDAV(("WRN: write wrote wrong number of remaining bytes\n")); } writeCtx->bytes_written = 0; } if( close( writeCtx->fd ) < 0 ) { DEBUG_WEBDAV(("Could not close file %s\n", writeCtx->tmpFileName )); errno = EBADF; ret = -1; } /* and open it again to read from */ #ifdef _WIN32 _fmode = _O_BINARY; #endif if( writeCtx->fileWritten ) { DEBUG_WEBDAV(("Putting file through file cache.\n")); /* we need to go the slow way and close and open the file and read from fd. */ if (( writeCtx->fd = open( writeCtx->tmpFileName, O_RDONLY )) < 0) { errno = EIO; ret = -1; } else { if (fstat( writeCtx->fd, &st ) < 0) { DEBUG_WEBDAV(("Could not stat file %s\n", writeCtx->tmpFileName )); errno = EIO; ret = -1; } /* successfully opened for read. Now start the request via ne_put */ ne_set_request_body_fd( writeCtx->req, writeCtx->fd, 0, st.st_size ); rc = ne_request_dispatch( writeCtx->req ); if( close( writeCtx->fd ) == -1 ) { errno = EBADF; ret = -1; } if (rc == NE_OK) { if ( ne_get_status( writeCtx->req )->klass != 2 ) { DEBUG_WEBDAV(("Error - PUT status value no 2xx\n")); errno = EIO; ret = -1; } } else { DEBUG_WEBDAV(("Error - put request on close failed: %d!\n", rc )); errno = EIO; ret = -1; } } } else { /* all content is in the buffer. */ DEBUG_WEBDAV(("Putting file through memory cache.\n")); ne_set_request_body_buffer( writeCtx->req, _buffer, writeCtx->bytes_written ); rc = ne_request_dispatch( writeCtx->req ); if( rc == NE_OK ) { if ( ne_get_status( writeCtx->req )->klass != 2 ) { DEBUG_WEBDAV(("Error - PUT status value no 2xx\n")); errno = EIO; ret = -1; } } else { DEBUG_WEBDAV(("Error - put request from memory failed: %d!\n", rc )); errno = EIO; ret = -1; } } } ne_request_destroy( writeCtx->req ); } else { /* Its a GET request, not much to do in close. */ if( writeCtx->fd > -1) { if( close( writeCtx->fd ) == -1 ) { errno = EBADF; ret = -1; } } } /* Remove the local file. */ unlink( writeCtx->tmpFileName ); /* free mem. Note that the request mem is freed by the ne_request_destroy call */ SAFE_FREE( writeCtx->tmpFileName ); SAFE_FREE( writeCtx ); return ret; }