root/branches/orangefs-2-8-5/src/client/windows/client-service/fs.c @ 9186

Revision 9186, 19.8 KB (checked in by sampson, 17 months ago)

Windows Client: added ability to configure permissions mask for new files and directories.

  • Property svn:executable set to *
Line 
1/*
2 * (C) 2010-2011 Clemson University and Omnibond LLC
3 *
4 * See COPYING in top-level directory.
5 */
6
7/*
8 * Client Service - file system routines
9 * These routines provide a layer of abstraction between the Dokan
10 * callbacks (dokan-interface.c) and OrangeFS.
11 */
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <time.h>
16
17#include "pvfs2.h"
18#include "str-utils.h"
19
20const PVFS_util_tab *tab;
21
22/* split path into base dir and entry name components */
23int split_path(char *fs_path,
24               char *base_dir,
25               int base_dir_len,
26               char *entry_name,
27               int entry_name_len)
28{
29    int ret;
30
31    /* get base dir */
32    ret = PINT_get_base_dir(fs_path, base_dir, base_dir_len);
33
34    if (ret != 0)
35        return ret;
36
37    /* get entry name */
38    ret = PINT_remove_base_dir(fs_path, entry_name, entry_name_len);
39
40    return ret;
41}
42
43/* initialize file systems */
44int fs_initialize(const char *tabfile,
45                  char *error_msg,
46                  size_t error_msg_len)
47{
48    int ret, i, found_one = 0;
49    char errbuf[256];
50
51    /* read tab file */
52    tab = PVFS_util_parse_pvfstab(tabfile);
53    if (!tab)
54    {
55        _snprintf(error_msg, error_msg_len, "fs_initialize: failed to parse %s",
56            tabfile);
57        return -1;
58    }
59
60    /* initialize PVFS */
61    ret = PVFS_sys_initialize(GOSSIP_NO_DEBUG);
62    if (ret < 0)
63    {
64        PVFS_strerror_r(ret, errbuf, 256);
65        _snprintf(error_msg, error_msg_len, "PVFS_sys_initialize: %s", errbuf);
66        return ret;
67    }
68   
69    /* initialize file systems */
70    for (i = 0; i < tab->mntent_count; i++)
71    {
72        ret = PVFS_sys_fs_add(&tab->mntent_array[i]);
73        if (ret == 0)
74            found_one = 1;
75    }
76
77    if (!found_one)
78    {
79        _snprintf(error_msg, error_msg_len, "fs_initialize: could not initialize any "
80            "file systems from %s", tab->tabfile_name);
81
82        PINT_release_pvfstab();
83        PVFS_sys_finalize();
84        return -1;
85    }
86
87    return 0;
88}
89
90struct PVFS_sys_mntent *fs_get_mntent(PVFS_fs_id fs_id)
91{
92    /* TODO: ignore fs_id right now,
93       return first entry */
94    return &tab->mntent_array[0];
95}
96
97int fs_resolve_path(const char *local_path,
98                    char *fs_path,
99                    size_t fs_path_max)
100{
101    struct PVFS_sys_mntent *mntent;
102    char *trans_path, *full_path;
103    char *inptr, *outptr;
104    PVFS_fs_id fs_id;
105    int ret;
106
107    if (local_path == NULL || fs_path == NULL ||
108        fs_path_max == 0)
109        return -1;
110
111    trans_path = (char *) malloc(strlen(local_path) + 1);
112    if (trans_path == NULL)
113    {
114        return -1;   /* TODO */
115    }
116
117    /* remove drive: if necessary */
118    if (strlen(local_path) >= 2 && local_path[1] == ':')
119        inptr = (char *) local_path + 2;
120    else
121        inptr = (char *) local_path;
122
123    /* translate \'s to /'s */
124    for (outptr = trans_path; *inptr; inptr++, outptr++)
125    {
126        if (*inptr == '\\')           
127            *outptr = '/';
128        else
129            *outptr = *inptr;
130    }
131    *outptr = '\0';
132
133    mntent = fs_get_mntent(0);
134   
135    full_path = (char *) malloc(strlen(trans_path) +
136                                strlen(mntent->mnt_dir) + 2);
137    if (full_path == NULL)
138    {
139        free(trans_path);
140        return -1;
141    }
142   
143    /* prepend mount directory to path */
144    strcpy(full_path, mntent->mnt_dir);
145    /* append path */
146    if (full_path[strlen(full_path)-1] != '/')
147        strcat(full_path, "/");
148    if (trans_path[0] == '/')
149        strcat(full_path, trans_path+1);
150    else
151        strcat(full_path, trans_path);
152    strncpy(fs_path, full_path, fs_path_max);
153
154    /* resolve the path against PVFS */
155    ret = PVFS_util_resolve(full_path, &fs_id, fs_path, fs_path_max);
156
157    free(full_path);
158    free(trans_path);
159
160    return ret;
161}
162
163/* Workaround to follow PVFS2 file links */
164int sys_lookup_follow_links(PVFS_fs_id fs_id,
165                            char *fs_path,
166                            PVFS_credentials *credentials,
167                            PVFS_sysresp_lookup *resp)
168{
169    char *real_path;
170    PVFS_sysresp_getattr resp_getattr;
171    int ret, link_flag;
172
173    if (fs_path == NULL || strlen(fs_path) == 0 || credentials == NULL ||
174        resp == NULL)
175        return -1;
176
177    /* copy to be used for link paths */
178    real_path = strdup(fs_path);
179    do
180    {
181        link_flag = FALSE;
182
183        /* lookup the given path on the FS */
184        ret = PVFS_sys_lookup(fs_id, real_path, credentials, resp,
185            PVFS2_LOOKUP_LINK_NO_FOLLOW, NULL);
186        if (ret != 0)
187            break;
188
189        /* check if it's a link */
190        memset(&resp_getattr, 0, sizeof(resp_getattr));
191        ret = PVFS_sys_getattr(resp->ref, PVFS_ATTR_SYS_LNK_TARGET, credentials,
192            &resp_getattr, NULL);
193        if (ret != 0)
194            break;
195
196        if (resp_getattr.attr.link_target != NULL)
197        {
198            link_flag = TRUE;
199            /* get file name */
200            free(real_path);
201            real_path = (char *) malloc(PVFS_NAME_MAX);
202            ret = PVFS_util_resolve(resp_getattr.attr.link_target, &fs_id,
203                real_path, PVFS_NAME_MAX);
204            /* free attr buffer */
205            free(resp_getattr.attr.link_target);
206        }
207    } while (ret == 0 && link_flag);
208
209    free(real_path);
210
211    return ret;
212}
213
214/* lookup PVFS file path
215   returns 0 and handle if exists */
216int fs_lookup(char *fs_path,
217              PVFS_credentials *credentials,
218              PVFS_handle *handle)
219{
220    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
221    PVFS_sysresp_lookup resp;
222    int ret;
223
224    if (fs_path == NULL || credentials == NULL || handle == NULL)
225        return -1;
226
227    /* lookup the given path on the FS - do not follow links */
228    ret = PVFS_sys_lookup(mntent->fs_id, fs_path, credentials, &resp,
229        PVFS2_LOOKUP_LINK_NO_FOLLOW, NULL);
230
231    if (ret == 0)
232        *handle = resp.ref.handle;
233
234    return ret;
235}
236
237/* create file with specified path
238      returns 0 and handle on success */
239int fs_create(char *fs_path,
240              PVFS_credentials *credentials,
241              PVFS_handle *handle,
242              unsigned int perms)
243{   
244    char *base_dir, *entry_name;
245    int len;
246    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
247    PVFS_sysresp_lookup resp_lookup;
248    PVFS_object_ref parent_ref;
249    int ret;
250    PVFS_sys_attr attr;
251    PVFS_sysresp_create resp_create;
252
253    if (fs_path == NULL || strlen(fs_path) == 0)
254        return -1;
255   
256    /* cannot be only a dir */
257    if (fs_path[strlen(fs_path)-1] == '/')
258        return -1;
259
260    /* split path into path and file components */
261    len = strlen(fs_path) + 1;
262    base_dir = (char *) malloc(len);   
263    entry_name = (char *) malloc(len);
264    ret = split_path(fs_path, base_dir, len, entry_name, len);
265    if (ret != 0)
266        goto fs_create_exit;
267
268    /* lookup parent path - follow links */
269    ret = sys_lookup_follow_links(mntent->fs_id, base_dir, credentials,
270        &resp_lookup);
271    if (ret != 0)
272        goto fs_create_exit;
273
274    parent_ref.fs_id = resp_lookup.ref.fs_id;
275    parent_ref.handle = resp_lookup.ref.handle;
276
277    /* create file */
278    memset(&attr, 0, sizeof(PVFS_sys_attr));
279    attr.mask = PVFS_ATTR_SYS_ALL_SETABLE;
280    attr.owner = credentials->uid;
281    attr.group = credentials->gid;
282    /* configurable in options */
283    attr.perms = perms;
284    attr.atime = attr.mtime = attr.ctime = time(NULL);
285
286    ret = PVFS_sys_create(entry_name, parent_ref, attr,
287              credentials, NULL, &resp_create, NULL, NULL);
288    if (ret)
289        goto fs_create_exit;
290
291    *handle = resp_create.ref.handle;
292
293fs_create_exit:
294    free(entry_name);
295    free(base_dir);
296
297    return ret;
298}
299
300/* remove specified directory or file */
301int fs_remove(char *fs_path,
302              PVFS_credentials *credentials)
303{
304    char *base_dir, *entry_name;
305    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
306    int len, ret;
307    PVFS_sysresp_lookup resp_lookup;
308    PVFS_object_ref parent_ref;
309
310    if (fs_path == NULL || strlen(fs_path) == 0)
311        return -1;
312
313    /* split path into path and file components */
314    len = strlen(fs_path) + 1;
315    base_dir = (char *) malloc(len);   
316    entry_name = (char *) malloc(len);
317    ret = split_path(fs_path, base_dir, len, entry_name, len);
318    if (ret != 0)
319        goto fs_remove_exit;
320
321    /* lookup parent entry - follow links */
322    ret = sys_lookup_follow_links(mntent->fs_id, base_dir, credentials,
323        &resp_lookup);
324    if (ret != 0)
325        goto fs_remove_exit;
326
327    parent_ref.fs_id = resp_lookup.ref.fs_id;
328    parent_ref.handle = resp_lookup.ref.handle;
329
330    ret = PVFS_sys_remove(entry_name, parent_ref, credentials, NULL);
331
332fs_remove_exit:
333    free(entry_name);
334    free(base_dir);
335
336    return ret;
337}
338
339int fs_rename(char *old_path,
340              char *new_path,
341              PVFS_credentials *credentials)
342{
343    char *old_base_dir, *old_entry_name,
344         *new_base_dir, *new_entry_name;
345    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
346    int len, ret;
347    PVFS_sysresp_lookup old_resp_lookup, new_resp_lookup;
348    PVFS_object_ref old_parent_ref, new_parent_ref;
349
350    if (old_path == NULL || strlen(old_path) == 0 ||
351        new_path == NULL || strlen(new_path) == 0)
352        return -1;
353
354    /* split paths into path and file components */
355    len = strlen(old_path) + 1;
356    old_base_dir = (char *) malloc(len);   
357    old_entry_name = (char *) malloc(len);
358    ret = split_path(old_path, old_base_dir, len, old_entry_name, len);
359    if (ret != 0)
360        goto fs_rename_exit;
361
362    /* lookup parent entry - follow links */
363    ret = sys_lookup_follow_links(mntent->fs_id, old_base_dir, credentials,
364        &old_resp_lookup);
365    if (ret != 0)
366        goto fs_rename_exit;
367
368    old_parent_ref.fs_id = old_resp_lookup.ref.fs_id;
369    old_parent_ref.handle = old_resp_lookup.ref.handle;
370
371    len = strlen(new_path) + 1;
372    new_base_dir = (char *) malloc(len);   
373    new_entry_name = (char *) malloc(len);
374    ret = split_path(new_path, new_base_dir, len, new_entry_name, len);
375    if (ret != 0)
376        goto fs_rename_exit;
377
378    /* lookup parent entry - follow links */
379    ret = sys_lookup_follow_links(mntent->fs_id, new_base_dir, credentials,
380        &new_resp_lookup);
381    if (ret != 0)
382        goto fs_rename_exit;
383
384    new_parent_ref.fs_id = new_resp_lookup.ref.fs_id;
385    new_parent_ref.handle = new_resp_lookup.ref.handle;
386
387    /* rename/move the file */
388    ret = PVFS_sys_rename(old_entry_name, old_parent_ref, new_entry_name,
389                          new_parent_ref, credentials, NULL);
390
391fs_rename_exit:
392   
393    free(new_entry_name);
394    free(new_base_dir);
395    free(old_entry_name);
396    free(old_base_dir);
397
398    return ret;
399}
400
401int fs_truncate(char *fs_path,
402                PVFS_size size,
403                PVFS_credentials *credentials)
404{
405    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
406    int ret;
407    PVFS_sysresp_lookup resp_lookup;
408
409    /* lookup file - follow links */
410    ret = sys_lookup_follow_links(mntent->fs_id, fs_path, credentials,
411        &resp_lookup);
412    if (ret != 0)
413        goto fs_truncate_exit;
414
415    ret = PVFS_sys_truncate(resp_lookup.ref, size, credentials, NULL);
416
417fs_truncate_exit:
418
419    return ret;
420}
421
422int fs_getattr(char *fs_path,
423               PVFS_credentials *credentials,
424               PVFS_sys_attr *attr)
425{
426    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
427    int ret;
428    PVFS_sysresp_lookup resp_lookup;
429    PVFS_sysresp_getattr resp_getattr;
430
431    if (fs_path == NULL || strlen(fs_path) == 0 ||
432        attr == NULL)
433        return -PVFS_EINVAL;
434
435    /* lookup file - follow links */
436    ret = sys_lookup_follow_links(mntent->fs_id, fs_path, credentials,
437        &resp_lookup);
438    if (ret != 0)
439        goto fs_getattr_exit;
440
441    /* read all attributes */
442    memset(&resp_getattr, 0, sizeof(resp_getattr));
443    ret = PVFS_sys_getattr(resp_lookup.ref, PVFS_ATTR_SYS_ALL_NOHINT,
444                        credentials, &resp_getattr, NULL);
445
446    /* free attr bufs */
447    if (resp_getattr.attr.link_target != NULL)
448    {
449        free(resp_getattr.attr.link_target);
450        resp_getattr.attr.link_target = NULL;
451    }
452    if (resp_getattr.attr.dist_name != NULL)
453    {
454        free(resp_getattr.attr.dist_name);
455        resp_getattr.attr.dist_name = NULL;
456    }
457    if (resp_getattr.attr.dist_params != NULL)
458    {
459        free(resp_getattr.attr.dist_params);           
460        resp_getattr.attr.dist_params = NULL;
461    }
462
463    if (ret != 0)
464        goto fs_getattr_exit;
465
466    memcpy(attr, &resp_getattr.attr, sizeof(PVFS_sys_attr));
467
468fs_getattr_exit:
469
470    return ret;
471}
472
473int fs_setattr(char *fs_path,
474               PVFS_sys_attr *attr,
475               PVFS_credentials *credentials)
476{
477    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
478    int ret;
479    PVFS_sysresp_lookup resp_lookup;
480
481    if (fs_path == NULL || strlen(fs_path) == 0 ||
482        attr == NULL)
483        return -PVFS_EINVAL;
484
485    /* lookup file - follow links */
486    ret = sys_lookup_follow_links(mntent->fs_id, fs_path, credentials,
487        &resp_lookup);
488    if (ret != 0)
489        goto fs_setattr_exit;
490
491    /* set attributes */
492    ret = PVFS_sys_setattr(resp_lookup.ref, *attr, credentials, NULL);
493
494fs_setattr_exit:
495
496    return ret;
497}
498
499int fs_mkdir(char *fs_path,
500             PVFS_credentials *credentials,
501             PVFS_handle *handle,
502             unsigned int perms)
503{
504    char *base_dir, *entry_name;
505    int len;
506    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
507    PVFS_sysresp_lookup resp_lookup;
508    PVFS_object_ref parent_ref;
509    PVFS_sys_attr attr;
510    PVFS_sysresp_mkdir resp_mkdir;
511    int ret;
512
513    if (fs_path == NULL || strlen(fs_path) == 0)
514        return -1;
515   
516    /* split path into path and file components */
517    len = strlen(fs_path) + 1;
518    base_dir = (char *) malloc(len);   
519    entry_name = (char *) malloc(len);
520    ret = split_path(fs_path, base_dir, len, entry_name, len);
521    if (ret != 0)
522        goto fs_mkdir_exit;
523
524    /* lookup parent path - follow links */
525    ret = sys_lookup_follow_links(mntent->fs_id, base_dir, credentials,
526        &resp_lookup);
527
528    if (ret != 0)
529        goto fs_mkdir_exit;
530
531    parent_ref.fs_id = resp_lookup.ref.fs_id;
532    parent_ref.handle = resp_lookup.ref.handle;
533
534    /* create file */
535    memset(&attr, 0, sizeof(PVFS_sys_attr));
536    attr.mask = PVFS_ATTR_SYS_ALL_SETABLE;
537    attr.owner = credentials->uid;
538    attr.group = credentials->gid;
539    /* configurable in options */
540    attr.perms = perms;
541    attr.atime = attr.mtime = attr.ctime = time(NULL);
542
543    ret = PVFS_sys_mkdir(entry_name, parent_ref, attr, credentials,
544                         &resp_mkdir, NULL);
545
546    if (ret == 0)
547        *handle = resp_mkdir.ref.handle;
548
549fs_mkdir_exit:
550    free(entry_name);
551    free(base_dir);
552
553    return ret;
554}
555
556int fs_io(enum PVFS_io_type io_type,
557          char *fs_path,
558          void *buffer,
559          size_t buffer_len,
560          uint64_t offset,
561          PVFS_size *op_len,
562          PVFS_credentials *credentials)
563{
564    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
565    PVFS_sysresp_lookup resp_lookup;
566    PVFS_object_ref object_ref;
567    PVFS_Request file_req, mem_req;
568    PVFS_sysresp_io resp_io;
569    int ret;
570
571    if (fs_path == NULL || strlen(fs_path) == 0 ||
572        buffer == NULL)
573        return -PVFS_EINVAL;
574
575    /* lookup file - follow links */
576    ret = sys_lookup_follow_links(mntent->fs_id, fs_path, credentials,
577        &resp_lookup);
578    if (ret != 0)
579        goto fs_io_exit;
580
581    /* copy object ref */
582    object_ref.fs_id = resp_lookup.ref.fs_id;
583    object_ref.handle = resp_lookup.ref.handle;
584
585    /* get memory buffer */
586    file_req = PVFS_BYTE;
587
588    ret = PVFS_Request_contiguous(buffer_len, PVFS_BYTE, &(mem_req));
589    if (ret != 0)
590        goto fs_io_exit;
591
592    /* perform io operation */
593    ret = PVFS_sys_io(object_ref, file_req, offset, buffer, mem_req,
594                      credentials, &resp_io, io_type, NULL);
595    if (ret == 0 && op_len != NULL)
596    {
597        *op_len = resp_io.total_completed;
598    }
599
600    PVFS_Request_free(&mem_req);
601
602fs_io_exit:
603
604    return ret;
605}
606
607int fs_flush(char *fs_path,
608             PVFS_credentials *credentials)
609{
610    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
611    int ret;
612    PVFS_sysresp_lookup resp_lookup;
613
614    if (fs_path == NULL || strlen(fs_path) == 0)
615        return -PVFS_EINVAL;
616
617    /* lookup file - follow links */
618    ret = sys_lookup_follow_links(mntent->fs_id, fs_path, credentials,
619        &resp_lookup);
620    if (ret != 0)
621        goto fs_flush_exit;
622
623    /* flush file */
624    ret = PVFS_sys_flush(resp_lookup.ref, credentials, NULL);
625
626fs_flush_exit:
627
628    return ret;
629}
630
631int fs_find_next_file(char *fs_path,
632                      PVFS_ds_position *token,
633                      PVFS_credentials *credentials,
634                      char *filename,
635                      size_t max_name_len)
636{
637    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
638    int ret;
639    PVFS_sysresp_lookup resp_lookup;
640    PVFS_sysresp_readdir resp_readdir;
641
642    if (fs_path == NULL || strlen(fs_path) == 0 ||
643        token == NULL || filename == NULL || max_name_len == 0)
644        return -PVFS_EINVAL;
645
646    /* lookup file - follow links */
647    ret = sys_lookup_follow_links(mntent->fs_id, fs_path, credentials,
648        &resp_lookup);
649    if (ret != 0)
650        goto fs_readdir_exit;
651
652    /* read one entry, starting with token */
653    ret = PVFS_sys_readdir(resp_lookup.ref, *token, 1, credentials,
654                           &resp_readdir, NULL);
655    if (ret != 0)
656        goto fs_readdir_exit;
657
658    /* copy output results */
659    if (resp_readdir.pvfs_dirent_outcount != 0)
660    {
661        *token = resp_readdir.token;
662       
663        strncpy(filename, resp_readdir.dirent_array[0].d_name, max_name_len);
664        filename[max_name_len-1] = '\0';
665
666        /* free memory */
667        free(resp_readdir.dirent_array);
668    }
669    else
670    {
671        /* return empty string when done */
672        filename[0] = '\0';
673    }
674
675fs_readdir_exit:
676
677    return ret;
678}
679
680int fs_find_first_file(char *fs_path,
681                       PVFS_ds_position *token,
682                       PVFS_credentials *credentials,
683                       char *filename,
684                       size_t max_name_len)
685{
686    if (token == NULL)
687    {
688        return -PVFS_EINVAL;
689    }
690
691   *token = PVFS_READDIR_START;
692   return fs_find_next_file(fs_path, token, credentials, filename, max_name_len);
693}
694
695int fs_get_diskfreespace(PVFS_credentials *credentials,
696                         PVFS_size *free_bytes,
697                         PVFS_size *total_bytes)
698{
699    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
700    PVFS_sysresp_statfs resp_statfs;
701    int ret;
702
703    if (free_bytes == NULL || total_bytes == NULL)
704    {
705        return -PVFS_EINVAL;
706    }
707
708    ret = PVFS_sys_statfs(mntent->fs_id, credentials, &resp_statfs, NULL);
709
710    if (ret == 0)
711    {
712        *free_bytes = resp_statfs.statfs_buf.bytes_available;
713        *total_bytes = resp_statfs.statfs_buf.bytes_total;
714    }
715
716    return ret;
717}
718
719PVFS_fs_id fs_get_id(int fs_num)
720{
721    /* TODO: ignore fs_num for now */
722    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
723
724    return mntent ? mntent->fs_id : 0;
725}
726
727char *fs_get_name(int fs_num)
728{
729    /* TODO: ignore fs_num for now */
730    struct PVFS_sys_mntent *mntent = fs_get_mntent(0);
731
732    return mntent ? mntent->pvfs_fs_name : "PVFS2";
733}
734
735int fs_finalize()
736{
737    /* TODO */
738    PVFS_sys_finalize();
739
740    return 0;
741}
Note: See TracBrowser for help on using the browser.