dav/system.c

changeset 611
a7c48e0dca88
parent 608
3e4c0285a868
child 612
66dc8b992d8d
equal deleted inserted replaced
610:aa3baf1dd81b 611:a7c48e0dca88
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include <libidav/utils.h>
30
29 #include <stdio.h> 31 #include <stdio.h>
30 #include <stdlib.h> 32 #include <stdlib.h>
31 #include <string.h> 33 #include <string.h>
32 #include <dirent.h> 34 #include <dirent.h>
33 #include <sys/stat.h> 35 #include <sys/stat.h>
34 #include <sys/types.h> 36 #include <sys/types.h>
35 #include <errno.h> 37 #include <errno.h>
36 38
39 #include <ucx/string.h>
40
37 #ifndef _WIN32 41 #ifndef _WIN32
38 #include <unistd.h> 42 #include <unistd.h>
39 #endif 43 #endif
40 44
41 #include "system.h" 45 #include "system.h"
45 free(ent); 49 free(ent);
46 } 50 }
47 51
48 #ifndef _WIN32 52 #ifndef _WIN32
49 /* ---------- POSIX implementation ---------- */ 53 /* ---------- POSIX implementation ---------- */
54
55 void sys_init(void) {
56
57 }
58 void sys_uninit(void) {
59
60 }
50 61
51 SYS_DIR sys_opendir(const char *path) { 62 SYS_DIR sys_opendir(const char *path) {
52 DIR *dir = opendir(path); 63 DIR *dir = opendir(path);
53 if(!dir) { 64 if(!dir) {
54 return NULL; 65 return NULL;
94 105
95 int sys_lstat(const char *path, SYS_STAT *s) { 106 int sys_lstat(const char *path, SYS_STAT *s) {
96 return lstat(path, s); 107 return lstat(path, s);
97 } 108 }
98 109
110 int sys_islink(const char *path) {
111 struct stat s;
112 if(!lstat(path, &s)) {
113 return S_ISLNK(s.st_mode);
114 }
115 } return 0;
116
99 int sys_rename(const char *oldpath, const char *newpath) { 117 int sys_rename(const char *oldpath, const char *newpath) {
100 return rename(oldpath, newpath); 118 return rename(oldpath, newpath);
101 } 119 }
102 120
103 int sys_unlink(const char *path) { 121 int sys_unlink(const char *path) {
106 124
107 int sys_mkdir(const char *path) { 125 int sys_mkdir(const char *path) {
108 return mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 126 return mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
109 } 127 }
110 128
111 ssize_t sys_readlink(const char *path, char *buffer, size_t size) { 129 char* sys_readlink(const char *path, SYS_STAT *s) {
112 return readlink(path, buffer, size); 130 char *ret = NULL;
131
132 off_t l_sz = s->st_size + 16;
133 size_t lnksize = l_sz > 256 ? l_sz : 256;
134 char *lnkbuf = malloc(lnksize);
135
136 ssize_t len = 0;
137 for(int i=0;i<4;i++) {
138 // we try to read the link at most 4 times
139 // only repeat if the buffer is too small
140 len = readlink(path, lnkbuf, lnksize);
141 if(len < lnksize) {
142 ret = lnkbuf; // success
143 lnkbuf[len] = 0; // terminate buffer
144 break;
145 }
146 lnksize *= 2; // retry with bigger buffer
147 lnkbuf = realloc(lnkbuf, lnksize);
148 }
149
150 if(!ret) {
151 free(lnkbuf);
152 }
153 return ret;
113 } 154 }
114 155
115 int sys_symlink(const char *target, const char *linkpath) { 156 int sys_symlink(const char *target, const char *linkpath) {
116 int err = symlink(target, linkpath); 157 int err = symlink(target, linkpath);
117 if(err && errno == EEXIST) { 158 if(err && errno == EEXIST) {
123 return err; 164 return err;
124 } 165 }
125 166
126 #else 167 #else
127 /* ---------- Windows implementation ---------- */ 168 /* ---------- Windows implementation ---------- */
169
170 #include <windows.h>
171 #include <winnls.h>
172 #include <shobjidl.h>
173 #include <objbase.h>
174 #include <objidl.h>
175
176 #include <direct.h>
177 #include <wchar.h>
178
179 void sys_init(void) {
180 HRESULT res = CoInitialize(NULL);
181 if(res != S_OK) {
182 fprintf(stderr, "Error: CoInitialize failed\n");
183 }
184 }
185
186 void sys_uninit(void) {
187 CoUninitialize();
188 }
128 189
129 static wchar_t* path2winpath(const char *path, int dir, int *newlen) { 190 static wchar_t* path2winpath(const char *path, int dir, int *newlen) {
130 size_t len = strlen(path); 191 size_t len = strlen(path);
131 size_t lenadd = dir ? 2 : 0; 192 size_t lenadd = dir ? 2 : 0;
132 193
156 wpath[wlen++] = L'*'; 217 wpath[wlen++] = L'*';
157 } 218 }
158 wpath[wlen] = 0; 219 wpath[wlen] = 0;
159 220
160 return wpath; 221 return wpath;
161 } 222 }
223
224 static char* winpath2multibyte(const wchar_t *wpath, size_t wlen) {
225 size_t maxlen = wlen * 4;
226 char *ret = malloc(maxlen + 1);
227 int ret_len = WideCharToMultiByte(
228 CP_UTF8,
229 0,
230 wpath,
231 wlen,
232 ret,
233 maxlen,
234 NULL,
235 NULL);
236 ret[ret_len] = 0;
237 return ret;
238 }
239
240
162 241
163 SYS_DIR sys_opendir(const char *path) { 242 SYS_DIR sys_opendir(const char *path) {
164 struct WinDir *dir = malloc(sizeof(struct WinDir)); 243 struct WinDir *dir = malloc(sizeof(struct WinDir));
165 wchar_t *dirpath = path2winpath(path, TRUE, NULL); 244 wchar_t *dirpath = path2winpath(path, TRUE, NULL);
166 if(!dirpath) { 245 if(!dirpath) {
245 free(fpath); 324 free(fpath);
246 return ret; 325 return ret;
247 } 326 }
248 327
249 int sys_lstat(const char *path, SYS_STAT *s) { 328 int sys_lstat(const char *path, SYS_STAT *s) {
250 return sys_stat(path, s); // unsupported on windows 329 return sys_stat(path, s); // unsupported on windows
330 }
331
332 int sys_islink(const char *path) {
333 // don't use symlinks on windows, because it is not really useful
334 // however, we interpret .lnk files as symlinks
335 int ret = 0;
336
337 scstr_t path_s = scstr(path);
338 if(scstrsuffix(path_s, SC(".lnk"))) {
339 // looks like a .lnk file
340 // check content
341 IShellLink *sl;
342 HRESULT hres;
343 hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID*)&sl);
344 if(SUCCEEDED(hres)) {
345 IPersistFile *file;
346 hres = sl->lpVtbl->QueryInterface(sl, &IID_IPersistFile, (void**)&file);
347 if(!SUCCEEDED(hres)) {
348 sl->lpVtbl->Release(sl);
349 return ret;
350 }
351
352 int newlen = 0;
353 wchar_t *wpath = path2winpath(path, 0, &newlen);
354
355 hres = file->lpVtbl->Load(file, wpath, STGM_READ);
356 if(SUCCEEDED(hres)) {
357 ret = 1;
358 file->lpVtbl->Release(file);
359 }
360 free(wpath);
361
362 sl->lpVtbl->Release(sl);
363 }
364 }
365 return ret;
251 } 366 }
252 367
253 int sys_rename(const char *oldpath, const char *newpath) { 368 int sys_rename(const char *oldpath, const char *newpath) {
254 wchar_t *o = path2winpath(oldpath, FALSE, NULL); 369 wchar_t *o = path2winpath(oldpath, FALSE, NULL);
255 wchar_t *n = path2winpath(newpath, FALSE, NULL); 370 wchar_t *n = path2winpath(newpath, FALSE, NULL);
290 int ret = _wmkdir(wpath); 405 int ret = _wmkdir(wpath);
291 free(wpath); 406 free(wpath);
292 return ret; 407 return ret;
293 } 408 }
294 409
295 ssize_t sys_readlink(const char *path, char *buffer, size_t size) { 410 char* sys_readlink(const char *path, SYS_STAT *s) {
296 // TODO 411 char *ret_link = NULL;
297 fprintf(stderr, "sys_readlink: implement me\n"); 412
298 return 1; 413 // create COM object for using the ShellLink interface
414 IShellLinkW *sl;
415 HRESULT hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID*)&sl);
416 if(!SUCCEEDED(hres)) {
417 return NULL;
418 }
419
420 IPersistFile *file;
421 hres = sl->lpVtbl->QueryInterface(sl, &IID_IPersistFile, (void**)&file);
422 if(!SUCCEEDED(hres)) {
423 sl->lpVtbl->Release(sl);
424 return NULL;
425 }
426
427 // load .lnk file
428 int newlen = 0;
429 wchar_t *wpath = path2winpath(path, 0, &newlen);
430 hres = file->lpVtbl->Load(file, wpath, STGM_READ);
431 if(SUCCEEDED(hres)) {
432 WCHAR link_path[MAX_PATH];
433 memset(link_path, 0, MAX_PATH);
434
435 hres = sl->lpVtbl->Resolve(sl, 0, SLR_NO_UI);
436 if(SUCCEEDED(hres)) {
437 hres = sl->lpVtbl->GetPath(sl, link_path, MAX_PATH, NULL, SLGP_SHORTPATH);
438 if(SUCCEEDED(hres)) {
439 ret_link = winpath2multibyte(link_path, wcslen(link_path));
440 }
441 }
442 }
443 // cleanup
444 free(wpath);
445 file->lpVtbl->Release(file);
446 sl->lpVtbl->Release(sl);
447
448 return ret_link;
299 } 449 }
300 450
301 int sys_symlink(const char *target, const char *linkpath) { 451 int sys_symlink(const char *target, const char *linkpath) {
302 // TODO 452 // convert relative target to absolut path
303 fprintf(stderr, "sys_symlink: implement me\n"); 453 char *link_parent = util_parent_path(linkpath);
304 return 1; 454 char *target_unnormalized = util_concat_path(link_parent, target);
455 char *target_normalized = util_path_normalize(target_unnormalized);
456
457 free(link_parent);
458 free(target_unnormalized);
459
460 // convert to wchar_t*
461 int wtargetlen = 0;
462 wchar_t *wtarget = path2winpath(target_normalized, FALSE, &wtargetlen);
463 free(target_normalized);
464 if(!wtarget) {
465 return 1;
466 }
467
468 int wlinkpathlen = 0;
469 wchar_t *wlinkpath = path2winpath(linkpath, FALSE, &wlinkpathlen);
470 if(!wlinkpath) {
471 free(wtarget);
472 return 1;
473 }
474
475 int ret = 1;
476
477 // create COM object for using the ShellLink interface
478 IShellLinkW *sl;
479 HRESULT hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID*)&sl);
480 if(SUCCEEDED(hres)) {
481 IPersistFile *file;
482 hres = sl->lpVtbl->QueryInterface(sl, &IID_IPersistFile, (void**)&file);
483 if(SUCCEEDED(hres)) {
484 // try to load the shortcut
485 file->lpVtbl->Load(file, wlinkpath, STGM_READ); // ignore error
486
487 // set path
488 hres = sl->lpVtbl->SetPath(sl, wtarget);
489 if(SUCCEEDED(hres)) {
490 hres = file->lpVtbl->Save(file, wlinkpath, TRUE);
491 if(SUCCEEDED(hres)) {
492 // successfully created/modified shortcut
493 ret = 0; // ok
494 }
495 }
496
497 file->lpVtbl->Release(file);
498 }
499
500 sl->lpVtbl->Release(sl);
501 }
502
503 free(wtarget);
504 free(wlinkpath);
505
506 return ret;
305 } 507 }
306 508
307 #endif 509 #endif

mercurial