root/branches/Orange-Branch/src/client/usrint/iocommon.c @ 8890

Revision 8890, 33.6 KB (checked in by walt, 2 years ago)

main implementation done, compiles clean, ready for debugging

Line 
1/*
2 * (C) 2011 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7/** \file
8 *  \ingroup usrint
9 *
10 *  PVFS2 user interface routines - low level calls to system interface
11 */
12#include <usrint.h>
13#include <linux/dirent.h>
14#include <posix-ops.h>
15#include <openfile-util.h>
16#include <iocommon.h>
17
18int init=0;
19
20/* Perform PVFS initialization if not already finished */
21void iocommon_ensure_init()
22{
23
24    /* Initialize the file system with mount points */
25    int ret;
26    if (!init)
27    {
28        ret = PVFS_util_init_defaults();
29        assert(ret==PVFS_FD_SUCCESS);
30        init=1;
31    }
32
33}
34
35void iocommon_cred(PVFS_credentials **credentials)
36{
37    static PVFS_credentials creds_buf;
38    static int cred_init = 0;
39
40    if(!cred_init)
41    {
42        memset(&creds_buf, 0, sizeof(creds_buf));
43        creds_buf.uid = getuid();
44        creds_buf.gid = getgid();
45        cred_init = 1;
46    }
47
48    *credentials = &creds_buf;
49}
50
51int iocommon_fsync(pvfs_descriptor *pd)
52{
53    PVFS_credentials *credentials;
54    iocommon_cred(&credentials);
55    return PVFS_sys_flush(pd->pvfs_ref, credentials, PVFS_HINT_NULL);
56}
57
58/*
59 * Find the PVFS handle to an object (file, dir sym)
60 * assumes an absoluate path
61 */
62int iocommon_lookup_absolute(const char *abs_path, PVFS_object_ref *ref)
63{
64    int rc = 0;
65    char pvfs_path[256];
66    PVFS_fs_id lookup_fs_id;
67    PVFS_credentials *credentials;
68    PVFS_sysresp_lookup resp_lookup;
69
70    /* Initialize any variables */
71    memset(&resp_lookup, 0, sizeof(resp_lookup));
72
73    /* Determine the fs_id and pvfs_path */
74    rc = PVFS_util_resolve(abs_path, &lookup_fs_id, pvfs_path, 256);
75    if (rc == -1)
76    {
77        return -1;
78    }
79
80    iocommon_cred(&credentials);
81    rc = PVFS_sys_lookup(lookup_fs_id, pvfs_path,
82                         credentials, &resp_lookup,
83                         PVFS2_LOOKUP_LINK_FOLLOW, NULL);
84    *ref = resp_lookup.ref;
85
86    return rc;
87}
88
89/*
90 * Lookup a file via the PVFS system interface
91 */
92int iocommon_lookup_relative(const char *rel_path,
93                             PVFS_object_ref parent_ref, /* by value */
94                             int follow_links,
95                             PVFS_object_ref *ref )
96{
97    int rc = 0;
98    PVFS_credentials *credentials;
99    PVFS_sysresp_lookup resp_lookup;
100
101    /* Initialize any variables */
102    memset(&resp_lookup, 0, sizeof(resp_lookup));
103
104    /* Set credentials */
105    iocommon_cred(&credentials);
106
107    /* Contact server */
108    rc = PVFS_sys_ref_lookup(parent_ref.fs_id,
109                             (char*)rel_path,
110                             parent_ref,
111                             credentials,
112                             &resp_lookup,
113                             follow_links,
114                             PVFS_HINT_NULL);
115    *ref = resp_lookup.ref;
116
117    return rc;
118}
119
120/*
121 * Create a file via the PVFS system interface
122 */
123int iocommon_create_file(const char *filename,
124                         mode_t file_permission,
125                         PVFS_hint file_creation_param,
126                         PVFS_object_ref parent_ref,
127                         PVFS_object_ref *ref )
128{
129    int rc = 0;
130    mode_t mode_mask;
131    mode_t user_mode;
132    PVFS_sys_attr attr;
133    PVFS_credentials *credentials;
134    PVFS_sysresp_create resp_create;
135
136    /* Initialize */
137    memset(&attr, 0, sizeof(attr));
138    memset(&resp_create, 0, sizeof(resp_create));
139
140    /* Create distribution var */
141    PVFS_sys_dist *dist=NULL;
142
143    /* this is not right - need to pull parameters out of hints */
144    /* investigate PVFS hint mechanism */
145#if 0
146    if (file_creation_param.striping_unit > 0)
147    {
148        dist = PVFS_sys_dist_lookup("simple_stripe");
149        if (PVFS_sys_dist_setparam(dist, "strip_size",
150                                  &(file_creation_param.striping_unit)) < 0)
151        {
152            fprintf(stderr, "Error: failed to set striping_factor\n");
153        }
154    }
155#endif
156
157    attr.owner = getuid();
158    attr.group = getgid();
159    attr.atime = time(NULL);
160    attr.mtime = attr.atime;
161    attr.ctime = attr.atime;
162    attr.mask = PVFS_ATTR_SYS_ALL_SETABLE;
163
164#if 0
165    if (file_creation_param.striping_factor > 0){
166        attributes.dfile_count = file_creation_param.striping_factor;
167        attributes.mask |= PVFS_ATTR_SYS_DFILE_COUNT;
168    }
169#endif
170
171    /* Extract the users umask (and restore it to the original value) */
172    mode_mask = umask(0);
173    umask(mode_mask);
174    user_mode = file_permission & ~mode_mask;
175
176    /* Set file permissions */
177    if (user_mode & S_IXOTH)
178    {
179        attr.perms |= PVFS_O_EXECUTE;
180    }
181    if (user_mode & S_IWOTH)
182    {
183        attr.perms |= PVFS_O_WRITE;
184    }
185    if (user_mode & S_IROTH)
186    {
187        attr.perms |= PVFS_O_READ;
188    }
189    if (user_mode & S_IXGRP)
190    {
191        attr.perms |= PVFS_G_EXECUTE;
192    }
193    if (user_mode & S_IWGRP)
194    {
195        attr.perms |= PVFS_G_WRITE;
196    }
197    if (user_mode & S_IRGRP)
198    {
199        attr.perms |= PVFS_G_READ;
200    }
201    if (user_mode & S_IXUSR)
202    {
203        attr.perms |= PVFS_U_EXECUTE;
204    }
205    if (user_mode & S_IWUSR)
206    {
207        attr.perms |= PVFS_U_WRITE;
208    }
209    if (user_mode & S_IRUSR)
210    {
211        attr.perms |= PVFS_U_READ;
212    }
213
214    /* Set credentials */
215    iocommon_cred(&credentials);
216
217    /* Contact server */
218    rc = PVFS_sys_create((char*)filename,
219                         parent_ref,
220                         attr,
221                         credentials,
222                         dist,
223                         &resp_create,
224                         NULL,
225                         NULL);
226
227    *ref = resp_create.ref;
228
229    if (dist)
230    {
231        PINT_dist_free(dist);
232    }
233
234    return rc;
235}
236
237
238/* pvfs_open implementation, return file info in fd */
239/* assumes path is fully qualified */
240/* if pdir is not NULL, it is the parent directory */
241pvfs_descriptor *iocommon_open(const char *pathname, int flag,
242                               PVFS_hint file_creation_param,
243                               mode_t file_permission,
244                               PVFS_object_ref *pdir)
245{
246    int rc = 0;
247    int follow_link;
248    char *directory = NULL;
249    char *filename = NULL;
250    PVFS_object_ref file_ref;
251    PVFS_object_ref parent_ref;
252    int fs_id = 0;
253    pvfs_descriptor *pd = NULL; /* invalid pd until file is opened */
254    PVFS_sysresp_getattr attributes_resp;
255    PVFS_credentials *credentials;
256
257    /* Initialize */
258    memset(&file_ref, 0, sizeof(file_ref));
259    memset(&parent_ref, 0, sizeof(parent_ref));
260    memset(&attributes_resp, 0, sizeof(attributes_resp));
261
262    /* Split the path into a directory and file */
263    rc = split_pathname(pathname, &directory, &filename);
264    if (rc == -1)
265    {
266        goto errorout;
267    }
268
269    /* Check the flag to determine if links are followed */
270    if (flag & O_NOFOLLOW)
271    {
272        follow_link = PVFS2_LOOKUP_LINK_NO_FOLLOW;
273    }
274    else
275    {
276        follow_link = PVFS2_LOOKUP_LINK_FOLLOW;
277    }
278
279    /* Get reference for the parent directory */
280    if (pdir == NULL)
281    {
282        rc = iocommon_lookup_absolute(directory, &parent_ref);
283        if (rc == -1)
284        {
285            goto errorout;
286        }
287    }
288    else
289    {
290        if (directory)
291        {
292            rc = iocommon_lookup_relative(directory,
293                                          *pdir,
294                                          follow_link,
295                                          &parent_ref);
296            if (rc == -1)
297            {
298                goto errorout;
299            }
300        }
301        else
302        {
303            parent_ref = *pdir;
304        }
305    }
306
307    /* An open procedure safe for multiprocessing */
308
309    /* Attempt to find file */
310    rc = iocommon_lookup_relative(filename,
311                                  parent_ref,
312                                  follow_link,
313                                  &file_ref);
314    /* File was found */
315    if (rc == 0)
316    {
317        //if EXCLUSIVE, fail */
318        if ((flag & O_EXCL) && (flag & O_CREAT))
319        {
320            errno = EEXIST;
321            goto errorout;
322        }
323    }
324    else
325    {
326        /* File wasn't found */
327        if (flag & O_CREAT)
328        {
329            /* create file? */
330            rc = iocommon_create_file(filename,
331                                      file_permission,
332                                      file_creation_param,
333                                      parent_ref,
334                                      &file_ref);
335            /* create failed, the file must have been */
336            /* created by a different process, so just open it */
337            if (rc != -1)
338            {
339                /* get existing handle */
340                rc = iocommon_lookup_relative(filename,
341                                              parent_ref,
342                                              follow_link,
343                                              &file_ref);
344                if (rc == -1)
345                {
346                    /* not sure what is wrong */
347                    goto errorout;
348                }
349            }
350        }
351    }
352
353    /* Translate the pvfs reference into a file descriptor */
354    /* Set the file information */
355    /* create fd object */
356    pd = pvfs_alloc_descriptor(&pvfs_ops);
357    pd->pvfs_ref = file_ref;
358    pd->flags = flag;
359    pd->is_in_use = PVFS_FS;    //indicate fd is valid!
360
361    /* Get the file's type information from its attributes */
362    PVFS_sys_getattr(pd->pvfs_ref, PVFS_ATTR_SYS_ALL_NOHINT,
363                     credentials, &attributes_resp, NULL);
364    pd->mode = attributes_resp.attr.perms; /* this may change */
365    if (attributes_resp.attr.objtype & PVFS_TYPE_METAFILE)
366    {
367        pd->mode |= S_IFREG;
368    }
369    if (attributes_resp.attr.objtype & PVFS_TYPE_DIRECTORY)
370    {
371        pd->mode |= S_IFDIR;
372    }
373    if (attributes_resp.attr.objtype & PVFS_TYPE_SYMLINK)
374    {
375        pd->mode |= S_IFLNK;
376    }
377
378    /* Truncate the file if neccesary */
379    if (flag & O_TRUNC)
380    {
381        PVFS_credentials *credentials;
382        iocommon_cred(&credentials);
383        PVFS_sys_truncate(file_ref, 0, credentials, NULL);
384    }
385
386    /* Move to the end of file if necessary */
387    if (flag & O_APPEND)
388    {
389        iocommon_lseek(pd, 0, 0, SEEK_END);
390    }
391
392errorout:
393
394    /* Free directory and filename memory */
395    if (directory)
396    {
397        free(directory);
398    }
399    if (filename)
400    {
401        free(filename);
402    }
403    if (rc == -1)
404    {
405        return NULL;
406    }
407    else
408    {
409        return pd;
410    }
411}
412
413/**
414 * Implementation of lseek for file and directory via PVFS
415 *
416 */
417off64_t iocommon_lseek(pvfs_descriptor *pd, off64_t offset,
418            PVFS_size unit_size, int whence)
419{
420    int rc = 0;
421    PVFS_credentials *credentials;
422    PVFS_sysresp_getattr attributes_resp;
423    PVFS_sysresp_readdir readdir_resp;
424
425    if (0 == pd)
426    {
427        errno = EBADF;
428        return PVFS_FD_FAILURE;
429    }
430
431    /* Initialize */
432    memset(&readdir_resp, 0, sizeof(readdir_resp));
433    memset(&attributes_resp, 0, sizeof(attributes_resp));
434
435    /* Construct credentials*/
436    iocommon_cred(&credentials);
437
438    switch(whence)
439    {
440        case SEEK_SET:
441        {
442            pd->file_pointer = offset*unit_size;
443            break;
444        }
445        case SEEK_CUR:
446        {
447            pd->file_pointer += offset*unit_size;
448            break;
449        }
450        case SEEK_END:
451        {
452            /* Get the file's size in bytes as the ending offset */
453            rc = PVFS_sys_getattr(pd->pvfs_ref, PVFS_ATTR_SYS_SIZE,
454                                  credentials, &attributes_resp, NULL);
455            if(rc)
456            {
457                return -1;
458            }
459            pd->file_pointer = attributes_resp.attr.size + offset*unit_size;
460            break;
461        }
462        default:
463        {
464            errno = EINVAL;
465            return PVFS_FD_FAILURE;
466        }
467    }
468    /* if this is a directory adjust token, the hard way */
469    if (S_ISDIR(pd->mode))
470    {
471        int dirent_no;
472        dirent_no = pd->file_pointer / sizeof(PVFS_dirent);
473        pd->file_pointer = dirent_no * sizeof(PVFS_dirent);
474        pd->token = PVFS_READDIR_START;
475        if(dirent_no)
476        {
477            rc = PVFS_sys_readdir(pd->pvfs_ref,
478                                  pd->token,
479                                  dirent_no,
480                                  credentials,
481                                  &readdir_resp,
482                                  NULL);
483            if(rc == -1)
484            {
485                return -1;
486            }
487            pd->token = readdir_resp.token;
488            free(readdir_resp.dirent_array);
489        }
490    }
491    return pd->file_pointer;
492}
493
494/*
495 * pvfs_unlink implementation
496 * need to verify this is a file or symlink
497 * use rmdir for directory
498 */
499int iocommon_remove (const char *pathname,
500                     PVFS_object_ref *pdir,
501                     int dirflag)
502{
503    int rc = 0;
504    char *parentdir = NULL;
505    char *file = NULL;
506    PVFS_object_ref parent_ref, file_ref;
507    PVFS_credentials *credentials;
508    PVFS_sys_attr attr;
509
510    /* Initialize */
511    memset(&parent_ref, 0, sizeof(parent_ref));
512    memset(&file_ref, 0, sizeof(file_ref));
513    memset(&attr, 0, sizeof(attr));
514
515    /* Initialize the system interface for this process */
516    iocommon_ensure_init();
517    iocommon_cred(&credentials);
518
519    rc = split_pathname(pathname, &parentdir, &file);
520    if (rc == -1)
521    {
522        return -1;
523    }
524
525    if (!pdir)
526    {
527        rc = iocommon_lookup_absolute(parentdir, &parent_ref);
528        if (rc == -1)
529        {
530            goto errorout;
531        }
532    }
533    else
534    {
535        if (!parentdir)
536        {
537            rc = iocommon_lookup_relative(parentdir, *pdir,
538                            PVFS2_LOOKUP_LINK_FOLLOW, &parent_ref);
539            if (rc == -1)
540            {
541                goto errorout;
542            }
543        }
544        else
545        {
546            parent_ref = *pdir;
547        }
548    }
549
550    /* need to verify this is a file or symlink */
551    /* WBL - What is going on here ??? */
552    rc = iocommon_lookup_relative(file, parent_ref,
553                PVFS2_LOOKUP_LINK_NO_FOLLOW, &file_ref);
554    if (rc == -1)
555    {
556        goto errorout;
557    }
558    rc = iocommon_getattr(file_ref, &attr);
559    if (rc == -1)
560    {
561        goto errorout;
562    }
563    if ((attr.objtype & PVFS_TYPE_DIRECTORY) && dirflag)
564    {
565        errno = EISDIR;
566        goto errorout;
567    }
568    else if (!(attr.objtype & PVFS_TYPE_DIRECTORY) && !dirflag)
569    {
570        errno = ENOTDIR;
571        goto errorout;
572    }
573
574    rc = PVFS_sys_remove(file, parent_ref, credentials, PVFS_HINT_NULL);
575
576errorout:
577    if (parentdir)
578    {
579        free(parentdir);
580    }
581    if (file)
582    {
583        free(file);
584    }
585    if (rc == -1)
586    {
587        return -1;
588    }
589    else
590    {
591        return 0;
592    }
593}
594
595int iocommon_unlink(const char *pathname,
596                    PVFS_object_ref *pdir)
597{
598    return iocommon_remove(pathname, pdir, 1);
599}
600
601int iocommon_rmdir(const char *pathname,
602                   PVFS_object_ref *pdir)
603{
604    return iocommon_remove(pathname, pdir, 0);
605}
606
607/* if dir(s) are NULL, assume name is absolute */
608int iocommon_rename(PVFS_object_ref *oldpdir, const char *oldpath,
609                    PVFS_object_ref *newpdir, const char *newpath)
610{
611    int rc = 0;
612    char *olddir = NULL, *newdir = NULL, *oldname = NULL, *newname = NULL;
613    PVFS_object_ref oldref, newref;
614    PVFS_credentials *creds;
615    PVFS_hint hints = PVFS_HINT_NULL;
616
617    /* Initialize */
618    memset(&oldref, 0, sizeof(oldref));
619    memset(&newref, 0, sizeof(newref));
620
621    iocommon_cred(&creds);
622    rc = split_pathname(oldpath, &olddir, &oldname);
623    if (rc == -1)
624    {
625        return -1;
626    }
627    if (!olddir)
628    {
629        rc = iocommon_lookup_absolute(olddir, &oldref);
630        if (rc == -1)
631        {
632            goto errorout;
633        }
634    }
635    else
636    {
637        if (!olddir)
638        {
639            rc = iocommon_lookup_relative(olddir, *oldpdir,
640                                PVFS2_LOOKUP_LINK_FOLLOW, &oldref);
641            if (rc == -1)
642            {
643                goto errorout;
644            }
645        }
646        else
647        {
648            oldref = *oldpdir;
649        }
650    }
651    rc = split_pathname(newpath, &olddir, &oldname);
652    if (rc == -1)
653    {
654        goto errorout;
655    }
656    if (!newpdir)
657    {
658        rc = iocommon_lookup_absolute(newdir, &newref);
659        if (rc == -1)
660        {
661            goto errorout;
662        }
663    }
664    else
665    {
666        if (!olddir)
667        {
668            rc = iocommon_lookup_relative(newdir, *newpdir,
669                            PVFS2_LOOKUP_LINK_FOLLOW, &newref);
670            if (rc == -1)
671            {
672                goto errorout;
673            }
674        }
675        else
676        {
677            newref = *newpdir;
678        }
679    }
680    rc = PVFS_sys_rename(oldname, oldref, newname, newref, creds, hints);
681
682errorout:
683    if (olddir)
684    {
685        free(olddir);
686    }
687    if (oldname)
688    {
689        free(oldname);
690    }
691    if (newdir)
692    {
693        free(newdir);
694    }
695    if (newname)
696    {
697        free(newname);
698    }
699    return rc;
700}
701
702/** do a blocking read or write
703 *
704 */
705int iocommon_readorwrite(enum PVFS_io_type which,
706                         pvfs_descriptor *pd,
707                         PVFS_size offset,
708                         void *buf,
709                         PVFS_Request mem_req,
710                         PVFS_Request file_req)
711        //returned by nonblocking operations
712{
713    int rc = 0;
714    PVFS_credentials *creds;
715    PVFS_sysresp_io read_resp;
716
717    /* Initialize */
718    memset(&read_resp, 0, sizeof(read_resp));
719
720    if (!pd)
721    {
722        errno = EBADF;
723        return -1;
724    }
725
726    //Ensure descriptor is used for the correct type of access
727    if (which==PVFS_IO_READ && (O_WRONLY == (pd->flags & O_ACCMODE)) ||
728        which==PVFS_IO_WRITE && (O_RDONLY == (pd->flags & O_ACCMODE)))
729    {
730        errno = EBADF;
731        return PVFS_FD_FAILURE;
732    }
733
734    iocommon_cred(&creds);
735
736    rc = PVFS_sys_io(pd->pvfs_ref,
737                     file_req,
738                     offset,
739                     buf,
740                     mem_req,
741                     creds,
742                     &read_resp,
743                     which,
744                     PVFS_HINT_NULL);
745
746    if (rc = -1)
747    {
748        errno = EIO;
749        return -1;
750    }
751
752    return read_resp.total_completed;
753}
754
755/** Do a nonblocking read or write
756 *
757 * extra_offset = extra padding to the pd's offset,
758 * independent of the pd's offset
759 * Returns an op_id, response, and ret_mem_request
760 * (which represents an etype_req*count region)
761 * Note that the none of the PVFS_Requests are freed
762 */
763int iocommon_ireadorwrite(enum PVFS_io_type which,
764                          pvfs_descriptor *pd,
765                          PVFS_size extra_offset,
766                          void *buf,
767                          PVFS_Request etype_req,
768                          PVFS_Request file_req,
769                          size_t count,
770                          PVFS_sys_op_id *ret_op_id,
771                          PVFS_sysresp_io *ret_resp,
772                          PVFS_Request *ret_memory_req)
773{
774    int rc = 0;
775    PVFS_Request contig_memory_req;
776    PVFS_credentials *credentials;
777    PVFS_size req_size;
778
779    //Ensure descriptor is used for the correct type of access
780    if (which==PVFS_IO_READ && (O_WRONLY == (pd->flags & O_ACCMODE)) ||
781        which==PVFS_IO_WRITE && (O_RDONLY == (pd->flags & O_ACCMODE)))
782    {
783        errno = EBADF;
784        return PVFS_FD_FAILURE;
785    }
786
787    //Create the memory request of a contiguous region: 'mem_req' x count
788    rc = PVFS_Request_contiguous(count, etype_req, &contig_memory_req);
789
790    iocommon_cred(&credentials);
791
792    rc = PVFS_isys_io(pd->pvfs_ref,
793                      file_req,
794                      pd->file_pointer+extra_offset,
795                      buf,
796                      contig_memory_req,
797                      credentials,
798                      ret_resp,
799                      which,
800                      ret_op_id,
801                      PVFS_HINT_NULL,
802                      NULL);
803
804    assert(*ret_op_id!=-1);//TODO: handle this
805
806    if (rc != 0)
807    {
808        errno = EIO;
809        return -1;
810    }
811
812    PVFS_Request_size(contig_memory_req, &req_size);
813    pd->file_pointer += req_size;
814
815    *ret_memory_req = contig_memory_req;
816
817    return -1;
818}
819
820int iocommon_getattr(PVFS_object_ref obj, PVFS_sys_attr *attr)
821{
822    int                  rc = 0;
823    PVFS_credentials     *credentials;
824    PVFS_sysresp_getattr getattr_response;
825
826    /* Initialize */
827    memset(&getattr_response, 0, sizeof(getattr_response));
828
829    /* check credentials */
830    iocommon_cred(&credentials);
831
832    /* now get attributes */
833    rc = PVFS_sys_getattr(obj,
834                          PVFS_ATTR_SYS_ALL_NOHINT,
835                          credentials,
836                          &getattr_response, NULL);
837
838    *attr = getattr_response.attr;
839
840    if(rc < 0)
841    {
842        errno = EACCES; /* need to get proper return code */
843        return -1;
844    }
845
846    return 0;
847}
848
849/* WBL - question - should attr not be a pointer */
850int iocommon_setattr(PVFS_object_ref obj, PVFS_sys_attr *attr)
851{
852    int                  rc = 0;
853    PVFS_credentials     *credentials;
854
855    /* check credentials */
856    iocommon_cred(&credentials);
857
858    /* now get attributes */
859    rc = PVFS_sys_setattr(obj, *attr, credentials, NULL);
860
861    if(rc < 0)
862    {
863        errno = EACCES; /* need to get proper return code */
864        return -1;
865    }
866
867    return 0;
868}
869
870int iocommon_stat(pvfs_descriptor *pd, struct stat *buf)
871{
872    int                  rc = 0;
873    PVFS_sys_attr        attr;
874
875    /* Initialize */
876    memset(&attr, 0, sizeof(attr));
877
878    rc = iocommon_getattr(pd->pvfs_ref, &attr);
879
880    /* copy attributes into standard stat struct */
881    buf->st_dev = pd->pvfs_ref.fs_id;
882    buf->st_ino = pd->pvfs_ref.handle;
883    buf->st_mode = attr.perms;
884    if (attr.objtype & PVFS_TYPE_METAFILE)
885    {
886        buf->st_mode |= S_IFREG;
887    }
888    if (attr.objtype & PVFS_TYPE_DIRECTORY)
889    {
890        buf->st_mode |= S_IFDIR;
891    }
892    if (attr.objtype & PVFS_TYPE_SYMLINK)
893    {
894        buf->st_mode |= S_IFLNK;
895    }
896    buf->st_nlink = 1; /* PVFS does not allow hard links */
897    buf->st_uid = attr.owner;
898    buf->st_gid = attr.group;
899    buf->st_rdev = 0; /* no dev special files */
900    buf->st_size = attr.size;
901    buf->st_blksize = attr.blksize;
902    buf->st_blocks = 0; /* don't have blocks at this time */
903    buf->st_atime = attr.atime;
904    buf->st_mtime = attr.mtime;
905    buf->st_ctime = attr.ctime;
906
907    return 0;
908}
909
910/*
911 * The only difference here is that buf is stat64 which
912 * means some of its fields are defined as different types
913 */
914int iocommon_stat64(pvfs_descriptor *pd, struct stat64 *buf)
915{
916    int                  rc = 0;
917    PVFS_sys_attr        attr;
918
919    /* Initialize */
920    memset(&attr, 0, sizeof(attr));
921
922    rc = iocommon_getattr(pd->pvfs_ref, &attr);
923
924    /* copy attributes into standard stat struct */
925    buf->st_dev = pd->pvfs_ref.fs_id;
926    buf->st_ino = pd->pvfs_ref.handle;
927    buf->st_mode = attr.perms;
928    if (attr.objtype & PVFS_TYPE_METAFILE)
929    {
930        buf->st_mode |= S_IFREG;
931    }
932    if (attr.objtype & PVFS_TYPE_DIRECTORY)
933    {
934        buf->st_mode |= S_IFDIR;
935    }
936    if (attr.objtype & PVFS_TYPE_SYMLINK)
937    {
938        buf->st_mode |= S_IFLNK;
939    }
940    buf->st_nlink = 1; /* PVFS does not allow hard links */
941    buf->st_uid = attr.owner;
942    buf->st_gid = attr.group;
943    buf->st_rdev = 0; /* no dev special files */
944    buf->st_size = attr.size;
945    buf->st_blksize = attr.blksize;
946    buf->st_blocks = 0; /* don't have blocks at this time */
947    buf->st_atime = attr.atime;
948    buf->st_mtime = attr.mtime;
949    buf->st_ctime = attr.ctime;
950
951    return 0;
952}
953
954int iocommon_chown(pvfs_descriptor *pd, uid_t owner, gid_t group)
955{
956    int                  rc = 0;
957    PVFS_sys_attr        attr;
958
959    /* Initialize */
960    memset(&attr, 0, sizeof(attr));
961
962    if (owner != -1)
963    {
964        attr.owner = owner;
965    }
966    if (owner != -1)
967    {
968        attr.group = group;
969    }
970    attr.mask = PVFS_ATTR_SYS_UID | PVFS_ATTR_SYS_GID;
971
972    rc = iocommon_setattr(pd->pvfs_ref, &attr);
973
974    return rc;
975}
976
977int iocommon_chmod(pvfs_descriptor *pd, mode_t mode)
978{
979    int                  rc = 0;
980    PVFS_sys_attr        attr;
981
982    attr.perms = mode & 07777; /* mask off any stray bits */
983    attr.mask = PVFS_ATTR_SYS_PERM;
984
985    rc = iocommon_setattr(pd->pvfs_ref, &attr);
986
987    return rc;
988}
989
990iocommon_make_directory(const char *pvfs_path,
991                        const int mode,
992                        PVFS_object_ref *pdir)
993{
994    int rc = 0;
995    char *parentdir = NULL;
996    char *filename = NULL;
997    PVFS_sys_attr       attr;
998    PVFS_sysresp_lookup resp_lookup;
999    PVFS_object_ref     parent_ref;
1000    PVFS_sysresp_mkdir  resp_mkdir;
1001    PVFS_credentials    *credentials;
1002
1003    /* Initialize any variables */
1004    memset(&attr,        0, sizeof(attr));
1005    memset(&resp_lookup, 0, sizeof(resp_lookup));
1006    memset(&parent_ref,  0, sizeof(parent_ref));
1007    memset(&resp_mkdir,  0, sizeof(resp_mkdir));
1008
1009    iocommon_cred(&credentials);
1010
1011    rc = split_pathname(pvfs_path, &parentdir, &filename);
1012    if (rc == -1)
1013    {
1014        return -1;
1015    }
1016
1017    /* Make sure we don't try and create the root or current directory */
1018
1019    /* lookup parent */
1020    if (!pdir)
1021    {
1022        rc = iocommon_lookup_absolute(parentdir, &parent_ref);
1023        if (rc == -1)
1024        {
1025            goto errorout;
1026        }
1027    }
1028    else
1029    {
1030        if (!parentdir)
1031        {
1032            rc = iocommon_lookup_relative(parentdir, *pdir,
1033                            PVFS2_LOOKUP_LINK_FOLLOW, &parent_ref);
1034            if (rc == -1)
1035            {
1036                goto errorout;
1037            }
1038        }
1039        else
1040        {
1041            parent_ref = *pdir;
1042        }
1043    }
1044   
1045    /* Set the attributes for the new directory */
1046    attr.owner = (int)getuid;
1047    attr.group = (int)getgid;
1048    attr.perms = mode;
1049    attr.mask = (PVFS_ATTR_SYS_ALL_SETABLE);
1050
1051    rc = PVFS_sys_mkdir(filename,
1052                        parent_ref,
1053                        attr,
1054                        credentials,
1055                        &resp_mkdir, NULL);
1056
1057errorout:
1058    if (parentdir)
1059    {
1060        free(parentdir);
1061    }
1062    if (filename)
1063    {
1064        free(filename);
1065    }   
1066    return(rc);
1067}
1068
1069int iocommon_readlink(pvfs_descriptor *pd, char *buf, int size)
1070{
1071    int                  rc = 0;
1072    PVFS_sys_attr        attr;
1073
1074    /* Initialize any variables */
1075    memset(&attr, 0, sizeof(attr));
1076
1077    rc = iocommon_getattr(pd->pvfs_ref, &attr);
1078
1079    /* copy attributes into standard stat struct */
1080    if (attr.objtype & PVFS_TYPE_SYMLINK)
1081    {
1082        strncpy(buf, attr.link_target, size);
1083    }
1084    else
1085    {
1086        errno = EINVAL;
1087        return -1;
1088    }
1089
1090    return 0;
1091}
1092
1093int iocommon_symlink(const char *pvfs_path,
1094                     const char *link_target,
1095                     PVFS_object_ref *pdir)
1096{
1097    int rc = 0;
1098    char *parentdir = NULL;
1099    char *filename = NULL;
1100    PVFS_sys_attr       attr;
1101    PVFS_object_ref     parent_ref;
1102    PVFS_sysresp_symlink  resp_symlink;
1103    PVFS_credentials    *credentials;
1104
1105    /* Initialize any variables */
1106    memset(&attr,        0, sizeof(attr));
1107    memset(&parent_ref,  0, sizeof(parent_ref));
1108    memset(&resp_symlink,0, sizeof(resp_symlink));
1109
1110    iocommon_cred(&credentials);
1111
1112
1113    rc = split_pathname(pvfs_path, &parentdir, &filename);
1114    if (rc == -1)
1115    {
1116        return -1;
1117    }
1118
1119    /* Make sure we don't try and create the root or current directory */
1120
1121    /* lookup parent */
1122    if (!pdir)
1123    {
1124        rc = iocommon_lookup_absolute(parentdir, &parent_ref);
1125        if (rc == -1)
1126        {
1127            goto errorout;
1128        }
1129    }
1130    else
1131    {
1132        if (!parentdir)
1133        {
1134            rc = iocommon_lookup_relative(parentdir, *pdir,
1135                            PVFS2_LOOKUP_LINK_FOLLOW, &parent_ref);
1136            if (rc == -1)
1137            {
1138                goto errorout;
1139            }
1140        }
1141        else
1142        {
1143            parent_ref = *pdir;
1144        }
1145    }
1146   
1147    /* Set the attributes for the new directory */
1148    attr.owner = getuid();
1149    attr.group = getgid();
1150    attr.perms = 0777;
1151    attr.mask = (PVFS_ATTR_SYS_ALL_SETABLE);
1152
1153    rc = PVFS_sys_symlink(filename,
1154                          parent_ref,
1155                          (char *)link_target,
1156                          attr,
1157                          credentials,
1158                          &resp_symlink,
1159                          NULL);
1160
1161errorout:
1162    if (parentdir)
1163    {
1164        free(parentdir);
1165    }
1166    if (filename)
1167    {
1168        free(filename);
1169    }   
1170    return(rc);
1171}
1172
1173int iocommon_getdents(pvfs_descriptor *pd,
1174                      struct dirent *dirp,
1175                      unsigned int count)
1176{
1177    int rc = 0;
1178    int name_max;
1179    PVFS_credentials *credentials;
1180    PVFS_sysresp_readdir readdir_resp;
1181    PVFS_ds_position token;
1182    int bytes = 0, i = 0;
1183
1184    if (pd->token == PVFS_READDIR_END)
1185    {
1186        return -1;  /* EOF */
1187    }
1188
1189    if (!S_ISDIR(pd->mode))
1190    {
1191        errno = ENOENT;
1192        return -1;
1193    }
1194
1195    /* Initialize */
1196    memset(&readdir_resp, 0, sizeof(readdir_resp));
1197
1198    iocommon_cred(&credentials);
1199
1200    token = pd->token == 0 ? PVFS_READDIR_START : pd->token;
1201
1202    rc = PVFS_sys_readdir(pd->pvfs_ref,
1203                          token,
1204                          count,
1205                          credentials,
1206                          &readdir_resp,
1207                          NULL);
1208    if(rc == -1)
1209    {
1210        return -1;
1211    }
1212    pd->token = readdir_resp.token;
1213    name_max = MIN(NAME_MAX, PVFS_NAME_MAX);
1214    while(readdir_resp.pvfs_dirent_outcount--)
1215    {
1216        /* copy a PVFS_dirent to a struct dirent */
1217        dirp->d_ino = (long)readdir_resp.dirent_array[i].handle;
1218        dirp->d_off = pd->file_pointer;
1219        dirp->d_reclen = sizeof(PVFS_dirent);
1220        memncpy(dirp->d_name, readdir_resp.dirent_array[i].d_name, name_max);
1221        dirp->d_name[name_max] = 0;
1222        pd->file_pointer += sizeof(PVFS_dirent);
1223        bytes += sizeof(PVFS_dirent);
1224    }
1225    free(readdir_resp.dirent_array);
1226    return bytes;
1227}
1228
1229/** Read entries from a directory.
1230 *                 
1231 *  \param token opaque value used to track position in directory
1232 *         when more than one read is required.
1233 *  \param pvfs_dirent_incount maximum number of entries to read, if
1234 *         available, starting from token.
1235PVFS_error PVFS_sys_readdir(
1236    PVFS_object_ref ref,
1237    PVFS_ds_position token,
1238    int32_t pvfs_dirent_incount,
1239    const PVFS_credentials *credentials,
1240    PVFS_sysresp_readdir *resp,
1241    PVFS_hint hints)
1242 */         
1243/** Read entries from a directory and their associated attributes
1244 *  in an efficient manner.
1245 * 
1246 *  \param token opaque value used to track position in directory
1247 *         when more than one read is required.
1248 *  \param pvfs_dirent_incount maximum number of entries to read, if
1249 *         available, starting from token.
1250PVFS_error PVFS_sys_readdirplus(
1251    PVFS_object_ref ref,
1252    PVFS_ds_position token,
1253    int32_t pvfs_dirent_incount,
1254    const PVFS_credentials *credentials,
1255    uint32_t attrmask,
1256    PVFS_sysresp_readdirplus *resp,
1257    PVFS_hint hints)
1258 */
1259
1260int iocommon_access(const char *pvfs_path,
1261                    const int mode,
1262                    const int flags,
1263                    PVFS_object_ref *pdir)
1264{
1265    int rc = 0;
1266    char *parentdir = NULL;
1267    char *file = NULL;
1268    int followflag = PVFS2_LOOKUP_LINK_FOLLOW;
1269    int uid = -1, gid = -1;
1270    PVFS_object_ref parent_ref, file_ref;
1271    PVFS_credentials *credentials;
1272    PVFS_sys_attr attr;
1273
1274    /* Initialize */
1275    memset(&parent_ref, 0, sizeof(parent_ref));
1276    memset(&file_ref, 0, sizeof(file_ref));
1277    memset(&attr, 0, sizeof(attr));
1278
1279    /* Initialize the system interface for this process */
1280    iocommon_ensure_init();
1281    iocommon_cred(&credentials);
1282
1283    rc = split_pathname(pvfs_path, &parentdir, &file);
1284    if (rc == -1)
1285    {
1286        return -1;
1287    }
1288
1289    if (!pdir)
1290    {
1291        rc = iocommon_lookup_absolute(parentdir, &parent_ref);
1292        if (rc == -1)
1293        {
1294            goto errorout;
1295        }
1296    }
1297    else
1298    {
1299        if (!parentdir)
1300        {
1301            rc = iocommon_lookup_relative(parentdir, *pdir,
1302                            PVFS2_LOOKUP_LINK_FOLLOW, &parent_ref);
1303            if (rc == -1)
1304            {
1305                goto errorout;
1306            }
1307        }
1308        else
1309        {
1310            parent_ref = *pdir;
1311        }
1312    }
1313    /* Attempt to find file */
1314    if (flags & AT_SYMLINK_NOFOLLOW)
1315    {
1316        followflag = PVFS2_LOOKUP_LINK_NO_FOLLOW;
1317    }
1318    rc = iocommon_lookup_relative(file,
1319                                  parent_ref,
1320                                  followflag,
1321                                  &file_ref);
1322    if (rc)
1323    {
1324        /* File was not found */
1325        goto errorout;
1326    }
1327    /* Get file atributes */
1328    rc = iocommon_getattr(file_ref, &attr);
1329    if (rc)
1330    {
1331        goto errorout;
1332    }
1333    if (flags & AT_EACCESS)
1334    {
1335        uid = getuid();
1336        gid = getgid();
1337    }
1338    else
1339    {
1340        uid = geteuid();
1341        gid = getegid();
1342    }
1343    if (uid == attr.owner)
1344    {
1345        if (((R_OK & mode) && !(S_IRUSR & attr.perms)) ||
1346           ((W_OK & mode) && !(S_IWUSR & attr.perms)) ||
1347           ((X_OK & mode) && !(S_IXUSR & attr.perms)))
1348        {
1349            errno = EACCES;
1350            rc = -1;
1351            goto errorout;
1352        }
1353    }
1354    else if (gid == attr.group)
1355    {
1356        if (((R_OK & mode) && !(S_IRGRP & attr.perms)) ||
1357           ((W_OK & mode) && !(S_IWGRP & attr.perms)) ||
1358           ((X_OK & mode) && !(S_IXGRP & attr.perms)))
1359        {
1360            errno = EACCES;
1361            rc = -1;
1362            goto errorout;
1363        }
1364    }
1365    else
1366    {
1367        if (((R_OK & mode) && !(S_IROTH & attr.perms)) ||
1368           ((W_OK & mode) && !(S_IWOTH & attr.perms)) ||
1369           ((X_OK & mode) && !(S_IXOTH & attr.perms)))
1370        {
1371            errno = EACCES;
1372            rc = -1;
1373            goto errorout;
1374        }
1375    }
1376    /* Access is allowed, rc should be 0 */ 
1377
1378errorout:
1379    if (parentdir)
1380    {
1381        free(parentdir);
1382    }
1383    if (file)
1384    {
1385        free(file);
1386    }
1387    return rc;
1388}
1389
1390
1391/*
1392 * Local variables:
1393 *  c-indent-level: 4
1394 *  c-basic-offset: 4
1395 * End:
1396 *
1397 * vim: ts=4 sts=4 sw=4 expandtab
1398 */
1399
Note: See TracBrowser for help on using the browser.