19 #include <apr_fnmatch.h>
23 #define AFW_IMPLEMENTATION_ID "vfs"
37 for (e = adaptor->vfs_map; e->key_z; e++) {
51 impl_read_file_object(
76 adjusted.s = object_id->s + vfs_entry->key.len;
77 adjusted.len = object_id->len - vfs_entry->key.len;
83 if (rv != APR_SUCCESS) {
85 if (APR_STATUS_IS_ENOENT(rv)) {
94 apr, rv,
"apr_stat() error", xctx);
98 if (finfo.filetype == APR_DIR) {
104 if (APR_STATUS_IS_ENOENT(rv)) {
109 if (rv != APR_SUCCESS) {
111 "apr_dir_open() %s failed.",
112 vfs_entry->string_z);
118 &self->pub.adaptor->adaptor_id,
119 &afw_vfs_s__AdaptiveFile_vfs,
129 &afw_vfs_s_vfsPath, vfs_path, xctx);
132 &afw_vfs_s_data, filenames, xctx);
136 rv = apr_dir_read(&finfo, APR_FINFO_NAME | APR_FINFO_TYPE, dir);
137 if (rv == APR_ENOENT || rv == 720018)
break;
139 if (rv != APR_SUCCESS) {
146 if (finfo.filetype == APR_DIR) {
148 if (strcmp(finfo.name,
".") == 0 ||
149 strcmp(finfo.name,
"..") == 0)
153 size = strlen(finfo.name) + 1;
155 buff[size - 1] =
'/';
156 memcpy(buff, finfo.name, size - 1);
164 else if (finfo.filetype == APR_REG) {
165 size = strlen(finfo.name);
167 memcpy(buff, finfo.name, size);
178 rv = apr_dir_close(dir);
179 if (rv != APR_SUCCESS) {
186 else if (finfo.filetype == APR_REG) {
187 fd = fopen(file_path_z,
"r");
190 size = (size_t)finfo.size;
192 size_read = fread(buff, 1, size, fd);
194 if (size_read == -1) {
196 "Error reading %s.", file_path_z);
200 &self->pub.adaptor->adaptor_id,
201 &afw_vfs_s__AdaptiveFile_vfs,
209 &afw_vfs_s_vfsPath, vfs_path, xctx);
214 &afw_vfs_s_data, data_string, xctx);
220 &afw_vfs_s_data, data_binary, xctx);
226 if (finfo.filetype == APR_DIR || finfo.filetype == APR_REG) {
229 if (finfo.atime != 0) {
234 &afw_vfs_s_timeAccessed,
240 if (finfo.ctime != 0) {
245 &afw_vfs_s_timeCreated,
251 if (finfo.mtime != 0) {
256 &afw_vfs_s_timeModified,
270 impl_process_directory(
291 if (APR_STATUS_IS_ENOENT(rv)) {
296 if (rv != APR_SUCCESS) {
298 "apr_dir_open() %s failed.",
299 vfs_entry->string_z);
309 rv = apr_dir_read(&finfo, APR_FINFO_NAME | APR_FINFO_TYPE, dir);
310 if (rv == APR_ENOENT || rv == 720018)
break;
312 if (rv != APR_SUCCESS) {
318 if (*(finfo.name) ==
'.') {
319 if (!ctx->includeHidden ||
320 (finfo.filetype == APR_DIR &&
321 (strcmp(finfo.name,
"./") == 0 ||
322 strcmp(finfo.name,
"../") == 0)))
329 if (ctx->recursive && finfo.filetype == APR_DIR) {
332 ctx->p, xctx,
"%s%s/", vfs_entry->key_z, finfo.name);
333 subdirectory_vfs_entry.key.len =
334 strlen(subdirectory_vfs_entry.key_z);
336 ctx->p, xctx,
"%s%s/", vfs_entry->string_z, finfo.name);
337 subdirectory_vfs_entry.string.len =
338 strlen(subdirectory_vfs_entry.string_z);
339 shortcut = impl_process_directory(
self,
340 ctx, &subdirectory_vfs_entry, xctx);
350 if (finfo.filetype == APR_REG && ctx->suffix) {
351 if (strlen(finfo.name) < ctx->suffix->len ||
367 "%s%s%s", vfs_entry->key_z, finfo.name,
368 finfo.filetype == APR_DIR ?
"/" :
"");
369 object = impl_read_file_object(
self, ctx->impl_request, vfs_entry,
370 object_id, object_p, xctx);
382 shortcut = ctx->original_callback(
object,
383 ctx->original_context, xctx);
396 rv = apr_dir_close(dir);
397 if (rv != APR_SUCCESS) {
409 afw_vfs_adaptor_internal_session_create(
421 self->pub.inf = &impl_afw_adaptor_session_inf;
423 self->pub.p = xctx->p;
475 ctx.impl_request = impl_request;
476 ctx.criteria = criteria;
477 ctx.original_context = context;
478 ctx.original_callback = callback;
479 ctx.suffix = &afw_s_a_empty_string;
482 if (
afw_utf8_equal(object_type_id, &afw_s__AdaptiveObjectType_)) {
483 short_circuit =
false;
485 &afw_s__AdaptiveObjectType_,
486 &afw_vfs_s__AdaptiveAdaptorTypeSpecific_vfs_retrieve_objects,
491 short_circuit = callback(
object, context, xctx);
494 if (!short_circuit) {
496 &afw_s__AdaptiveObjectType_,
497 &afw_vfs_s__AdaptiveFile_vfs,
502 short_circuit = callback(
object, context, xctx);
506 callback(NULL, context, xctx);
511 if (!
afw_utf8_equal(object_type_id, &afw_vfs_s__AdaptiveFile_vfs)) {
512 callback(NULL, context, xctx);
517 if (adaptor_type_specific) {
521 adaptor_type_specific, &afw_vfs_s_includeHidden, &found, xctx);
525 adaptor_type_specific, &afw_vfs_s_subdirectory, xctx);
535 "The subdirectory property of the adaptorTypeSpecific "
536 "parameter of retrieve_objects() can not start with '/', "
537 "must end with '/', and can not contain '\\', './' or '../'",
543 adaptor_type_specific, &afw_vfs_s_suffix, xctx);
547 adaptor_type_specific, &afw_vfs_s_recursive, &found, xctx);
551 for (vfs_entry = adaptor->vfs_map; vfs_entry->key_z; vfs_entry++)
558 subdirectory_vfs_entry.key.len =
559 strlen(subdirectory_vfs_entry.key_z);
564 subdirectory_vfs_entry.string.len =
565 strlen(subdirectory_vfs_entry.string_z);
570 impl_process_directory(
self, &ctx, &subdirectory_vfs_entry, xctx);
574 callback(NULL, context, xctx);
601 if (!
afw_utf8_equal(object_type_id, &afw_vfs_s__AdaptiveFile_vfs)) {
602 callback(NULL, context, xctx);
610 callback(NULL, context, xctx);
616 vfs_entry = impl_get_vfs_entry(
self, object_id, xctx);
619 object = impl_read_file_object(
self, impl_request,
620 vfs_entry, object_id, object_p, xctx);
625 callback(
object, context, xctx);
631 impl_determine_path_for_object_id(
649 *is_directory =
false;
652 vfs_entry = impl_get_vfs_entry(
self, object_id, xctx);
655 "object_id does not match anything in vfs map",
661 *is_directory =
true;
665 adjusted.s.s = object_id->s + vfs_entry->key.len;
666 adjusted.s.len = object_id->len - vfs_entry->key.len;
671 path->s.len = strlen(path->s_z);
676 if (APR_STATUS_IS_ENOENT(rv)) {
679 else if (rv != APR_SUCCESS) {
681 apr, rv,
"apr_stat() error", xctx);
702 if (finfo.filetype == APR_DIR) {
703 if (!*is_directory) {
706 " is directory so must end with '/'",
710 else if (finfo.filetype == APR_REG) {
714 " is a regular file so must not end with '/'",
721 " filetype is not allowed",
729 impl_write_data_to_file(
743 apr_size_t bytes_written;
752 "object must have a \"data\" property that is data type "
753 "string or hexBinary for vfs adaptor",
758 flag = APR_FOPEN_WRITE | APR_FOPEN_CREATE;
760 flag |= APR_FOPEN_BINARY;
765 flag |= APR_FOPEN_CREATE;
769 rv = apr_file_open(&fd, path_z, flag, APR_FPROT_OS_DEFAULT,
771 if (rv != APR_SUCCESS) {
773 "apr_file_open() error",
786 rv = apr_file_write_full(fd, buf, nbytes, &bytes_written);
788 if (rv != APR_SUCCESS) {
790 "apr_file_write_full() error",
795 if (adaptor->mark_executable) {
800 for (pattern = adaptor->mark_executable; pattern->s_z; pattern++) {
801 if (apr_fnmatch(pattern->s_z, vfs_path_z, 0) ==
804 rv = apr_file_attrs_set(path_z,
805 APR_FILE_ATTR_EXECUTABLE, APR_FILE_ATTR_EXECUTABLE,
807 if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
809 "apr_file_attrs_set() error",
841 if (!
afw_utf8_equal(object_type_id, &afw_vfs_s__AdaptiveFile_vfs)) {
843 "Only object type _AdaptiveFile_vfs is allowed by vfs adaptor",
848 impl_determine_path_for_object_id(
849 self, suggested_object_id,
false,
850 &path, &is_directory,
858 rv = apr_dir_make_recursive(path.s_z, APR_FPROT_OS_DEFAULT,
860 if (rv != APR_SUCCESS) {
862 "apr_dir_make_recursive() error",
870 impl_write_data_to_file(
self,
871 suggested_object_id, path.s_z, data,
true, xctx);
875 return suggested_object_id;
901 if (!
afw_utf8_equal(object_type_id, &afw_vfs_s__AdaptiveFile_vfs)) {
903 "Only object type _AdaptiveFile_vfs is allowed by vfs adaptor",
908 impl_determine_path_for_object_id(
909 self, object_id,
true,
910 &path, &is_directory,
916 "modify_object() is not allowed for a directory by vfs adaptor",
925 if ((*entry)->type != afw_adaptor_modify_entry_type_set_property) {
928 else if (!(*entry)->first_property_name_entry ||
929 (*entry)->first_property_name_entry->next)
935 &(*entry)->first_property_name_entry->property_name,
940 else if (*(entry + 1)) {
945 "modify_object() only supports "
946 "[[\"set_property\", \"data\", value]] for vfs adaptor",
951 impl_write_data_to_file(
self,
952 object_id, path.s_z, (*entry)->value,
false, xctx);
977 if (!
afw_utf8_equal(object_type_id, &afw_vfs_s__AdaptiveFile_vfs)) {
979 "Only object type _AdaptiveFile_vfs is allowed by vfs adaptor",
984 impl_determine_path_for_object_id(
985 self, object_id,
true,
986 &path, &is_directory,
992 "replace_object() is not allowed for a directory by vfs adaptor",
998 impl_write_data_to_file(
self,
999 object_id, path.s_z, data,
false, xctx);
1023 if (!
afw_utf8_equal(object_type_id, &afw_vfs_s__AdaptiveFile_vfs)) {
1025 "Only object type _AdaptiveFile_vfs is allowed",
1030 impl_determine_path_for_object_id(
1031 self, object_id,
true,
1032 &path, &is_directory,
1038 if (rv != APR_SUCCESS) {
1040 "apr_dir_remove() error",
1048 if (rv != APR_SUCCESS) {
1050 "apr_file_remove() error",
1077 impl_afw_adaptor_session_get_journal_interface(
1119 impl_afw_adaptor_session_get_object_type_cache_interface(
Adaptive Framework Core API.
Helpers for adaptor implementation development.
Interface afw_interface implementation declares.
Internal header for adaptor type vfs.
void impl_afw_adaptor_session_modify_object(const afw_adaptor_session_t *instance, const afw_adaptor_impl_request_t *impl_request, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, const afw_adaptor_modify_entry_t *const *entry, const afw_object_t *adaptor_type_specific, afw_xctx_t *xctx)
void impl_afw_adaptor_session_replace_object(const afw_adaptor_session_t *instance, const afw_adaptor_impl_request_t *impl_request, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, const afw_object_t *replacement_object, const afw_object_t *adaptor_type_specific, afw_xctx_t *xctx)
void impl_afw_adaptor_session_delete_object(const afw_adaptor_session_t *instance, const afw_adaptor_impl_request_t *impl_request, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, const afw_object_t *adaptor_type_specific, afw_xctx_t *xctx)
void impl_afw_adaptor_session_retrieve_objects(const afw_adaptor_session_t *instance, const afw_adaptor_impl_request_t *impl_request, const afw_utf8_t *object_type_id, const afw_query_criteria_t *criteria, void *context, afw_object_cb_t callback, const afw_object_t *adaptor_type_specific, const afw_pool_t *p, afw_xctx_t *xctx)
const afw_adaptor_transaction_t * impl_afw_adaptor_session_begin_transaction(const afw_adaptor_session_t *instance, afw_xctx_t *xctx)
void impl_afw_adaptor_session_destroy(const afw_adaptor_session_t *instance, afw_xctx_t *xctx)
const afw_adaptor_impl_index_t * impl_afw_adaptor_session_get_index_interface(const afw_adaptor_session_t *instance, afw_xctx_t *xctx)
const afw_utf8_t * impl_afw_adaptor_session_add_object(const afw_adaptor_session_t *instance, const afw_adaptor_impl_request_t *impl_request, const afw_utf8_t *object_type_id, const afw_utf8_t *suggested_object_id, const afw_object_t *object, const afw_object_t *adaptor_type_specific, afw_xctx_t *xctx)
void impl_afw_adaptor_session_get_object(const afw_adaptor_session_t *instance, const afw_adaptor_impl_request_t *impl_request, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, void *context, afw_object_cb_t callback, const afw_object_t *adaptor_type_specific, const afw_pool_t *p, afw_xctx_t *xctx)
const afw_adaptor_key_value_t * impl_afw_adaptor_session_get_key_value_interface(const afw_adaptor_session_t *instance, afw_xctx_t *xctx)
afw_object_set_property_as_anyURI(const afw_object_t *object, const afw_utf8_t *property_name, const afw_utf8_t *internal, afw_xctx_t *xctx)
Set property function for data type anyURI values.
#define afw_object_old_get_property_as_boolean(object, property_name, found, xctx)
Get property function for data type boolean value.
afw_value_allocate_dateTime(const afw_pool_t *p, afw_xctx_t *xctx)
Allocate function for unmanaged data type dateTime value.
#define afw_value_is_hexBinary(A_VALUE)
Macro to determine if value is evaluated hexBinary.
afw_object_set_property_as_hexBinary(const afw_object_t *object, const afw_utf8_t *property_name, const afw_memory_t *internal, afw_xctx_t *xctx)
Set property function for data type hexBinary values.
afw_object_set_property_as_list(const afw_object_t *object, const afw_utf8_t *property_name, const afw_list_t *internal, afw_xctx_t *xctx)
Set property function for data type list values.
afw_value_create_string(const afw_utf8_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type string value.
#define afw_object_old_get_property_as_string(object, property_name, xctx)
Get property function for data type string value.
afw_data_type_string
Data type struct for string.
#define afw_value_is_string(A_VALUE)
Macro to determine if value is evaluated string.
afw_object_set_property_as_string(const afw_object_t *object, const afw_utf8_t *property_name, const afw_utf8_t *internal, afw_xctx_t *xctx)
Set property function for data type string values.
#define AFW_UTF8_FMT_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify arg.
afw_boolean_t(* afw_object_cb_t)(const afw_object_t *object, void *context, afw_xctx_t *xctx)
Typedef for afw_adaptor_session_object callback.
#define AFW_UTF8_FMT_OPTIONAL_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify optional arg.
unsigned char afw_byte_t
A byte of memory (unsigned).
#define AFW_UTF8_FMT
Format string specifier used for afw_utf8_t.
afw_utf8_octet_t afw_utf8_z_t
NFC normalized UTF-8 null terminated string.
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
apr_size_t afw_size_t
size_t.
#define AFW_THROW_ERROR_RV_Z(code, rv_source_id, rv, message_z, xctx)
Macro used to set error and rv in xctx and throw it.
#define AFW_THROW_ERROR_FZ(code, xctx, format_z,...)
Macro used to set error and 0 rv in xctx and throw it.
#define AFW_THROW_ERROR_RV_FZ(code, rv_source_id, rv, xctx, format_z,...)
Macro used to set error and rv in xctx and throw it.
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
afw_list_add_value(const afw_list_t *instance, const afw_value_t *value, afw_xctx_t *xctx)
Call method add_value of interface afw_list_setter.
#define afw_list_of_create(data_type, p, xctx)
Create an list of a specific data type in memory.
#define afw_memory_clear(to)
Clear preallocated memory for sizeof(*(to)).
const afw_memory_t * afw_memory_create(const afw_byte_t *ptr, afw_size_t size, const afw_pool_t *p, afw_xctx_t *xctx)
Create a afw_memory_t struct for a ptr and size.
#define afw_memory_copy(to, from)
Copy to preallocated memory of same type.
#define afw_object_get_property(instance, property_name, xctx)
Call method get_property of interface afw_object.
afw_object_set_property(const afw_object_t *instance, const afw_utf8_t *property_name, const afw_value_t *value, afw_xctx_t *xctx)
Set the value of an object's property.
#define afw_object_create_and_cede_p(p, xctx)
Create an empty entity object in memory in specified pool and cede control of the pool to the object.
#define afw_pool_malloc(instance, size, xctx)
Call method malloc of interface afw_pool.
#define afw_pool_get_apr_pool(instance)
Call method get_apr_pool of interface afw_pool.
#define afw_pool_release(instance, xctx)
Call method release of interface afw_pool.
const afw_pool_t * afw_pool_create(const afw_pool_t *parent, afw_xctx_t *xctx)
Create a new pool.
afw_query_criteria_test_object(const afw_object_t *obj, const afw_query_criteria_t *criteria, const afw_pool_t *p, afw_xctx_t *xctx)
Test object against query criteria.
afw_runtime_get_object(const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, afw_xctx_t *xctx)
Get a runtime object.
void afw_dateTime_set_from_apr_time(afw_dateTime_t *dateTime, apr_time_t apr_time, afw_xctx_t *xctx)
Set afw_dateTime_t from apr_time.
afw_utf8_ends_with(const afw_utf8_t *string, const afw_utf8_t *ends_with)
Check to see if a string ends with another string.
afw_boolean_t afw_utf8_equal(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string equals another string.
const afw_utf8_z_t * afw_utf8_z_printf(const afw_pool_t *p, afw_xctx_t *xctx, const afw_utf8_z_t *format_z,...)
afw_utf8_printf(const afw_pool_t *p, afw_xctx_t *xctx, const afw_utf8_z_t *format,...)
Create a utf-8 string using a c format string in specified pool.
afw_utf8_contains(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string contains another string.
afw_boolean_t afw_utf8_starts_with(const afw_utf8_t *string, const afw_utf8_t *starts_with)
Check to see if a string starts with another string.
#define afw_utf8_is_valid(s, len, xctx)
Determine if series of bytes is valid utf-8.
#define afw_utf8_create(s, len, p, xctx)
Create utf-8 string without copy unless necessary in pool specified.
afw_value_true
Adaptive value true.
#define afw_xctx_calloc_type(type, xctx)
Macro to allocate cleared memory to hold type in xctx's pool.
Interface afw_adaptor_impl_index public struct.
Internal request info used by afw_adaptor_impl*() functions.
Interface afw_adaptor_journal public struct.
Interface afw_adaptor_key_value public struct.
Interface afw_adaptor_object_type_cache public struct.
Interface afw_adaptor public struct.
Interface afw_adaptor_session public struct.
Interface afw_adaptor_transaction public struct.
Typedef for key/string pair that have both utf8 and utf8_z.
Interface afw_list public struct.
Struct for memory pointer and size.
Interface afw_object public struct.
Interface afw_pool public struct.
NFC normalized UTF-8 string.
struct for data type dateTime values.
struct for data type hexBinary values.
Interface afw_value public struct.
struct for data type string values.
Interface afw_xctx public struct.
NFC normalized UTF-8 string accessible as afw_utf8_t or afw_utf8_z_t.