root/branches/stable/src/client/usrint/openfile-util.c @ 9277

Revision 9277, 32.6 KB (checked in by walt, 14 months ago)

several bog fixes and cleanups
added layout LOCAL
added hint support for pvfs_open()

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 - routines to manage open files
11 */
12#define USRINT_SOURCE 1
13#include "usrint.h"
14#include <sys/syscall.h>
15#ifndef SYS_readdir
16#define SYS_readdir 89
17#endif
18#include "posix-ops.h"
19#include "openfile-util.h"
20#include "posix-pvfs.h"
21#ifdef PVFS_AIO_ENABLE
22#include "aiocommon.h"
23#endif
24
25#if PVFS_UCACHE_ENABLE
26#include "ucache.h"
27#endif
28
29static struct glibc_redirect_s
30{
31    int (*stat)(int ver, const char *path, struct stat *buf);
32    int (*stat64)(int ver, const char *path, struct stat64 *buf);
33    int (*fstat)(int ver, int fd, struct stat *buf);
34    int (*fstat64)(int ver, int fd, struct stat64 *buf);
35    int (*fstatat)(int ver, int fd, const char *path, struct stat *buf, int flag);
36    int (*fstatat64)(int ver, int fd, const char *path, struct stat64 *buf, int flag);
37    int (*lstat)(int ver, const char *path, struct stat *buf);
38    int (*lstat64)(int ver, const char *path, struct stat64 *buf);
39    int (*mknod)(int ver, const char *path, mode_t mode, dev_t dev);
40    int (*mknodat)(int ver, int dirfd, const char *path, mode_t mode, dev_t dev);
41} glibc_redirect;
42
43#define PREALLOC 3
44static char logfilepath[30];
45static int logfile;
46static int descriptor_table_count = 0;
47static int descriptor_table_size = 0;
48static pvfs_descriptor **descriptor_table;
49static char rstate[256];  /* used for random number generation */
50
51posix_ops glibc_ops;
52
53pvfs_descriptor_status pvfs_stdin_status =
54{
55    .dup_cnt = 1,
56    .fsops = &glibc_ops,
57    .pvfs_ref.fs_id = 0,
58    .pvfs_ref.handle = 0,
59    .flags = O_RDONLY,
60    .mode = 0,
61    .file_pointer = 0,
62    .token = 0,
63    .dpath = NULL,
64    .fent = NULL
65};
66
67pvfs_descriptor pvfs_stdin =
68{
69    .is_in_use = PVFS_FS,
70    .fd = 0,
71    .true_fd = STDIN_FILENO,
72    .fdflags = 0,
73    .s = &pvfs_stdin_status
74};
75
76pvfs_descriptor_status pvfs_stdout_status =
77{
78    .dup_cnt = 1,
79    .fsops = &glibc_ops,
80    .pvfs_ref.fs_id = 0,
81    .pvfs_ref.handle = 0,
82    .flags = O_WRONLY | O_APPEND,
83    .mode = 0,
84    .file_pointer = 0,
85    .token = 0,
86    .dpath = NULL,
87    .fent = NULL
88};
89
90pvfs_descriptor pvfs_stdout =
91{
92    .is_in_use = PVFS_FS,
93    .fd = 1,
94    .true_fd = STDOUT_FILENO,
95    .fdflags = 0,
96    .s = &pvfs_stdout_status
97};
98
99pvfs_descriptor_status pvfs_stderr_status =
100{
101    .dup_cnt = 1,
102    .fsops = &glibc_ops,
103    .pvfs_ref.fs_id = 0,
104    .pvfs_ref.handle = 0,
105    .flags = O_WRONLY | O_APPEND,
106    .mode = 0,
107    .file_pointer = 0,
108    .token = 0,
109    .dpath = NULL,
110    .fent = NULL
111};
112
113pvfs_descriptor pvfs_stderr =
114{
115    .is_in_use = PVFS_FS,
116    .fd = 2,
117    .true_fd = STDERR_FILENO,
118    .fdflags = 0,
119    .s = &pvfs_stderr_status
120};
121
122static int my_glibc_stat(const char *path, struct stat *buf)
123{
124    int rc = glibc_redirect.stat(_STAT_VER, path, buf);
125    return rc;
126}
127
128static int my_glibc_stat64(const char *path, struct stat64 *buf)
129{
130    int rc = glibc_redirect.stat64(_STAT_VER, path, buf);
131    return rc;
132}
133
134static int my_glibc_fstat(int fd, struct stat *buf)
135{
136    return glibc_redirect.fstat(_STAT_VER, fd, buf);
137}
138
139static int my_glibc_fstat64(int fd, struct stat64 *buf)
140{
141    return glibc_redirect.fstat64(_STAT_VER, fd, buf);
142}
143
144static int my_glibc_fstatat(int fd, const char *path, struct stat *buf, int flag)
145{
146    return glibc_redirect.fstatat(_STAT_VER, fd, path, buf, flag);
147}
148
149static int my_glibc_fstatat64(int fd, const char *path, struct stat64 *buf, int flag)
150{
151    return glibc_redirect.fstatat64(_STAT_VER, fd, path, buf, flag);
152}
153
154static int my_glibc_lstat(const char *path, struct stat *buf)
155{
156    return glibc_redirect.lstat(_STAT_VER, path, buf);
157}
158
159static int my_glibc_lstat64(const char *path, struct stat64 *buf)
160{
161    return glibc_redirect.lstat64(_STAT_VER, path, buf);
162}
163
164static int my_glibc_mknod(const char *path, mode_t mode, dev_t dev)
165{
166    return glibc_redirect.mknod(_MKNOD_VER, path, mode, dev);
167}
168
169static int my_glibc_mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
170{
171    return glibc_redirect.mknodat(_MKNOD_VER, dirfd, path, mode, dev);
172}
173
174static int my_glibc_getdents(u_int fd, struct dirent *dirp, u_int count)
175{
176    return syscall(SYS_getdents, fd, dirp, count);
177}
178
179static int my_glibc_getdents64(u_int fd, struct dirent64 *dirp, u_int count)
180{
181    return syscall(SYS_getdents64, fd, dirp, count);
182}
183
184static int my_glibc_fadvise64(int fd, off64_t offset, off64_t len, int advice)
185{
186    return syscall(SYS_fadvise64, fd, offset, len, advice);
187}
188
189static int my_glibc_fadvise(int fd, off_t offset, off_t len, int advice)
190{
191    return my_glibc_fadvise64(fd, (off64_t)offset, (off64_t)len, advice);
192}
193
194static int my_glibc_readdir(u_int fd, struct dirent *dirp, u_int count)
195{
196    return syscall(SYS_readdir, fd, dirp, count);
197}
198
199static int my_glibc_getcwd(char *buf, unsigned long size)
200{
201    return syscall(SYS_getcwd, buf, size);
202}
203
204void load_glibc(void)
205{
206    memset((void *)&glibc_ops, 0, sizeof(glibc_ops));
207    glibc_ops.open = dlsym(RTLD_NEXT, "open");
208    glibc_ops.open64 = dlsym(RTLD_NEXT, "open64");
209    glibc_ops.openat = dlsym(RTLD_NEXT, "openat");
210    glibc_ops.openat64 = dlsym(RTLD_NEXT, "openat64");
211    glibc_ops.creat = dlsym(RTLD_NEXT, "creat");
212    glibc_ops.creat64 = dlsym(RTLD_NEXT, "creat64");
213    glibc_ops.unlink = dlsym(RTLD_NEXT, "unlink");
214    glibc_ops.unlinkat = dlsym(RTLD_NEXT, "unlinkat");
215    glibc_ops.rename = dlsym(RTLD_NEXT, "rename");
216    glibc_ops.renameat = dlsym(RTLD_NEXT, "renameat");
217    glibc_ops.read = dlsym(RTLD_NEXT, "read");
218    glibc_ops.pread = dlsym(RTLD_NEXT, "pread");
219    glibc_ops.readv = dlsym(RTLD_NEXT, "readv");
220    glibc_ops.pread64 = dlsym(RTLD_NEXT, "pread64");
221    glibc_ops.write = dlsym(RTLD_NEXT, "write");
222    glibc_ops.pwrite = dlsym(RTLD_NEXT, "pwrite");
223    glibc_ops.writev = dlsym(RTLD_NEXT, "writev");
224    glibc_ops.pwrite64 = dlsym(RTLD_NEXT, "pwrite64");
225    glibc_ops.lseek = dlsym(RTLD_NEXT, "lseek");
226    glibc_ops.lseek64 = dlsym(RTLD_NEXT, "lseek64");
227    glibc_ops.truncate = dlsym(RTLD_NEXT, "truncate");
228    glibc_ops.truncate64 = dlsym(RTLD_NEXT, "truncate64");
229    glibc_ops.ftruncate = dlsym(RTLD_NEXT, "ftruncate");
230    glibc_ops.ftruncate64 = dlsym(RTLD_NEXT, "ftruncate64");
231    glibc_ops.fallocate = dlsym(RTLD_NEXT, "posix_fallocate");
232    glibc_ops.close = dlsym(RTLD_NEXT, "close");
233    glibc_ops.stat = my_glibc_stat;
234    glibc_redirect.stat = dlsym(RTLD_NEXT, "__xstat");
235    glibc_ops.stat64 = my_glibc_stat64;
236    glibc_redirect.stat64 = dlsym(RTLD_NEXT, "__xstat64");
237    glibc_ops.fstat = my_glibc_fstat;
238    glibc_redirect.fstat = dlsym(RTLD_NEXT, "__fxstat");
239    glibc_ops.fstat64 = my_glibc_fstat64;
240    glibc_redirect.fstat64 = dlsym(RTLD_NEXT, "__fxstat64");
241    glibc_ops.fstatat = my_glibc_fstatat;
242    glibc_redirect.fstatat = dlsym(RTLD_NEXT, "__fxstatat");
243    glibc_ops.fstatat64 = my_glibc_fstatat64;
244    glibc_redirect.fstatat64 = dlsym(RTLD_NEXT, "__fxstatat64");
245    glibc_ops.lstat = my_glibc_lstat;
246    glibc_redirect.lstat = dlsym(RTLD_NEXT, "__lxstat");
247    glibc_ops.lstat64 = my_glibc_lstat64;
248    glibc_redirect.lstat64 = dlsym(RTLD_NEXT, "__lxstat64");
249    glibc_ops.futimesat = dlsym(RTLD_NEXT, "futimesat");
250    glibc_ops.utimes = dlsym(RTLD_NEXT, "utimes");
251    glibc_ops.utime = dlsym(RTLD_NEXT, "utime");
252    glibc_ops.futimes = dlsym(RTLD_NEXT, "futimes");
253    glibc_ops.dup = dlsym(RTLD_NEXT, "dup");
254    glibc_ops.dup2 = dlsym(RTLD_NEXT, "dup2");
255    glibc_ops.chown = dlsym(RTLD_NEXT, "chown");
256    glibc_ops.fchown = dlsym(RTLD_NEXT, "fchown");
257    glibc_ops.fchownat = dlsym(RTLD_NEXT, "fchownat");
258    glibc_ops.lchown = dlsym(RTLD_NEXT, "lchown");
259    glibc_ops.chmod = dlsym(RTLD_NEXT, "chmod");
260    glibc_ops.fchmod = dlsym(RTLD_NEXT, "fchmod");
261    glibc_ops.fchmodat = dlsym(RTLD_NEXT, "fchmodat");
262    glibc_ops.mkdir = dlsym(RTLD_NEXT, "mkdir");
263    glibc_ops.mkdirat = dlsym(RTLD_NEXT, "mkdirat");
264    glibc_ops.rmdir = dlsym(RTLD_NEXT, "rmdir");
265    glibc_ops.readlink = dlsym(RTLD_NEXT, "readlink");
266    glibc_ops.readlinkat = dlsym(RTLD_NEXT, "readlinkat");
267    glibc_ops.symlink = dlsym(RTLD_NEXT, "symlink");
268    glibc_ops.symlinkat = dlsym(RTLD_NEXT, "symlinkat");
269    glibc_ops.link = dlsym(RTLD_NEXT, "link");
270    glibc_ops.linkat = dlsym(RTLD_NEXT, "linkat");
271    glibc_ops.readdir = my_glibc_readdir;
272    glibc_ops.getdents = my_glibc_getdents;
273    glibc_ops.getdents64 = my_glibc_getdents64;
274    glibc_ops.access = dlsym(RTLD_NEXT, "access");
275    glibc_ops.faccessat = dlsym(RTLD_NEXT, "faccessat");
276    glibc_ops.flock = dlsym(RTLD_NEXT, "flock");
277    glibc_ops.fcntl = dlsym(RTLD_NEXT, "fcntl");
278    glibc_ops.sync = dlsym(RTLD_NEXT, "sync");
279    glibc_ops.fsync = dlsym(RTLD_NEXT, "fsync");
280    glibc_ops.fdatasync = dlsym(RTLD_NEXT, "fdatasync");
281    glibc_ops.fadvise = my_glibc_fadvise;
282    glibc_ops.fadvise64 = my_glibc_fadvise64;
283    glibc_ops.statfs = dlsym(RTLD_NEXT, "statfs");
284    glibc_ops.statfs64 = dlsym(RTLD_NEXT, "statfs64");
285    glibc_ops.fstatfs = dlsym(RTLD_NEXT, "fstatfs");
286    glibc_ops.fstatfs64 = dlsym(RTLD_NEXT, "fstatfs64");
287    glibc_ops.statvfs = dlsym(RTLD_NEXT, "statvfs");
288    glibc_ops.fstatvfs = dlsym(RTLD_NEXT, "fstatvfs");
289    glibc_ops.mknod = my_glibc_mknod;
290    glibc_redirect.mknod = dlsym(RTLD_NEXT, "__xmknod");
291    glibc_ops.mknodat = my_glibc_mknodat;
292    glibc_redirect.mknodat = dlsym(RTLD_NEXT, "__xmknodat");
293    glibc_ops.sendfile = dlsym(RTLD_NEXT, "sendfile");
294    glibc_ops.sendfile64 = dlsym(RTLD_NEXT, "sendfile64");
295#ifdef HAVE_ATTR_XATTR_H
296    glibc_ops.setxattr = dlsym(RTLD_NEXT, "setxattr");
297    glibc_ops.lsetxattr = dlsym(RTLD_NEXT, "lsetxattr");
298    glibc_ops.fsetxattr = dlsym(RTLD_NEXT, "fsetxattr");
299    glibc_ops.getxattr = dlsym(RTLD_NEXT, "getxattr");
300    glibc_ops.lgetxattr = dlsym(RTLD_NEXT, "lgetxattr");
301    glibc_ops.fgetxattr = dlsym(RTLD_NEXT, "fgetxattr");
302    glibc_ops.listxattr = dlsym(RTLD_NEXT, "listxattr");
303    glibc_ops.llistxattr = dlsym(RTLD_NEXT, "llistxattr");
304    glibc_ops.flistxattr = dlsym(RTLD_NEXT, "flistxattr");
305    glibc_ops.removexattr = dlsym(RTLD_NEXT, "removexattr");
306    glibc_ops.lremovexattr = dlsym(RTLD_NEXT, "lremovexattr");
307    glibc_ops.fremovexattr = dlsym(RTLD_NEXT, "fremovexattr");
308#endif
309    glibc_ops.socket = dlsym(RTLD_NEXT, "socket");
310    glibc_ops.accept = dlsym(RTLD_NEXT, "accept");
311    glibc_ops.bind = dlsym(RTLD_NEXT, "bind");
312    glibc_ops.connect = dlsym(RTLD_NEXT, "connect");
313    glibc_ops.getpeername = dlsym(RTLD_NEXT, "getpeername");
314    glibc_ops.getsockname = dlsym(RTLD_NEXT, "getsockname");
315    glibc_ops.getsockopt = dlsym(RTLD_NEXT, "getsockopt");
316    glibc_ops.setsockopt = dlsym(RTLD_NEXT, "setsockopt");
317    glibc_ops.ioctl = dlsym(RTLD_NEXT, "ioctl");
318    glibc_ops.listen = dlsym(RTLD_NEXT, "listen");
319    glibc_ops.recv = dlsym(RTLD_NEXT, "recv");
320    glibc_ops.recvfrom = dlsym(RTLD_NEXT, "recvfrom");
321    glibc_ops.recvmsg = dlsym(RTLD_NEXT, "recvmsg");
322    //glibc_ops.select = dlsym(RTLD_NEXT, "select");
323    //glibc_ops.FD_CLR = dlsym(RTLD_NEXT, "FD_CLR");
324    //glibc_ops.FD_ISSET = dlsym(RTLD_NEXT, "FD_ISSET");
325    //glibc_ops.FD_SET = dlsym(RTLD_NEXT, "FD_SET");
326    //glibc_ops.FD_ZERO = dlsym(RTLD_NEXT, "FD_ZERO");
327    //glibc_ops.pselect = dlsym(RTLD_NEXT, "pselect");
328    glibc_ops.send = dlsym(RTLD_NEXT, "send");
329    glibc_ops.sendto = dlsym(RTLD_NEXT, "sendto");
330    glibc_ops.sendmsg = dlsym(RTLD_NEXT, "sendmsg");
331    glibc_ops.shutdown = dlsym(RTLD_NEXT, "shutdown");
332    glibc_ops.socketpair = dlsym(RTLD_NEXT, "socketpair");
333    glibc_ops.pipe = dlsym(RTLD_NEXT, "pipe");
334    glibc_ops.umask = dlsym(RTLD_NEXT, "umask");
335    glibc_ops.getumask = dlsym(RTLD_NEXT, "getumask");
336    glibc_ops.getdtablesize = dlsym(RTLD_NEXT, "getdtablesize");
337    glibc_ops.mmap = dlsym(RTLD_NEXT, "mmap");
338    glibc_ops.munmap = dlsym(RTLD_NEXT, "munmap");
339    glibc_ops.msync = dlsym(RTLD_NEXT, "msync");
340#if 0
341    glibc_ops.acl_delete_def_file = dlsym(RTLD_NEXT, "acl_delete_def_file");
342    glibc_ops.acl_get_fd = dlsym(RTLD_NEXT, "acl_get_fd");
343    glibc_ops.acl_get_file = dlsym(RTLD_NEXT, "acl_get_file");
344    glibc_ops.acl_set_fd = dlsym(RTLD_NEXT, "acl_set_fd");
345    glibc_ops.acl_set_file = dlsym(RTLD_NEXT, "acl_set_file");
346#endif
347
348/* PVFS does not implement socket ops */
349    pvfs_ops.socket = dlsym(RTLD_NEXT, "socket");
350    pvfs_ops.accept = dlsym(RTLD_NEXT, "accept");
351    pvfs_ops.bind = dlsym(RTLD_NEXT, "bind");
352    pvfs_ops.connect = dlsym(RTLD_NEXT, "connect");
353    pvfs_ops.getpeername = dlsym(RTLD_NEXT, "getpeername");
354    pvfs_ops.getsockname = dlsym(RTLD_NEXT, "getsockname");
355    pvfs_ops.getsockopt = dlsym(RTLD_NEXT, "getsockopt");
356    pvfs_ops.setsockopt = dlsym(RTLD_NEXT, "setsockopt");
357    pvfs_ops.ioctl = dlsym(RTLD_NEXT, "ioctl");
358    pvfs_ops.listen = dlsym(RTLD_NEXT, "listen");
359    pvfs_ops.recv = dlsym(RTLD_NEXT, "recv");
360    pvfs_ops.recvfrom = dlsym(RTLD_NEXT, "recvfrom");
361    pvfs_ops.recvmsg = dlsym(RTLD_NEXT, "recvmsg");
362    //pvfs_ops.select = dlsym(RTLD_NEXT, "select");
363    //pvfs_ops.FD_CLR = dlsym(RTLD_NEXT, "FD_CLR");
364    //pvfs_ops.FD_ISSET = dlsym(RTLD_NEXT, "FD_ISSET");
365    //pvfs_ops.FD_SET = dlsym(RTLD_NEXT, "FD_SET");
366    //pvfs_ops.FD_ZERO = dlsym(RTLD_NEXT, "FD_ZERO");
367    //pvfs_ops.pselect = dlsym(RTLD_NEXT, "pselect");
368    pvfs_ops.send = dlsym(RTLD_NEXT, "send");
369    pvfs_ops.sendto = dlsym(RTLD_NEXT, "sendto");
370    pvfs_ops.sendmsg = dlsym(RTLD_NEXT, "sendmsg");
371    pvfs_ops.shutdown = dlsym(RTLD_NEXT, "shutdown");
372    pvfs_ops.socketpair = dlsym(RTLD_NEXT, "socketpair");
373    pvfs_ops.pipe = dlsym(RTLD_NEXT, "pipe");
374}
375
376/*
377 * runs on exit to do any cleanup
378 */
379static void usrint_cleanup(void)
380{
381    /* later check for an error that might want us */
382    /* to keep this - for now it is empty */
383    glibc_ops.unlink(logfilepath);
384    /* cache cleanup? */
385#if 0
386    if (ucache_enabled)
387    {
388        ucache_finalize();
389    }
390#endif
391    PVFS_sys_finalize();
392}
393
394#if PVFS_UCACHE_ENABLE
395/*
396 * access function to see if cache is currently enabled
397 * only used by code ouside of this module
398 */
399int pvfs_ucache_enabled(void)
400{
401    return ucache_enabled;
402}
403#endif
404
405void pvfs_sys_init_doit(void);
406
407int pvfs_sys_init(void)
408{
409    static int pvfs_initializing_flag = 0;
410    static int pvfs_lib_lock_initialized = 0; /* recursive lock init flag */
411    static int pvfs_lib_init_flag = 0;
412
413    int rc = 0;
414
415    /* Mutex protecting initialization of recursive mutex */
416    static gen_mutex_t mutex_mutex = GEN_MUTEX_INITIALIZER;
417    /* The recursive mutex */
418    static pthread_mutex_t rec_mutex;
419
420    if(pvfs_lib_init_flag)
421        return 0;
422
423    if(!pvfs_lib_lock_initialized)
424    {
425        rc = gen_mutex_lock(&mutex_mutex);
426        if(!pvfs_lib_lock_initialized)
427        {
428            //init recursive mutex
429            pthread_mutexattr_t rec_attr;
430            rc = pthread_mutexattr_init(&rec_attr);
431            rc = pthread_mutexattr_settype(&rec_attr, PTHREAD_MUTEX_RECURSIVE);
432            rc = pthread_mutex_init(&rec_mutex, &rec_attr);
433            rc = pthread_mutexattr_destroy(&rec_attr);
434            pvfs_lib_lock_initialized = 1;
435        }
436        rc = gen_mutex_unlock(&mutex_mutex);
437    }
438
439    rc = pthread_mutex_lock(&rec_mutex);
440    if(pvfs_lib_init_flag || pvfs_initializing_flag)
441    {
442        rc = pthread_mutex_unlock(&rec_mutex);
443        return 1;
444    }
445
446    /* set this to prevent pvfs_sys_init from running recursively (indirect) */
447    pvfs_initializing_flag = 1;
448
449    //Perform Init
450    pvfs_sys_init_doit();
451    pvfs_initializing_flag = 0;
452    pvfs_lib_init_flag = 1;
453    rc = pthread_mutex_unlock(&rec_mutex);
454    return 0;
455}
456
457/*
458 * Perform PVFS initialization tasks
459 */
460void pvfs_sys_init_doit(void) {
461    struct rlimit rl;
462        int rc;
463    char curdir[PVFS_PATH_MAX];
464
465    /* this allows system calls to run */
466    load_glibc();
467    PINT_initrand();
468
469    /* if this fails not much we can do about it */
470    atexit(usrint_cleanup);
471
472    /* set up current working dir */
473    memset(curdir, 0, sizeof(curdir));
474    rc = my_glibc_getcwd(curdir, PVFS_PATH_MAX);
475    if (rc < 0)
476    {
477        perror("failed to get CWD");
478        exit(-1);
479    }
480    pvfs_cwd_init(curdir, PVFS_PATH_MAX);
481
482        rc = getrlimit(RLIMIT_NOFILE, &rl);
483        /* need to check for "INFINITY" */
484
485    /* set up descriptor table */
486        descriptor_table_size = rl.rlim_max;
487        descriptor_table =
488                        (pvfs_descriptor **)malloc(sizeof(pvfs_descriptor *) *
489                        descriptor_table_size);
490    if (!descriptor_table)
491    {
492        perror("failed to malloc descriptor table");
493        exit(-1);
494    }
495        memset(descriptor_table, 0,
496                        (sizeof(pvfs_descriptor *) * descriptor_table_size));
497    descriptor_table[0] = &pvfs_stdin;
498    gen_mutex_init(&pvfs_stdin.lock);
499    gen_mutex_init(&pvfs_stdin.s->lock);
500    descriptor_table[1] = &pvfs_stdout;
501    gen_mutex_init(&pvfs_stdout.lock);
502    gen_mutex_init(&pvfs_stdin.s->lock);
503    descriptor_table[2] = &pvfs_stderr;
504    gen_mutex_init(&pvfs_stderr.lock);
505    gen_mutex_init(&pvfs_stdin.s->lock);
506    descriptor_table_count = PREALLOC;
507
508    /* open log file */
509    /* we dupe this FD to get FD's for pvfs files */
510    memset(logfilepath, 0, sizeof(logfilepath));
511    snprintf(logfilepath, 25, "/tmp/pvfsuid-%05d.log", (int)(getuid()));
512    logfile = glibc_ops.open(logfilepath, O_RDWR|O_CREAT, 0600);
513    if (logfile < 0)
514    {
515        perror("failed in pvfs_sys_init");
516        exit(-1);
517    }
518
519        /* initalize PVFS */
520    /* this is very complex so most stuff needs to work
521     * before we do this
522     */
523        PVFS_util_init_defaults();
524    if (errno == EINPROGRESS)
525    {
526        errno = 0;
527    }
528
529    /* call other initialization routines */
530
531#if PVFS_UCACHE_ENABLE
532    //gossip_enable_file(UCACHE_LOG_FILE, "a");
533    //gossip_enable_stderr();
534
535    /* ucache initialization - assumes shared memory previously
536     * aquired (using ucache daemon)
537     */
538    rc = ucache_initialize();
539    if (rc < 0)
540    {
541        /* ucache failed to initialize, so continue without it */
542        /* Write a warning message in the ucache.log letting programmer know */
543        ucache_enabled = 0;
544
545        /* Enable the writing of the error message and write the message to file. */
546        //gossip_set_debug_mask(1, GOSSIP_UCACHE_DEBUG);
547        //gossip_debug(GOSSIP_UCACHE_DEBUG,
548        //    "WARNING: client caching configured enabled but couldn't inizialize\n");
549    }
550#endif
551
552#if PVFS_AIO_ENABLE
553   /* initialize aio interface */
554   aiocommon_init();
555#endif
556}
557
558int pvfs_descriptor_table_size(void)
559{
560    return descriptor_table_size;
561}
562
563/*
564 * Allocate a new pvfs_descriptor
565 * initialize fsops to the given set
566 */
567 pvfs_descriptor *pvfs_alloc_descriptor(posix_ops *fsops,
568                                        int fd,
569                                        PVFS_object_ref *file_ref,
570                                        int use_cache)
571 {
572    int newfd, flags = 0;
573    pvfs_descriptor *pd;
574
575    pvfs_sys_init();
576    if (fsops == NULL)
577    {
578        errno = EINVAL;
579        return NULL;
580    }
581    if (fd == -1)
582    {
583        /* PVFS file allocate a real descriptor for it */
584        newfd = glibc_ops.dup(logfile);
585    }
586    else
587    {
588        /* opened by glibc, make sure this is a valid fd */
589        newfd = fd;
590        flags = glibc_ops.fcntl(newfd, F_GETFL);
591        if (flags < 0)
592        {
593            return NULL;
594        }
595        if (descriptor_table[newfd] != NULL)
596        {
597            errno = EINVAL;
598            return NULL;
599        }
600    }
601
602    /* allocate new descriptor */
603        descriptor_table_count++;
604    pd = (pvfs_descriptor *)malloc(sizeof(pvfs_descriptor));
605
606    if (!pd)
607    {
608        return NULL;
609    }
610    memset(pd, 0, sizeof(pvfs_descriptor));
611
612    gen_mutex_init(&pd->lock);
613    gen_mutex_lock(&pd->lock);
614    descriptor_table[newfd] = pd;
615
616    pd->s = (pvfs_descriptor_status *)malloc(sizeof(pvfs_descriptor_status));
617    if (!pd->s)
618    {
619        free(pd);
620        return NULL;
621    }
622    memset(pd->s, 0, sizeof(pvfs_descriptor_status));
623
624    gen_mutex_init(&pd->s->lock);
625    gen_mutex_lock(&pd->s->lock);
626
627        /* fill in descriptor */
628        pd->is_in_use = PVFS_FS;
629        pd->fd = newfd;
630        pd->true_fd = newfd;
631        pd->fdflags = 0;
632
633    /*
634    if (!use_cache)
635    {
636            pd->fdflags |= PVFS_FD_NOCACHE;
637    }
638    */
639        pd->s->dup_cnt = 1;
640        pd->s->fsops = fsops;
641    if (file_ref)
642    {
643            pd->s->pvfs_ref.fs_id = file_ref->fs_id;
644            pd->s->pvfs_ref.handle = file_ref->handle;
645    }
646    else
647    {
648        /* if this is not a PVFS file then the file_ref will be NULL */
649            pd->s->pvfs_ref.fs_id = 0;
650            pd->s->pvfs_ref.handle = 0LL;
651    }
652
653    pd->s->flags = flags;
654    pd->s->mode = 0; /* this should be filled in by caller */
655    pd->s->file_pointer = 0;
656    pd->s->token = 0;
657    pd->s->dpath = NULL;
658    pd->s->fent = NULL; /* not caching if left NULL */
659
660#if PVFS_UCACHE_ENABLE
661    if (ucache_enabled /* && use_cache*/ )
662    {
663        /* File reference won't always be passed in */
664        if(file_ref != NULL)
665        {
666            /* We have the file identifiers
667             * so insert file info into ucache
668             * this fills in mtbl
669             */
670            ucache_open_file(&(file_ref->fs_id),
671                             &(file_ref->handle),
672                             &(pd->s->fent));
673        }
674    }
675#endif /* PVFS_UCACHE_ENABLE */
676
677    /* NEW PD IS STILL LOCKED */
678    return pd;
679}
680
681/*
682 * Function for duplicating a descriptor - used in dup and dup2 calls
683 */
684int pvfs_dup_descriptor(int oldfd, int newfd)
685{
686    int rc = 0;
687    pvfs_descriptor *pd;
688
689    pvfs_sys_init();
690    if (oldfd < 0 || oldfd >= descriptor_table_size)
691    {
692        errno = EBADF;
693        return -1;
694    }
695    if (newfd == -1) /* dup */
696    {
697        newfd = glibc_ops.dup(logfile);
698        if (newfd < 0)
699        {
700            return newfd;
701        }
702    }
703    else /* dup2 */
704    {
705        /* see if requested fd is in use */
706        if (descriptor_table[newfd] != NULL)
707        {
708            /* check for special case */
709            if (newfd == oldfd)
710            {
711                return oldfd;
712            }
713            /* close old file in new slot */
714            rc = pvfs_free_descriptor(newfd);
715            if (rc < 0)
716            {
717                return rc;
718            }
719        }
720        /* continuing with dup2 */
721        rc = glibc_ops.dup2(oldfd, newfd);
722        if (rc < 0)
723        {
724            return rc;
725        }
726    }
727    /* new set up new pvfs_descfriptor */
728        descriptor_table_count++;
729    pd = (pvfs_descriptor *)malloc(sizeof(pvfs_descriptor));
730    if (!pd)
731    {
732        return -1;
733    }
734    memset(pd, 0, sizeof(pvfs_descriptor));
735    gen_mutex_init(&pd->lock);
736    gen_mutex_lock(&pd->lock);
737    descriptor_table[newfd] = pd;
738
739        pd->is_in_use = PVFS_FS;
740        pd->fd = newfd;
741        pd->true_fd = newfd;
742        pd->fdflags = 0;
743    /* share the pvfs_desdriptor_status info */
744    pd->s = descriptor_table[oldfd]->s;
745    gen_mutex_lock(&pd->s->lock);
746    pd->s->dup_cnt++;
747    gen_mutex_unlock(&pd->s->lock);
748    gen_mutex_unlock(&pd->lock);
749    return 0;
750}
751
752/*
753 * Return a pointer to the pvfs_descriptor for the file descriptor or null
754 * if there is no entry for the given file descriptor
755 * should probably be inline if we can get at static table that way
756 */
757pvfs_descriptor *pvfs_find_descriptor(int fd)
758{
759    pvfs_descriptor *pd = NULL;
760
761    pvfs_sys_init();
762    if (fd < 0 || fd >= descriptor_table_size)
763    {
764        errno = EBADF;
765        return NULL;
766    }
767    pd = descriptor_table[fd];
768    if (!pd)
769    {
770        int flags = 0;
771        /* see if glibc opened this file without our knowing */
772        flags = glibc_ops.fcntl(fd, F_GETFL);
773        if (flags == -1)
774        {
775            /* apparently not */
776            return NULL;
777        }
778        /* allocate a descriptor */
779            descriptor_table_count++;
780        pd = (pvfs_descriptor *)malloc(sizeof(pvfs_descriptor));
781        if (!pd)
782        {
783            return NULL;
784        }
785        memset(pd, 0, sizeof(pvfs_descriptor));
786        gen_mutex_init(&pd->lock);
787        gen_mutex_lock(&pd->lock);
788        descriptor_table[fd] = pd;
789
790        pd->s =
791             (pvfs_descriptor_status *)malloc(sizeof(pvfs_descriptor_status));
792        if (!pd->s)
793        {
794            free(pd);
795            return NULL;
796        }
797        memset(pd->s, 0, sizeof(pvfs_descriptor_status));
798        gen_mutex_init(&pd->s->lock);
799   
800            /* fill in descriptor */
801            pd->is_in_use = PVFS_FS;
802            pd->fd = fd;
803            pd->true_fd = fd;
804            pd->fdflags = 0;
805            pd->s->dup_cnt = 1;
806            pd->s->fsops = &glibc_ops;
807            pd->s->pvfs_ref.fs_id = 0;
808            pd->s->pvfs_ref.handle = 0LL;
809            pd->s->flags = flags;
810            pd->s->mode = 0;
811            pd->s->file_pointer = 0;
812            pd->s->token = 0;
813            pd->s->dpath = NULL;
814        pd->s->fent = NULL; /* not caching if left NULL */
815    }
816    else
817    {
818        /* locks here prevent a thread from getting */
819        /* a pd that is not finish being allocated yet */
820        gen_mutex_lock(&pd->lock);
821        if (pd->is_in_use != PVFS_FS)
822        {
823            errno = EBADF;
824            gen_mutex_unlock(&pd->lock);
825            return NULL;
826        }
827    }
828    gen_mutex_unlock(&pd->lock);
829        return pd;
830}
831
832int pvfs_free_descriptor(int fd)
833{
834    int dup_cnt;
835    pvfs_descriptor *pd = NULL;
836    debug("pvfs_free_descriptor called with %d\n", fd);
837
838    pd = pvfs_find_descriptor(fd);
839    if (pd == NULL)
840    {
841        return -1;
842    }
843
844        /* clear out table entry */
845        descriptor_table[fd] = NULL;
846    glibc_ops.close(fd);
847
848        /* keep up with used descriptors */
849        descriptor_table_count--;
850
851    /* check if last copy */
852    gen_mutex_lock(&pd->s->lock);
853    dup_cnt = --(pd->s->dup_cnt);
854    gen_mutex_unlock(&pd->s->lock);
855    if (dup_cnt <= 0)
856    {
857        if (pd->s->dpath)
858        {
859            free(pd->s->dpath);
860        }
861
862#if PVFS_UCACHE_ENABLE
863        if (pd->s->fent)
864        {
865            int rc = 0;
866            rc = ucache_close_file(pd->s->fent);
867            if(rc == -1)
868            {
869                return rc;
870            }
871        }
872#endif /* PVFS_UCACHE_ENABLE */
873
874        /* free descriptor status - wipe memory first */
875        memset(pd->s, 0, sizeof(pvfs_descriptor_status));
876
877        /* first 3 descriptors not malloc'd */
878        if (fd > 2)
879        {
880                free(pd->s);
881        }
882    }
883        /* free descriptor - wipe memory first */
884        memset(pd, 0, sizeof(pvfs_descriptor));
885    /* first 3 descriptors not malloc'd */
886    if (fd > 2)
887    {
888            free(pd);
889    }
890
891    debug("pvfs_free_descriptor returns %d\n", 0);
892        return 0;
893}
894
895/*
896 * takes a path that is relative to the working dir and
897 * expands it all the way to the root
898 */
899char *pvfs_qualify_path(const char *path)
900{
901    int cdsz, psz, msz;
902    char *rc;
903    char *newpath = NULL;
904    char curdir[PVFS_PATH_MAX];
905
906    if(path[0] != '/')
907    {
908        memset(curdir, 0, PVFS_PATH_MAX);
909        rc = getcwd(curdir, PVFS_PATH_MAX);
910        if (curdir == NULL)
911        {
912            /* ERANGE if need a larger buffer */
913            /* error, bail out */
914            return NULL;
915        }
916        cdsz = strlen(curdir);
917        psz = strlen(path);
918        msz = cdsz + psz + 2;
919        if (msz < 2)
920        {
921            errno = EINVAL;
922            return NULL;
923        }
924        /* allocate buffer for whole path and copy */
925        newpath = (char *)malloc(msz);
926        if (!newpath)
927        {
928            return NULL;
929        }
930        memset(newpath, 0, msz);
931        if (cdsz >= 0) /* zero size copy is bad */
932        {
933            strncpy(newpath, curdir, cdsz);
934        }
935        /* free(curdir); */
936        strncat(newpath, "/", 1);
937        if (psz >= 0) /* zero size copy is bad */
938        {
939            strncat(newpath, path, psz);
940        }
941    }
942    else
943    {
944        newpath = (char *)path;
945    }
946    return newpath;
947}
948
949/**
950 * Determines if a path is part of a PVFS Filesystem
951 *
952 * returns 1 if PVFS 0 otherwise
953 */
954
955int is_pvfs_path(const char *path)
956{
957    int rc = 0;
958    char *newpath = NULL ;
959#if PVFS_USRINT_KMOUNT
960    int npsize;
961    struct stat sbuf;
962    struct statfs fsbuf;
963#else
964    PVFS_fs_id fs_id;
965    char pvfs_path[PVFS_PATH_MAX];
966#endif
967   
968    if(pvfs_sys_init())
969    {
970        return 0;
971    }
972
973    if (!path)
974    {
975        errno = EINVAL;
976        return 0; /* let glibc sort out the error */
977    }
978#if PVFS_USRINT_KMOUNT
979    memset(&sbuf, 0, sizeof(sbuf));
980    memset(&fsbuf, 0, sizeof(fsbuf));
981    npsize = strnlen(path, PVFS_PATH_MAX) + 1;
982    newpath = (char *)malloc(npsize);
983    if (!newpath)
984    {
985        return 0; /* let glibc sort out the error */
986    }
987    strncpy(newpath, path, npsize);
988   
989    /* first try to stat the path */
990    /* this must call standard glibc stat */
991    rc = glibc_ops.stat(newpath, &sbuf);
992    if (rc < 0)
993    {
994        int count;
995        /* path doesn't exist, try removing last segment */
996        for(count = strlen(newpath) - 2; count > 0; count--)
997        {
998            if(newpath[count] == '/')
999            {
1000                newpath[count] = '\0';
1001                break;
1002            }
1003        }
1004        /* this must call standard glibc stat */
1005        rc = glibc_ops.stat(newpath, &sbuf);
1006        if (rc < 0)
1007        {
1008            /* can't find the path must be an error */
1009            free(newpath);
1010            return 0; /* let glibc sort out the error */
1011        }
1012    }
1013    /* this must call standard glibc statfs */
1014    rc = glibc_ops.statfs(newpath, &fsbuf);
1015    free(newpath);
1016    if(fsbuf.f_type == PVFS_FS)
1017    {
1018        return 1; /* PVFS */
1019    }
1020    else
1021    {
1022        return 0; /* not PVFS assume the kernel can handle it */
1023    }
1024/***************************************************************/
1025#else /* PVFS_USRINT_KMOUNT */
1026/***************************************************************/
1027    /* we might not be able to stat the file direcly
1028     * so we will use our resolver to look up the path
1029     * prefix in the mount tab files
1030     */
1031    memset(pvfs_path, 0 , PVFS_PATH_MAX);
1032    newpath = pvfs_qualify_path(path);
1033    rc = PVFS_util_resolve(newpath, &fs_id, pvfs_path, PVFS_PATH_MAX);
1034    if (newpath != path)
1035    {
1036        free(newpath);
1037    }
1038    if (rc < 0)
1039    {
1040        if (rc == -PVFS_ENOENT)
1041        {
1042            return 0; /* not a PVFS path */
1043        }
1044        errno = rc;
1045        return 0; /* an error returned - let glibc deal with it */
1046        // return -1; /* an error returned */
1047    }
1048    return 1; /* a PVFS path */
1049#endif /* PVFS_USRINT_KMOUNT */
1050}
1051
1052/**
1053 * Split a pathname into a directory and a filename.
1054 * If non-null is passed as the directory or filename,
1055 * the field will be allocated and filled with the correct value
1056 *
1057 * A slash at the end of the path is interpreted as no filename
1058 * and is an error.  To parse the last dir in a path, remove this
1059 * trailing slash.  No filename with no directory is OK.
1060 */
1061int split_pathname( const char *path,
1062                    int dirflag,
1063                    char **directory,
1064                    char **filename)
1065{
1066    int i, fnlen, slashes = 0;
1067    int length = strlen("pvfs2");
1068
1069    if (!path || !directory || !filename)
1070    {
1071        errno = EINVAL;
1072        return -1;
1073    }
1074        /* chop off pvfs2 prefix */
1075        if (strncmp(path, "pvfs2:", length) == 0)
1076    {
1077                path = &path[length];
1078    }
1079    /* Split path into a directory and filename */
1080    length = strnlen(path, PVFS_PATH_MAX);
1081    if (length == PVFS_PATH_MAX)
1082    {
1083        errno = ENAMETOOLONG;
1084        return -1;
1085    }
1086    i = length - 1;
1087    if (dirflag)
1088    {
1089        /* skip any trailing slashes */
1090        for(; i >= 0 && path[i] == '/'; i--)
1091        {
1092            slashes++;
1093        }
1094    }
1095    for (; i >= 0; i--)
1096    {
1097        if (path[i] == '/')
1098        {
1099            /* parse the directory */
1100            *directory = malloc(i + 1);
1101            if (!*directory)
1102            {
1103                return -1;
1104            }
1105            strncpy(*directory, path, i);
1106            (*directory)[i] = '\0';
1107            break;
1108        }
1109    }
1110    if (i == -1)
1111    {
1112        /* found no '/' path is all filename */
1113        *directory = NULL;
1114    }
1115    i++;
1116    /* copy the filename */
1117    fnlen = length - i - slashes;
1118    if (fnlen == 0)
1119    {
1120        filename = NULL;
1121        if (!directory)
1122        {
1123            errno = EISDIR;
1124        }
1125        else
1126        {
1127            errno = ENOENT;
1128        }
1129        return -1;
1130    }
1131    /* check flag to see if there are slashes to skip */
1132    *filename = malloc(fnlen + 1);
1133    if (!*filename)
1134    {
1135        if (*directory)
1136        {
1137            free(*directory);
1138        }
1139        *directory = NULL;
1140        *filename = NULL;
1141        return -1;
1142    }
1143    strncpy(*filename, path + i, length - i);
1144    (*filename)[length - i] = '\0';
1145    return 0;
1146}
1147
1148void PINT_initrand(void)
1149{
1150    static int init_called = 0;
1151    pid_t pid;
1152    uid_t uid;
1153    gid_t gid;
1154    struct timeval time;
1155    char *oldstate;
1156    unsigned int seed;
1157
1158    if (init_called)
1159    {
1160        return;
1161    }
1162    init_called = 1;
1163    pid = getpid();
1164    uid = getuid();
1165    gid = getgid();
1166    gettimeofday(&time, NULL);
1167    seed = (((pid << 16) ^ uid) ^ (gid << 8)) ^ time.tv_usec;
1168    oldstate = initstate(seed, rstate, 256);
1169    setstate(oldstate);
1170}
1171
1172long int PINT_random(void)
1173{
1174    char *oldstate;
1175    long int rndval;
1176
1177    PINT_initrand();
1178    oldstate = setstate(rstate);
1179    rndval = random();
1180    setstate(oldstate);
1181    return rndval;
1182}
1183
1184/*
1185 * Local variables:
1186 *  c-indent-level: 4
1187 *  c-basic-offset: 4
1188 * End:
1189 *
1190 * vim: ts=4 sts=4 sw=4 expandtab
1191 */
Note: See TracBrowser for help on using the browser.