adding extern tags
[rrq/fuse_xattrs.git] / utils.c
1 /*
2   fuse_xattrs - Add xattrs support using sidecar files
3
4   Copyright (C) 2016  Felipe Barriga Richards <felipe {at} felipebarriga.cl>
5
6   This program can be distributed under the terms of the GNU GPL.
7   See the file COPYING.
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/stat.h>
14
15 #include "utils.h"
16 #include "fuse_xattrs_config.h"
17 #include "xattrs_config.h"
18
19 /* TODO: re-use memory to avoid calling malloc every time */
20 char *prepend_source_directory(const char *b) {
21     const size_t b_size = strlen(b);
22     const size_t dst_len = xattrs_config.source_dir_size + b_size + 1;
23     char *dst = (char*) malloc(sizeof(char) * dst_len);
24
25     memcpy(dst, xattrs_config.source_dir, xattrs_config.source_dir_size);
26     memcpy(dst+xattrs_config.source_dir_size, b, b_size + 1); // include '\0'
27     //sprintf(dst, "%s%s", a, b);
28
29     return dst;
30 }
31
32 int is_directory(const char *path) {
33     struct stat statbuf;
34     if (stat(path, &statbuf) != 0) {
35         fprintf(stderr, "cannot get source directory status: %s\n", path);
36         return -1;
37     }
38
39     if (!S_ISDIR(statbuf.st_mode)) {
40         fprintf(stderr, "source directory must be a directory: %s\n", path);
41         return -1;
42     }
43
44     return 1;
45 }
46
47 int is_regular_file(const char *path) {
48     struct stat statbuf;
49     if (stat(path, &statbuf) != 0) {
50         return -1;
51     }
52
53     if (!S_ISREG(statbuf.st_mode)) {
54         return -1;
55     }
56
57     return 1;
58 }
59
60 char *get_sidecar_path(const char *path)
61 {
62     const size_t path_len = strlen(path);
63     const size_t sidecar_ext_len = strlen(BINARY_SIDECAR_EXT); // this can be optimized
64     const size_t sidecar_path_len = path_len + sidecar_ext_len + 1;
65     char *sidecar_path = (char *) malloc(sidecar_path_len);
66     memset(sidecar_path, '\0', sidecar_path_len);
67     memcpy(sidecar_path, path, path_len);
68     memcpy(sidecar_path + path_len, BINARY_SIDECAR_EXT, sidecar_ext_len);
69
70     return sidecar_path;
71 }
72
73 // TODO: make it work for binary data
74 char *sanitize_value(const char *value, size_t value_size)
75 {
76     char *sanitized = malloc(value_size + 1);
77     memcpy(sanitized, value, value_size);
78     sanitized[value_size] = '\0';
79     return sanitized;
80 }
81
82
83 const size_t BINARY_SIDECAR_EXT_SIZE = strlen(BINARY_SIDECAR_EXT);
84
85 const int filename_is_sidecar(const char *string) {
86     if(string == NULL)
87         return 0;
88
89     size_t size = strlen(string);
90     if (size <= BINARY_SIDECAR_EXT_SIZE)
91         return 0;
92
93     if (memcmp(string+size-BINARY_SIDECAR_EXT_SIZE, BINARY_SIDECAR_EXT, BINARY_SIDECAR_EXT_SIZE) == 0) {
94         return 1;
95     }
96
97     return 0;
98 }
99
100 #define USER_NAMESPACE "user."
101 #define SYSTEM_NAMESPACE "system."
102 #define SECURITY_NAMESPACE "security."
103 #define TRUSTED_NAMESPACE "trusted."
104
105 const size_t USER_NAMESPACE_SIZE     = strlen(USER_NAMESPACE);
106 const size_t SYSTEM_NAMESPACE_SIZE   = strlen(SYSTEM_NAMESPACE);
107 const size_t SECURITY_NAMESPACE_SIZE = strlen(SECURITY_NAMESPACE);
108 const size_t THRUSTED_NAMESPACE_SIZE = strlen(TRUSTED_NAMESPACE);
109
110 enum namespace get_namespace(const char *name) {
111     size_t name_size = strlen(name);
112
113     if (name_size > USER_NAMESPACE_SIZE && memcmp(name, USER_NAMESPACE, USER_NAMESPACE_SIZE) == 0) {
114         return USER;
115     }
116
117     if (name_size > SYSTEM_NAMESPACE_SIZE && memcmp(name, SYSTEM_NAMESPACE, SYSTEM_NAMESPACE_SIZE) == 0) {
118         return SYSTEM;
119     }
120
121     if (name_size > SECURITY_NAMESPACE_SIZE && memcmp(name, SECURITY_NAMESPACE, SECURITY_NAMESPACE_SIZE) == 0) {
122         return SECURITY;
123     }
124
125     if (name_size > THRUSTED_NAMESPACE_SIZE && memcmp(name, TRUSTED_NAMESPACE, THRUSTED_NAMESPACE_SIZE) == 0) {
126         return TRUSTED;
127     }
128
129     error_print("invalid namespace for key: %s\n", name);
130     return ERROR;
131 }