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

Revision 9262, 32.5 KB (checked in by walt, 14 months ago)

updates to usrint/ucache code

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