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

Revision 9271, 32.5 KB (checked in by sdsnyde, 14 months ago)

removed references to the aio interface that were causing compile errors

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