Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_vfs_adaptor.c
Go to the documentation of this file.
1 /* Interface afw_adaptor Implementation for vfs */
2 // See the 'COPYING' file in the project root for licensing information.
3 /*
4  * Adaptive Framework
5  *
6  * Copyright (c) 2010-2023 Clemson University
7  *
8  */
9 
10 
11 
17 #include "afw.h"
18 #include "afw_adaptor_impl.h"
20 
21 
22 /* Declares and rti/inf defines for interface afw_adaptor */
23 #define AFW_IMPLEMENTATION_ID "vfs"
25 
26 
27 /* Create an instance of the adaptor. */
28 const afw_adaptor_t *
29 afw_vfs_adaptor_internal_create_cede_p(
30  const afw_object_t *properties,
31  const afw_pool_t *p, afw_xctx_t *xctx)
32 {
34  afw_adaptor_t *adaptor;
35  const afw_list_t *vfs_map;
36  const afw_list_t *x_list;
37  afw_utf8_utf8_z_t *mark_executable;
38  const afw_iterator_t *iterator;
39  afw_key_z_string_z_t *entries;
41  afw_key_z_string_z_t temp_entry;
42  const afw_value_t *value;
43  const afw_utf8_t *entry;
44  const afw_utf8_octet_t *c;
45  const afw_utf8_octet_t *end_c;
46  afw_size_t count;
47  apr_finfo_t finfo;
48  apr_status_t rv;
49 
50  /* Create adaptor and process common properties. */
52  &impl_afw_adaptor_inf,
54  properties, p, xctx);
55  p = adaptor->p;
56  self = (afw_vfs_adaptor_internal_t *)adaptor;
57 
58  /* Get vfsMap property. */
60  adaptor->properties, &afw_vfs_s_vfsMap, xctx);
61  count = 0;
62  if (vfs_map) {
63  count = afw_list_get_count(vfs_map, xctx);
64  }
65  if (count == 0) {
66  AFW_THROW_ERROR_Z(general,
67  "At least one \"vfsMap\" entry must be specified",
68  xctx);
69  }
70 
71  /* Allocate memory for entries. */
72  entries = afw_pool_calloc(p,
73  (count + 1) * sizeof(afw_key_z_string_z_t), xctx);
74  self->vfs_map = entries;
75 
76  /* Add entries to allocated memory. */
77  for (iterator = NULL;;entries++) {
78 
79  /* Get next entry and parse until there are no more. */
80  value = afw_list_get_next_value(vfs_map, &iterator, p, xctx);
81  if (!value) {
82  break;
83  }
84  if (!afw_value_is_string(value)) {
85  AFW_THROW_ERROR_Z(general,
86  "\"vfsMap\" entries must be strings",
87  xctx);
88  }
89  entry = &((const afw_value_string_t *)value)->internal;
90  for (c = entry->s, end_c = c + entry->len;
91  c < end_c && *c != '=';
92  c++);
93  if (entry->s - c + 2 == entry->len) {
94  AFW_THROW_ERROR_Z(general,
95  "\"vfsMap\" entries must contain an equal ('=') "
96  "followed by a path",
97  xctx);
98  }
99  entries->key.len = c - entry->s;
100  entries->key_z =
101  afw_utf8_z_create(entry->s, entries->key.len, p, xctx);
102  entries->string.len = end_c - c - 1;
103  entries->string_z =
104  afw_utf8_z_create(c + 1, entries->string.len, p, xctx);
105 
106  /* Make sure <objectId_prefix> is empty or ends with '/'. */
107  if (entries->key.len > 0 &&
108  !afw_utf8_ends_with(&entries->key, &afw_s_a_slash))
109  {
110  AFW_THROW_ERROR_Z(general,
111  "The <objectId_prefix> in a vfsMap entry must be empty or end "
112  "with a slash ('/').",
113  xctx);
114  }
115 
116  /* Make sure <host file system directory path> ends with a '/' */
117  if (entries->string.len == 0 ||
118  !afw_utf8_ends_with(&entries->string, &afw_s_a_slash))
119  {
120 #if defined(_WIN32) || defined(WIN32)
121  if (!afw_utf8_ends_with(&entries->string, &afw_s_a_backslash)) {
122  AFW_THROW_ERROR_Z(general,
123  "The <host file system directory path> in a vfsMap entry "
124  "must end with a slash ('/') or a backslash ('\\')",
125  xctx);
126  }
127 #else
128  AFW_THROW_ERROR_Z(general,
129  "The <host file system directory path> in a vfsMap entry must "
130  "end with a slash ('/')",
131  xctx);
132 #endif
133  }
134 
135  /* Make sure <host file system directory path> is existing directory. */
136  rv = apr_stat(&finfo,
137  entries->string_z, APR_FINFO_TYPE, afw_pool_get_apr_pool(p));
138  if (rv != APR_SUCCESS || finfo.filetype != APR_DIR) {
139  AFW_THROW_ERROR_FZ(general, xctx,
140  "%s in vfsMap entry <host file system directory path> is not "
141  "a directory",
142  entries->string_z);
143  }
144 
145  /* Move new entry to its ordered place. */
146  for (e = entries; e > self->vfs_map; e--) {
147  if ((e - 1)->key.len > e->key.len ||
148  ((e - 1)->key.len == e->key.len &&
149  strcmp((e - 1)->key_z, e->key_z) < 0))
150  {
151  break;
152  }
153  if (strcmp((e - 1)->key_z, e->key_z) == 0) {
154  AFW_THROW_ERROR_Z(general,
155  "vfsMap has duplicate <objectId_prefix> values",
156  xctx);
157  }
158  afw_memory_copy(&temp_entry, e - 1);
159  afw_memory_copy(e - 1, e);
160  afw_memory_copy(e, &temp_entry);
161  }
162 
163  }
164 
165  /* Process markExecutable */
166  x_list = afw_object_old_get_property_as_list(adaptor->properties,
167  &afw_vfs_s_markExecutable, xctx);
168  count = 0;
169  if (x_list) {
170  count = afw_list_get_count(x_list, xctx);
171  }
172  if (count != 0) {
173  mark_executable = afw_pool_calloc(p,
174  (count + 1) * sizeof(afw_utf8_utf8_z_t), xctx);
175  self->mark_executable = mark_executable;
176 
177  for (iterator = NULL;; mark_executable++) {
178  value = afw_list_get_next_value(x_list, &iterator, p, xctx);
179  if (!value) {
180  break;
181  }
182  if (!afw_value_is_string(value)) {
183  AFW_THROW_ERROR_Z(general,
184  "\"executableSuffixes\" entries must be strings",
185  xctx);
186  }
187  mark_executable->s_z = afw_utf8_z_create(
188  (((const afw_value_string_t *)value)->internal).s,
189  (((const afw_value_string_t *)value)->internal).len,
190  p, xctx);
191  mark_executable->s.len = sizeof(mark_executable->s_z);
192  }
193  }
194 
195  /* Return adaptor. */
196  return adaptor;
197 }
198 
199 
200 
201 /*
202  * Implementation of method destroy for interface afw_adaptor.
203  */
204 void
206  const afw_adaptor_t * instance,
207  afw_xctx_t *xctx)
208 {
209  /*FIXME Add destroy code if needed. */
210 }
211 
212 
213 
214 /*
215  * Implementation of method create_adaptor_session for interface
216  * afw_adaptor.
217  */
218 const afw_adaptor_session_t *
220  const afw_adaptor_t *instance,
221  afw_xctx_t *xctx)
222 {
224  (afw_vfs_adaptor_internal_t *)instance;
225  const afw_adaptor_session_t *session;
226 
227  /* Create session and return. */
228  session = afw_vfs_adaptor_internal_session_create(
229  self, xctx);
230  return session;
231 }
232 
233 
234 
235 /*
236  * Implementation of method get_additional_metrics for interface
237  * afw_adaptor.
238  */
239 const afw_object_t *
241  const afw_adaptor_t * instance,
242  const afw_pool_t * p,
243  afw_xctx_t *xctx)
244 {
245  /* Add code if this implementation has additional metrics. */
246  return NULL;
247 }
Adaptive Framework Core API.
Helpers for adaptor implementation development.
Interface afw_interface implementation declares.
Internal header for adaptor type vfs.
const afw_object_t * impl_afw_adaptor_get_additional_metrics(const afw_adaptor_t *instance, const afw_pool_t *p, afw_xctx_t *xctx)
void impl_afw_adaptor_destroy(const afw_adaptor_t *instance, afw_xctx_t *xctx)
const afw_adaptor_session_t * impl_afw_adaptor_create_adaptor_session(const afw_adaptor_t *instance, afw_xctx_t *xctx)
afw_adaptor_impl_create_cede_p(const afw_adaptor_inf_t *inf, afw_size_t instance_size, const afw_object_t *properties, const afw_pool_t *p, afw_xctx_t *xctx)
Developers should call this in all create functions for afw_adaptor.
#define afw_object_old_get_property_as_list(object, property_name, xctx)
Get property function for data type list value.
#define afw_value_is_string(A_VALUE)
Macro to determine if value is evaluated string.
struct afw_iterator_s afw_iterator_t
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#define AFW_THROW_ERROR_FZ(code, xctx, format_z,...)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:319
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
#define afw_list_get_next_value(instance, iterator, p, xctx)
Call method get_next_value of interface afw_list.
#define afw_list_get_count(instance, xctx)
Call method get_count of interface afw_list.
#define afw_memory_copy(to, from)
Copy to preallocated memory of same type.
Definition: afw_memory.h:39
#define afw_pool_calloc(instance, size, xctx)
Call method calloc of interface afw_pool.
#define afw_pool_get_apr_pool(instance)
Call method get_apr_pool of interface afw_pool.
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.
Definition: afw_utf8.c:513
afw_utf8_z_create(const afw_utf8_octet_t *s, afw_size_t len, const afw_pool_t *p, afw_xctx_t *xctx)
Create a NFC Normalized zero terminated UTF-8 string in specified pool.
Definition: afw_utf8.c:366
Interface afw_adaptor public struct.
Interface afw_adaptor_session public struct.
Typedef for key/string pair that have both utf8 and utf8_z.
Definition: afw_common.h:698
Interface afw_list public struct.
Interface afw_object public struct.
Interface afw_pool public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
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.
Definition: afw_common.h:555