Using libdavix
File interface
Most methods in the Davix::DavFile
API come with an exception safe version
which accepts a DavixError*
as an argument, and a version which throws DavixException
instead.
Instantiate a new DavFile.
Context c;
DavFile file(c, Uri("http://example.org/dir1/file1"));
Get all replicas associated to a file.
Context c;
DavixError* err = NULL;
DavFile file(c, Uri("http://example.org/dir1/file1"));
std::vector<DavFile> resultVec;
resultVec = file.getReplicas(NULL, &err);
Execute a vector read operation.
Context c;
DavixError* err = NULL;
DavFile file(c, Uri("http://example.org/dir1/file_to_read"));
int number_of_vector = 2;
DavIOVecInput input_vector[number_of_vector];
DavIOVecOutput output_vector[number_of_vector];
// Setup vector operations parameters
char buf1[255] = {0};
char buf2[255] = {0};
input_vector[0].diov_offset = 100;
input_vector[0].diov_size = 200;
input_vector[0].diov_buffer = buf1;
input_vector[1].diov_offset = 600;
input_vector[1].diov_size = 150;
input_vector[1].diov_buffer = buf2;
// execute query
file.readPartialBufferVec(NULL, input_vector, output_vector, number_of_vector, &err);
std::cout << "Op 1 read " << output_vector[0].diov_size << "bytes" << std::endl;
std::cout << "Op 2 read " << output_vector[1].diov_size << "bytes" << std::endl;
// do things with content in output_vector[0].diov_buffer etc
Write the contents of a remote file to a local file descriptor.
Context c;
DavixError* err = NULL;
DavFile file(c, Uri("http://example.org/dir1/file_to_download"));
int fd = open("/tmp/local_file" O_WRONLY, O_CREAT);
// get full file
file.getToFd(NULL, fd, &err);
// get first 200 bytes from file
file.getToFd(NULL, fd, 200, &err);
Download parts of a file with a single-range GET
Context c;
char buffer[255];
DavFile file(c, Uri("http://example.org/dir1/file_to_download"));
// get 100 bytes from http://example.org/dir1/file_to_download at offset 200
file.readPartial(NULL, buffer, 100, 200);
Download full file contents to a dynamically allocated buffer.
Context c;
DavixError* err = NULL;
DavFile file(c, Uri("http://example.org/file_to_download"));
std::vector<char> buffer;
// warning, this operation has no size limit regarding the content
file.getFull(NULL, buffer, &err);
// do things with buffer
// ...
Create or replace a remote file with the contents of a file descriptor.
Context c;
DavFile file(c, Uri("http://example.org/file_to_create"));
int fd = open("/tmp/file_to_upload", O_RDONLY);
// get file size
struct stat st;
fstat(fd, &st);
// execute put
file.put(NULL, fd, static_cast<dav_size_t>(st.st_size));
Create or replace a remote file with the contents of a buffer.
Context c;
DavFile file(c, Uri("http://example.org/file_to_create"));
char buffer[255];
// fills buffer with something useful
// execute put
file.put(NULL, &buffer, static_cast<dav_size_t>sizeof(buffer));
Create or replace a remote file with contents provided by a callback function.
// data provider
int myDataProvider(void* buffer, dav_size_t max_size){
static dav_size_t content_size = 200;
if(max_size == 0)
return 0;
else{
char my_useful_content[255]={1};
int bytes_to_write = (max_size<content_size)?max_size:content_size;
memcpy(buffer, my_useful_content, bytes_to_write);
content_size -= bytes_to_write;
return bytes_to_write;
}
}
int main(int argc, char** argv){
Context c;
DavFile file(c, Uri("http://example.org/file_to_create"));
// set data provider callback
DataProviderFun dataCB = myDataProvider;
// execute put and write 100 bytes using data from callback
file.put(NULL, dataCB, 100);
}
Move a remote resource to another location.
Context c;
DavFile source(c, Uri("http://example.org/old_location"));
DavFile destination(c, Uri("http://example.org/new_location"));
source.move(NULL, destination);
Delete a collection or a directory.
Context c;
DavixError* err = NULL;
// delete a WebDAV collection
DavFile myDavCollection(c, Uri("davs://example.org/collection_to_delete"));
myDavCollection.deletion(NULL, &err);
// to delete a S3 bucket (note: bucket has to be empty or operation will fail)
// setup S3 authorisation keys
RequestParams params;
params.setAwsAuthorizationKeys("xxxxx", "yyyyy");
DavFile myS3Bucket(c, Uri("s3://bucket_to_delete.example.org"));
myS3Bucket.deletion(¶ms, &err);
Create a collection or directory.
Context c;
DavixError* err = NULL;
// Instantiate RequestParams object to hold request options
RequestParams params;
// to create a WebDav collection
DavFile myDavCollection(c, Uri("dav://example.org/collection_to_create"));
myDavCollection.makeCollection(NULL, &err);
// to create a new S3 bucket
// first we need to setup S3 authorisation keys for this request
params.setAwsAuthorizationKeys("xxxxx", "yyyyy");
DavFile myS3Bucket(c, Uri("s3://bucket_to_create.example.org"));
myS3Bucket.makeCollection(¶ms, &err);
Query basic file metadata.
Contect c;
DavFile file(c, Uri("http://example.org/dir/file_to_stat"));
StatInfo info;
file.stat(NULL, info);
std::cout << "my file is " << info.size << " bytes large " << std::endl;
std::cout << " mode : 0" << std::oct << info.mode << std::endl;
std::cout << " atime : " << info.atime << std::endl;
std::cout << " mtime : " << info.mtime << std::endl;
std::cout << " ctime : " << info.ctime << std::endl;
List the contents of a collection.
Contect c;
DavFile file(c, Uri("http://example.org/collection_to_list"));
DavFile::Iterator it = file.listCollection(NULL);
// prints out entries' name
do {
std::cout << it.name() << std::endl;
}while(it.next());
Calculate a checksum
Context c;
DavFile file(c, Uri("http://example.org/file_to_checksum"));
std::string chk;
// calculate MD5, also supports CRC32, ADLER32
file.checksum(NULL, chk, "MD5", &err);
std::cout << "MD5 " << chk << std::endl;
POSIX interface
Instantiate a new DavPosix
Context c;
DavPosix pos(&c);
Query basic file metadata
Contect c;
DavixError* err = NULL;
DavPosix pos(&c);
struct stat info;
pos.stat(NULL, "http://example.org/file_to_stat", &info, &err);
std::cout << " atime : " << info.st_atime << std::endl;
std::cout << " mtime : " << info.st_mtime << std::endl;
std::cout << " ctime : " << info.st_ctime << std::endl;
std::cout << " mode : 0" << std::oct << info.st_mode << std::endl;
std::cout << " len : " << info.st_size << std::endl;
Open and read a collection
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
DAVIX_DIR* fd;
struct dirent* entry;
fd = pos.opendir(NULL, "dav://example.org/collection_to_open", &err);
while(entry = pos.readdir(fd, &err)){
std::cout << entry->d_name << std::endl;
}
pos.closedir(fd, &err);
Open and read a collection with per-entry metadata
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
DAVIX_DIR* fd;
struct dirent* entry;
struct stat info;
fd = posix.opendirpp(NULL, "dav://example.org/collection_to_open", &err);
while(entry = pos.readdirpp(fd, &info, &err)){
std::cout << entry->d_name << "is " << info.st_size << "bytes in size." << std::endl;
}
pos.closedirpp(fd, &err);
Create a collection or directory
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
pos.mkdir(NULL, "dav://example.org/collection_to_create", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH, &err);
Rename a file or collection
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
pos.rename(NULL, "http://example.org/myfolder/old_file_name", "http://example.org/myfolder/new_file_name", &err);
Remove a file
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
pos.unlink(NULL, "http://example.org/file_to_delete", &err);
Remove a collection or directory
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
pos.rmdir(NULL, "dav://example.org/collection_to_remove", &err);
Open a file for random I/O (read, partial read, and write)
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
DAVIX_FD* fd;
fd = pos.open(NULL, "http://example.org/myfile", O_RDONLY, &err);
// read 200 bytes from myfile
char buffer[255];
pos.read(fd, &buffer, 200, &err);
// read 50 bytes from myfile at offset 100
char buffer2[255];
pos.pread(fd, &buffer2, 50, 100, &err);
pos.close(fd);
// create a new file and write 200 bytes from buffer to it
fd = pos.open(NULL, "http://example.org/myfolder/mynewfile", O_WRONLY | O_CREAT, &err);
pos.write(fd, &buffer, 200);
pos.close(fd);
Vectored read - carry out several read operations in one single request, if the server supports it
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
int number_of_vector = 2;
DavIOVecInput input_vector[number_of_vector];
DavIOVecOuput output_vector[number_of_vector];
DAVIX_FD* fd;
fd = pos.open(NULL, "http://example.org/myfile", O_RDONLY, &err);
// Setup vector operations parameters
char buf1[255] = {0};
char buf2[255] = {0};
input_vector[0].diov_offset = 100;
input_vector[0].diov_size = 200;
input_vector[0].diov_buffer = buf1;
input_vector[1].diov_offset = 600;
input_vector[1].diov_size = 150;
input_vector[1].diov_buffer = buf2;
// execute query
pos.preadVec(fd, input_vector, output_vector, number_of_vector, &err);
std::cout << "Op 1 read " << output_vector[0].diov_size << "bytes" << std::endl;
std::cout << "Op 2 read " << output_vector[1].diov_size << "bytes" << std::endl;
// do things with content in output_vector[0].diov_buffer etc
pos.close(fd);
Re-position read/write file offset
Context c;
DavixError* err = NULL;
DavPosix pos(&c);
DAVIX_FD* fd;
fd = pos.open(NULL, "http://example.com/myfile", O_RDONLY, &err);
// position cursor to 200 bytes offset
lseek(fd, 200, SEEK_SET, &err);
// position cursor to current location plus 100 offset
lseek(fd, 100, SEEK_CUR, &err);
// position cursor to end of the file plus offset 200
lseek(fd, 200, SEEK_END, &err);
pos.close(fd);
HTTP requests
The Davix::HttpRequest
interface allows you to construct, customise and execute HTTP requests.
It also provides methods for retrieving server responses.
Requests can be executed in two ways:
Using the
executeRequest()
method, which will execute the entire request immediately.Using the
beginRequest()
function, which will initiate a multi-part request. This should be used for requests that expect a large answer. Note that requests initiated bybeginRequest()
should be closed by using theendRequest()
.Instantiate a new HttpRequest
Context c;
DavixError* err = NULL;
HttpRequest myrequest(c, "http://example.org/some_useful_stuff", &err);
Set the request method
myrequest.setRequestMethod("GET");
Configure request parameters
RequestParams params;
params.setUserAgent("MyAwesomeApp");
params.setClientLoginPassword("my_login_name", "my_uber_secure_password");
// ...
myrequest.setParameters(params);
Add custom header field
myrequest.addHeaderField("Accept", "application/metalink4+xml");
Set the request body
// from a string
std::string content_string
myrequest.setRequestBody(content_string);
// from a buffer
char buffer [255];
// fills buffer with something useful
myrequest.setRequestBody(&buffer, sizeof(buffer));
// from a file descriptor, at offset 100 for 200 bytes
int fd = open("/tmp/myfile", O_RDONLY);
myrequest.setRequestBody(fd, 100, 200);
close(fd);
Execute a full request
myrequest.executeRequest(&err);
Start a multi-part HTTP request
myrequest.beginRequest(&err);
End a multi-part HTTP request
myrequest.endRequest(&err);
Read a block of size n bytes from the answer
// read max n bytes to static buffer
char buffer[255];
myrequest.readBlock(&buffer, n, &err);
// read to dynamically sized buffer, with max size n
std::vector<char> buffer2;
myrequest.readBlock(&buffer2, n, &err);
Read a segment of size n from the answer
// readSegment calls readBlock repeatedly until n size is read, or end of answer
char buffer[50*1024];
myrequest.readSegment(&buffer, n, &err);
Read a line of text from the answer, with a maximum size of n
char buffer[255];
myrequest.readLine(&buffer, n, &err);
Write the answer contents to a file descriptor
char buffer[255]
int fd = open("tmp/myfile", O_WRONLY | O_CREAT);
// with no size limit
myrequest.readToFd(fd, &err);
// with 100 bytes limit
myrequest.readToFd(fd, 100, &err);
Get size of answer
dav_ssize_t size;
size = myrequest.getAnswerSize();
Get response body
// into dynamically sized buffer
std::vector<char> buffer1;
buffer1 = myrequest.getAnswerContentVec();
// into static buffer
const char* buffer2 = myrequest.getAnswerContent();
Get the status code of the response
int code;
code = myrequest.getRequestCode();
Get last modified time
time_t last_modified;
last_modified = myrequest.getLastModified();
Get the value associated with a particular header key
std::string value;
myrequest.getAnswerHeader("Content-Type", &value);
std::cout << "Content-Type is " << value << std::endl;
Get all header fields into a vector
HeaderVec headers;
myrequest.getAnswerHeaders(headers);
for(HeaderVec::iterator it = headers.begin(), it < headers.end(); ++it){
std::cout << it->first << ": " << it->second << std::endl;
}
Clear the HttpRequest answer buffer
myrequest.clearAnswerContent();
Process then discard the response body
// calls readSegment on the answer repeatedly but do nothing with content
myrequest.discardBody(&err);
Use pre-configured requests for specific HTTP operations
Context c;
DavixError* err = NULL;
Uri myuri("http://example.org/myfile");
// Get request
GetRequest req(c, myuri, &err);
// Put request
PutRequest req(c, myuri, &err);
// Head request
HeadRequest req(c, myuri, &err);
// Delete request
DeleteRequest req(c, myuri, &err);
// Propfind request
ProfindRequest req(c, myuri, &err);
Error reporting and exceptions
Davix uses an error reporting system similar to Glib, relying on Davix::DavixError
objects to store the scope where an error occurred,
the error code, and the error message.
The DavixError
objects can be checked on local level, or passed into other functions for error handling, or be propagated back up the stack frame.
Davix also provides a Davix::DavixException
class that encapsulates DavixError
, for situations where exceptions are more appropriate.
Most functions in the Davix::DavFile
API provide an exception safe version that takes a DavixError*
as argument, as well as a version that throws DavixException
and does not require DavixError
.
Davix::DavixError
The DavixError
error reporting system can be used when exception throwing behavior is not desirable.
A DavixError
object should not be instantiated manually, the DavixError::setupError()
function should be used where an error has occurred.
Most functions provided by the APIs accept a pointer to the DavixError
type, which if set to NULL
, will bypasses the error reporting system. In the event where an error occurs, a new DavixError
object is created and its address assigned to the DavixError*
passed into the function.
Context c;
DavixError* err = NULL;
// delete a WebDAV collection
DavFile myDavCollection(c, Uri("davs://example.org/collection_to_delete"));
myDavCollection.deletion(NULL, &err);
// check if an error occurred
// if err is not NULL anymore, that means a DavixError object had been created
// if *err is not NULL, the object is valid
if(err && *err){
std::cerr << err->getErrScope() <<
" Error code: " << err->getStatus() <<
" Error: " << err->getErrMsg() << std::endl;
}
Davix::DavixException
DavixException
is the recommended error handling method when using the DavFile
API, it encapsulates a DavixError
object which holds information such as the scope where an error occurred, the error code, and the error message.
Throw a
DavixException
throw DavixException("Where", "What", "This is what has happened...");
Catch a
DavixException
TRY_DAVIX{
DavFile myDavCollection(c, Uri("davs://example.org/doomed_to_fail"));
myDavCollection.deletion(NULL);
}CATCH_DAVIX(&err){
std::cerr << err->getErrScope() <<
" Error code: " << err->getStatus() <<
" Error: " << err->getErrMsg() << std::endl;
// handle error or propagate
// ...
}