summaryrefslogtreecommitdiff
path: root/riscos
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2014-05-07 16:14:18 +0100
committerVincent Sanders <vince@kyllikki.org>2014-05-07 16:24:51 +0100
commitc56642819eed87431dff3446fe111f7f3eefaa7d (patch)
tree397126ca4baac425f9c1c44f3d5c56c681e2c4fe /riscos
parentc1e2da80dfa62793ea107cf12408c814e268a54b (diff)
downloadnetsurf-c56642819eed87431dff3446fe111f7f3eefaa7d.tar.gz
netsurf-c56642819eed87431dff3446fe111f7f3eefaa7d.tar.bz2
add file operations table and make all frontends use it.
This rationalises the path construction and basename file operations. The default implementation is POSIX which works for all frontends except windows, riscos and amiga which have differeing path separators and rules. These implementations are significantly more robust than the previous nine implementations and also do not use unsafe strncpy or buffers with arbitrary length limits. These implementations also carry full documentation comments.
Diffstat (limited to 'riscos')
-rw-r--r--riscos/gui.c188
1 files changed, 143 insertions, 45 deletions
diff --git a/riscos/gui.c b/riscos/gui.c
index db57ff68a..6447e4d90 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -67,6 +67,7 @@
#include "desktop/save_complete.h"
#include "desktop/treeview.h"
#include "render/font.h"
+#include "utils/file.h"
#include "riscos/content-handlers/artworks.h"
#include "riscos/bitmap.h"
@@ -2285,77 +2286,173 @@ void PDF_Password(char **owner_pass, char **user_pass, char *path)
*owner_pass = NULL;
}
+
+#define DIR_SEP ('.')
+
/**
- * Return the filename part of a full path
+ * Generate a riscos path from one or more component elemnts.
+ *
+ * Constructs a complete path element from passed components. The
+ * second (and subsequent) components have a slash substituted for all
+ * riscos directory separators.
*
- * \param path full path and filename
- * \return filename (will be freed with free())
+ * If a string is allocated it must be freed by the caller.
+ *
+ * @param[in,out] str pointer to string pointer if this is NULL enough
+ * storage will be allocated for the complete path.
+ * @param[in,out] size The size of the space available if \a str not
+ * NULL on input and if not NULL set to the total
+ * output length on output.
+ * @param[in] nemb The number of elements.
+ * @param[in] ap The elements of the path as string pointers.
+ * @return NSERROR_OK and the complete path is written to str
+ * or error code on faliure.
*/
-
-static char *filename_from_path(char *path)
+static nserror riscos_mkpath(char **str, size_t *size, size_t nelm, va_list ap)
{
- char *leafname;
- char *temp;
- int leaflen;
+ const char *elm[16];
+ size_t elm_len[16];
+ size_t elm_idx;
+ char *fname;
+ size_t fname_len = 0;
+ char *curp;
+ size_t idx;
+
+ /* check the parameters are all sensible */
+ if ((nelm == 0) || (nelm > 16)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if ((*str != NULL) && (size == NULL)) {
+ /* if the caller is providing the buffer they must say
+ * how much space is available.
+ */
+ return NSERROR_BAD_PARAMETER;
+ }
- temp = strrchr(path, '.');
- if (!temp)
- temp = path; /* already leafname */
- else
- temp += 1;
+ /* calculate how much storage we need for the complete path
+ * with all the elements.
+ */
+ for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
+ elm[elm_idx] = va_arg(ap, const char *);
+ elm_len[elm_idx] = strlen(elm[elm_idx]);
+ fname_len += elm_len[elm_idx];
+ }
+ fname_len += nelm; /* allow for separators and terminator */
+
+ /* ensure there is enough space */
+ fname = *str;
+ if (fname != NULL) {
+ if (fname_len > *size) {
+ return NSERROR_NOSPACE;
+ }
+ } else {
+ fname = malloc(fname_len);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ }
- leaflen = strlen(temp);
+ /* copy the elements in with directory separator */
+ curp = fname;
- leafname = malloc(leaflen + 1);
- if (!leafname) {
- LOG(("malloc failed"));
- return NULL;
+ /* first element is not altered */
+ memmove(curp, elm[elm_idx], elm_len[elm_idx]);
+ curp += elm_len[elm_idx];
+ /* ensure there is a delimiter */
+ if (curp[-1] != DIR_SEP) {
+ *curp = DIR_SEP;
+ curp++;
}
- memcpy(leafname, temp, leaflen + 1);
- /* and s/\//\./g */
- for (temp = leafname; *temp; temp++)
- if (*temp == '/')
- *temp = '.';
+ /* subsequent elemnts have slashes substituted with directory
+ * separators.
+ */
+ for (elm_idx = 1; elm_idx < nelm; elm_idx++) {
+ for (idx = 0; idx < elm_len[elm_idx]; idx++) {
+ if (elm[elm_idx][idx] == DIR_SEP) {
+ *curp = '/';
+ } else {
+ *curp = elm[elm_idx][idx];
+ }
+ curp++;
+ }
+ *curp = DIR_SEP;
+ curp++;
+ }
+ curp[-1] = 0; /* NULL terminate */
+
+ assert((curp - fname) <= (int)fname_len);
+
+ *str = fname;
+ if (size != NULL) {
+ *size = fname_len;
+ }
+
+ return NSERROR_OK;
- return leafname;
}
+
/**
- * Add a path component/filename to an existing path
+ * Get the basename of a file using posix path handling.
+ *
+ * This gets the last element of a path and returns it. The returned
+ * element has all forward slashes translated into riscos directory
+ * separators.
*
- * \param path buffer containing platform-native format path + free space
- * \param length length of buffer "path"
- * \param newpart string containing unix-format path component to add to path
- * \return true on success
+ * @param[in] path The path to extract the name from.
+ * @param[in,out] str Pointer to string pointer if this is NULL enough
+ * storage will be allocated for the path element.
+ * @param[in,out] size The size of the space available if \a
+ * str not NULL on input and set to the total
+ * output length on output.
+ * @return NSERROR_OK and the complete path is written to str
+ * or error code on faliure.
*/
-
-static bool path_add_part(char *path, int length, const char *newpart)
+static nserror riscos_basename(const char *path, char **str, size_t *size)
{
- size_t path_len = strlen(path);
+ const char *leafname;
+ char *fname;
+ char *temp;
- /* Append directory separator, if there isn't one */
- if (path[path_len - 1] != '.') {
- strncat(path, ".", length);
- path_len += 1;
+ if (path == NULL) {
+ return NSERROR_BAD_PARAMETER;
}
- strncat(path, newpart, length);
+ leafname = strrchr(path, DIR_SEP);
+ if (!leafname) {
+ leafname = path;
+ } else {
+ leafname += 1;
+ }
- /* Newpart is either a directory name, or a file leafname
- * Either way, we must replace all dots with forward slashes */
- for (path = path + path_len; *path; path++) {
- if (*path == '.')
- *path = '/';
+ fname = strdup(leafname);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
}
- return true;
+ /** @todo check this leafname translation is actually required */
+ /* and s/\//\./g */
+ for (temp = fname; *temp != 0; temp++) {
+ if (*temp == '/') {
+ *temp = DIR_SEP;
+ }
+ }
+
+ *str = fname;
+ if (size != NULL) {
+ *size = strlen(fname);
+ }
+ return NSERROR_OK;
}
+static struct gui_file_table riscos_file_table = {
+ .mkpath = riscos_mkpath,
+ .basename = riscos_basename,
+};
+
static struct gui_fetch_table riscos_fetch_table = {
- .filename_from_path = filename_from_path,
- .path_add_part = path_add_part,
.filetype = fetch_filetype,
.path_to_url = path_to_url,
.url_to_path = url_to_path,
@@ -2392,6 +2489,7 @@ int main(int argc, char** argv)
.clipboard = riscos_clipboard_table,
.download = riscos_download_table,
.fetch = &riscos_fetch_table,
+ .file = &riscos_file_table,
.utf8 = riscos_utf8_table,
.search = riscos_search_table,
};