diff options
Diffstat (limited to 'firmware/target/hosted/filesystem-unix.c')
-rw-r--r-- | firmware/target/hosted/filesystem-unix.c | 202 |
1 files changed, 191 insertions, 11 deletions
diff --git a/firmware/target/hosted/filesystem-unix.c b/firmware/target/hosted/filesystem-unix.c index 8ac1d4ada9..907d6ab14e 100644 --- a/firmware/target/hosted/filesystem-unix.c +++ b/firmware/target/hosted/filesystem-unix.c | |||
@@ -18,24 +18,204 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #define RB_FILESYSTEM_OS | ||
22 | #include <sys/statfs.h> /* lowest common denominator */ | ||
23 | #include <sys/stat.h> | ||
24 | #include <string.h> | ||
25 | #include <errno.h> | ||
26 | #include "config.h" | ||
27 | #include "system.h" | ||
28 | #include "file.h" | ||
29 | #include "dir.h" | ||
30 | #include "mv.h" | ||
31 | #include "debug.h" | ||
32 | #include "pathfuncs.h" | ||
33 | #include "string-extra.h" | ||
21 | 34 | ||
22 | #include <sys/stat.h> /* stat() */ | 35 | #define SAME_FILE_INFO(sb1p, sb2p) \ |
23 | #include "mv.h" /* stat() */ | 36 | ((sb1p)->st_dev == (sb2p)->st_dev && (sb1p)->st_ino == (sb2p)->st_ino) |
24 | 37 | ||
25 | 38 | off_t os_filesize(int osfd) | |
26 | long filesize(int fd) | ||
27 | { | 39 | { |
28 | struct stat buf; | 40 | struct stat sb; |
29 | 41 | ||
30 | if (!fstat(fd, &buf)) | 42 | if (!os_fstat(osfd, &sb)) |
31 | return buf.st_size; | 43 | return sb.st_size; |
32 | else | 44 | else |
33 | return -1; | 45 | return -1; |
34 | } | 46 | } |
35 | 47 | ||
36 | /* do we really need this in the app? */ | 48 | int os_fsamefile(int osfd1, int osfd2) |
37 | void fat_size(IF_MV(int volume,) unsigned long* size, unsigned long* free) | 49 | { |
50 | struct stat sb1, sb2; | ||
51 | |||
52 | if (os_fstat(osfd1, &sb1)) | ||
53 | return -1; | ||
54 | |||
55 | if (os_fstat(osfd2, &sb2)) | ||
56 | return -1; | ||
57 | |||
58 | return SAME_FILE_INFO(&sb1, &sb2); | ||
59 | } | ||
60 | |||
61 | int os_relate(const char *ospath1, const char *ospath2) | ||
62 | { | ||
63 | DEBUGF("\"%s\" : \"%s\"\n", ospath1, ospath2); | ||
64 | |||
65 | if (!ospath2 || !*ospath2) | ||
66 | { | ||
67 | errno = ospath2 ? ENOENT : EFAULT; | ||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | /* First file must stay open for duration so that its stats don't change */ | ||
72 | int fd1 = os_open(ospath1, O_RDONLY); | ||
73 | if (fd1 < 0) | ||
74 | return -2; | ||
75 | |||
76 | struct stat sb1; | ||
77 | if (os_fstat(fd1, &sb1)) | ||
78 | { | ||
79 | os_close(fd1); | ||
80 | return -3; | ||
81 | } | ||
82 | |||
83 | char path2buf[strlen(ospath2) + 1]; | ||
84 | *path2buf = 0; | ||
85 | |||
86 | ssize_t len = 0; | ||
87 | const char *p = ospath2; | ||
88 | const char *sepmo = path_is_absolute(ospath2) ? PA_SEP_HARD : PA_SEP_SOFT; | ||
89 | |||
90 | int rc = RELATE_DIFFERENT; | ||
91 | |||
92 | while (1) | ||
93 | { | ||
94 | if (sepmo != PA_SEP_HARD && | ||
95 | !(len = parse_path_component(&ospath2, &p))) | ||
96 | { | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | char compname[len + 1]; | ||
101 | strmemcpy(compname, p, len); | ||
102 | |||
103 | path_append(path2buf, sepmo, compname, sizeof (path2buf)); | ||
104 | sepmo = PA_SEP_SOFT; | ||
105 | |||
106 | int errnum = errno; /* save and restore if not actually failing */ | ||
107 | struct stat sb2; | ||
108 | |||
109 | if (!os_stat(path2buf, &sb2)) | ||
110 | { | ||
111 | if (SAME_FILE_INFO(&sb1, &sb2)) | ||
112 | { | ||
113 | rc = RELATE_SAME; | ||
114 | } | ||
115 | else if (rc == RELATE_SAME) | ||
116 | { | ||
117 | if (name_is_dot_dot(compname)) | ||
118 | rc = RELATE_DIFFERENT; | ||
119 | else if (!name_is_dot(compname)) | ||
120 | rc = RELATE_PREFIX; | ||
121 | } | ||
122 | } | ||
123 | else if (errno == ENOENT && !*GOBBLE_PATH_SEPCH(ospath2) && | ||
124 | !name_is_dot_dot(compname)) | ||
125 | { | ||
126 | if (rc == RELATE_SAME) | ||
127 | rc = RELATE_PREFIX; | ||
128 | |||
129 | errno = errnum; | ||
130 | break; | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | rc = -4; | ||
135 | break; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | if (os_close(fd1) && rc >= 0) | ||
140 | rc = -5; | ||
141 | |||
142 | return rc; | ||
143 | } | ||
144 | |||
145 | bool os_file_exists(const char *ospath) | ||
146 | { | ||
147 | int sim_fd = os_open(ospath, O_RDONLY, 0); | ||
148 | if (sim_fd < 0) | ||
149 | return false; | ||
150 | |||
151 | int errnum = errno; | ||
152 | os_close(sim_fd); | ||
153 | errno = errnum; | ||
154 | |||
155 | return true; | ||
156 | } | ||
157 | |||
158 | int os_opendirfd(const char *osdirname) | ||
159 | { | ||
160 | return os_open(osdirname, O_RDONLY); | ||
161 | } | ||
162 | |||
163 | int os_opendir_and_fd(const char *osdirname, DIR **osdirpp, int *osfdp) | ||
164 | { | ||
165 | /* another possible way is to use open() then fdopendir() */ | ||
166 | *osdirpp = NULL; | ||
167 | *osfdp = -1; | ||
168 | |||
169 | DIR *dirp = os_opendir(osdirname); | ||
170 | if (!dirp) | ||
171 | return -1; | ||
172 | |||
173 | int rc = 0; | ||
174 | int errnum = errno; | ||
175 | |||
176 | int fd = os_dirfd(dirp); | ||
177 | if (fd < 0) | ||
178 | { | ||
179 | fd = os_opendirfd(osdirname); | ||
180 | rc = 1; | ||
181 | } | ||
182 | |||
183 | if (fd < 0) | ||
184 | { | ||
185 | os_closedir(dirp); | ||
186 | return -2; | ||
187 | } | ||
188 | |||
189 | errno = errnum; | ||
190 | |||
191 | *osdirpp = dirp; | ||
192 | *osfdp = fd; | ||
193 | |||
194 | return rc; | ||
195 | } | ||
196 | |||
197 | /* do we really need this in the app? (in the sim, yes) */ | ||
198 | void volume_size(IF_MV(int volume,) unsigned long *sizep, unsigned long *freep) | ||
38 | { | 199 | { |
39 | IF_MV((void) volume); | 200 | unsigned long size = 0, free = 0; |
40 | *size = *free = 0; | 201 | char volpath[MAX_PATH]; |
202 | struct statfs fs; | ||
203 | |||
204 | if (os_volume_path(IF_MV(volume,) volpath, sizeof (volpath)) >= 0 | ||
205 | && !statfs(volpath, &fs)) | ||
206 | { | ||
207 | DEBUGF("statvfs: frsize=%d blocks=%ld bfree=%ld\n", | ||
208 | (int)fs.f_frsize, (long)fs.f_blocks, (long)fs.f_bfree); | ||
209 | if (sizep) | ||
210 | size = (fs.f_blocks / 2) * (fs.f_frsize / 512); | ||
211 | |||
212 | if (freep) | ||
213 | free = (fs.f_bfree / 2) * (fs.f_frsize / 512); | ||
214 | } | ||
215 | |||
216 | if (sizep) | ||
217 | *sizep = size; | ||
218 | |||
219 | if (freep) | ||
220 | *freep = free; | ||
41 | } | 221 | } |