Back to index

avfs  1.0.1
open.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 1998-2001  Miklos Szeredi <miklos@szeredi.hu>
00004 
00005     This program can be distributed under the terms of the GNU LGPL.
00006     See the file COPYING.LIB.
00007 */
00008 
00009 #include "utils.h"
00010 #include "config.h"
00011 
00012 #include <unistd.h>
00013 #include <stdlib.h>
00014 #include <stdarg.h>
00015 #include <fcntl.h>
00016 
00017 #define CREATFLAGS (O_WRONLY | O_CREAT | O_TRUNC)
00018 
00019 #ifdef HAVE_OPEN64
00020 static int real_open64(const char *path, int flags, mode_t mode, int undersc)
00021 {
00022     int res;
00023 
00024     if(undersc == 0) {
00025         static int (*prev)(const char *, int, mode_t);
00026         if(!prev)
00027             prev = (int (*)(const char *, int, mode_t))
00028                 __av_get_real("open64");
00029         
00030         res = prev(path, flags, mode);
00031     }
00032     else {
00033         static int (*prev)(const char *, int, mode_t);
00034         if(!prev)
00035             prev = (int (*)(const char *, int, mode_t))
00036                 __av_get_real("_open64");
00037 
00038         res = prev(path, flags, mode);
00039 
00040     }
00041 
00042     return res;
00043 }
00044 #endif
00045 
00046 static int real_open32(const char *path, int flags, mode_t mode, int undersc)
00047 {
00048     int res;
00049 
00050     if(undersc == 0) {
00051         static int (*prev)(const char *, int, mode_t);
00052         if(!prev)
00053             prev = (int (*)(const char *, int, mode_t))
00054                 __av_get_real("open");
00055         
00056         res = prev(path, flags, mode);
00057     }
00058     else {
00059         static int (*prev)(const char *, int, mode_t);
00060         if(!prev)
00061             prev = (int (*)(const char *, int, mode_t))
00062                 __av_get_real("_open");
00063 
00064         res = prev(path, flags, mode);
00065 
00066     }
00067 
00068     return res;
00069 }
00070 
00071 #ifdef HAVE_CREAT64
00072 static int real_creat64(const char *path, mode_t mode, int undersc)
00073 {
00074     int res;
00075 
00076     if(undersc == 0) {
00077         static int (*prev)(const char *, mode_t);
00078         if(!prev)
00079             prev = (int (*)(const char *, mode_t))
00080                 __av_get_real("creat64");
00081         
00082         res = prev(path, mode);
00083     }
00084     else {
00085         static int (*prev)(const char *, mode_t);
00086         if(!prev)
00087             prev = (int (*)(const char *, mode_t))
00088                 __av_get_real("_creat64");
00089         
00090         res = prev(path, mode);
00091     }
00092 
00093     return res;
00094 }
00095 #endif
00096 
00097 static int real_creat32(const char *path, mode_t mode, int undersc)
00098 {
00099     int res;
00100 
00101     if(undersc == 0) {
00102         static int (*prev)(const char *, mode_t);
00103         if(!prev)
00104             prev = (int (*)(const char *, mode_t))
00105                 __av_get_real("creat");
00106         
00107         res = prev(path, mode);
00108     }
00109     else {
00110         static int (*prev)(const char *, mode_t);
00111         if(!prev)
00112             prev = (int (*)(const char *, mode_t))
00113                 __av_get_real("_creat");
00114         
00115         res = prev(path, mode);
00116     }
00117 
00118     return res;
00119 }
00120 
00121 static int real_open(const char *path, int flags, mode_t mode, int undersc,
00122                        int is64, int creat)
00123 {
00124     int res;
00125     
00126     is64 = is64; /* Possibly unused arg */
00127 
00128     if(creat) {
00129 #ifdef HAVE_CREAT64            
00130         if(is64)
00131             res = real_creat64(path, mode, undersc);
00132         else
00133 #endif
00134             res = real_creat32(path, mode, undersc);
00135     }
00136     else {
00137 #ifdef HAVE_OPEN64
00138         if(is64)
00139             res = real_open64(path, flags, mode, undersc);
00140         else
00141 #endif
00142             res = real_open32(path, flags, mode, undersc);
00143     }
00144     
00145     return res;
00146 }
00147 
00148 
00149 static int real_close(int fd, int undersc)
00150 {
00151     if(undersc == 0) {
00152         static int (*prev)(int);
00153         
00154         if(!prev)
00155             prev = (int (*)(int)) __av_get_real("close");
00156         
00157         return prev(fd);
00158     }
00159     else {
00160         static int (*prev)(int);
00161         
00162         if(!prev)
00163             prev = (int (*)(int)) __av_get_real("_close");
00164         
00165         return prev(fd);
00166     }
00167 }
00168 
00169 static int real_unlink(const char *path)
00170 {
00171     return unlink(path);
00172 }
00173 
00174 static int get_handle()
00175 {
00176     int fh = -1;
00177     char dummyfile[64];
00178     int numtries;
00179     
00180     for(numtries = 0; numtries < 10; numtries++) {
00181         strcpy(dummyfile, "/tmp/.avfs_dummyfile_XXXXXX");
00182         mktemp(dummyfile);
00183         if(dummyfile[0] != '\0') {
00184             fh = real_open(dummyfile, O_RDONLY | O_CREAT | O_EXCL, 0600, 1,
00185                            1, 0);
00186             real_unlink(dummyfile);
00187         }
00188         if(fh != -1)
00189             break;
00190     }
00191 
00192     if(fh == -1)
00193         return -EIO;
00194   
00195     if(!FD_OK(fh)) {
00196         real_close(fh, 1);
00197         return -EIO;
00198     }
00199 
00200     if(ISVIRTUAL(fh)) {
00201         real_close(fh, 1);
00202         __av_dtable[fh].isvirtual = 0;
00203         return -EFAULT;
00204     }
00205 
00206     fcntl(fh, F_SETFD, FD_CLOEXEC); 
00207 
00208     __av_dtable[fh].isvirtual = 1;
00209 
00210     return fh;
00211 }
00212 
00213 static void free_handle(int fh)
00214 {
00215     if(FD_OK(fh)) 
00216         __av_dtable[fh].isvirtual = 0;
00217 
00218     real_close(fh, 1);
00219 }
00220 
00221 static int oflags_to_avfs(int flags)
00222 {
00223     int avflags;
00224   
00225     avflags = flags & O_ACCMODE;
00226     if(avflags == AVO_NOPERM)
00227        avflags = AVO_RDWR;
00228 
00229     if(flags & O_CREAT)    avflags |= AVO_CREAT;
00230     if(flags & O_EXCL)     avflags |= AVO_EXCL;
00231     if(flags & O_TRUNC)    avflags |= AVO_TRUNC;
00232     if(flags & O_APPEND)   avflags |= AVO_APPEND;
00233     if(flags & O_NONBLOCK) avflags |= AVO_NONBLOCK;
00234     if(flags & O_SYNC)     avflags |= AVO_SYNC;
00235 
00236     return avflags;
00237 }
00238 
00239 
00240 static int cmd_open(const char *path, int flags, mode_t mode, char *pathbuf,
00241                     int *holderfd)
00242 {
00243     int res;
00244     struct avfs_out_message outmsg;
00245     struct avfs_in_message inmsg;
00246     struct avfs_cmd cmd;
00247     struct avfs_result result;
00248     const char *abspath;
00249 
00250     res = __av_get_abs_path(path, pathbuf, &abspath);
00251     if(res < 0)
00252         return res;
00253 
00254     cmd.type = CMD_OPEN;
00255     cmd.u.open.flags = oflags_to_avfs(flags);
00256     cmd.u.open.mode = mode;
00257     
00258     outmsg.num = 2;
00259     outmsg.seg[0].len = sizeof(cmd);
00260     outmsg.seg[0].buf = &cmd;
00261     outmsg.seg[1].len = strlen(abspath) + 1;
00262     outmsg.seg[1].buf = abspath;
00263 
00264     inmsg.seg[0].buf = &result;
00265     inmsg.seg[1].buf = pathbuf;
00266 
00267     res = __av_send_message(&outmsg, &inmsg, 1);
00268     if(res == -1)
00269         return -EIO;
00270 
00271     *holderfd = res;
00272 
00273     if(inmsg.seg[1].len == 0)
00274         pathbuf[0] = '\0';
00275 
00276     return result.result;
00277 }
00278 
00279 static int cmd_close(int serverfh)
00280 {
00281     int res;
00282     struct avfs_out_message outmsg;
00283     struct avfs_in_message inmsg;
00284     struct avfs_cmd cmd;
00285     struct avfs_result result;
00286 
00287     cmd.type = CMD_CLOSE;
00288     cmd.u.fdops.serverfh = serverfh;
00289     
00290     outmsg.num = 1;
00291     outmsg.seg[0].len = sizeof(cmd);
00292     outmsg.seg[0].buf = &cmd;
00293 
00294     inmsg.seg[0].buf = &result;
00295 
00296     res = __av_send_message(&outmsg, &inmsg, 0);
00297     if(res == -1)
00298         return -EIO;
00299 
00300     return result.result;
00301 }
00302 
00303 
00304 static int do_open(const char *path, int flags, mode_t mode, char *pathbuf)
00305 {
00306     int serverfh;
00307     int holderfd;
00308     int fh;
00309 
00310     serverfh = cmd_open(path, flags, mode, pathbuf, &holderfd);
00311     if(serverfh < 0) {
00312         real_close(holderfd, 1);
00313         return serverfh;
00314     }
00315 
00316     fh = get_handle();
00317     if(fh < 0) {
00318         cmd_close(serverfh);
00319         real_close(holderfd, 1);
00320         return fh;
00321     }
00322     
00323     fcntl(holderfd, F_SETFD, FD_CLOEXEC);
00324 
00325     __av_dtable[fh].serverfh = serverfh;
00326     __av_dtable[fh].holderfd = holderfd;
00327 
00328     return fh;
00329 }
00330 
00331 static int virt_open(const char *path, int flags, mode_t mode, int undersc,
00332                      int is64, int creat)
00333 {
00334     int res = 0;
00335     int local = 0;
00336 
00337     if(__av_maybe_local(path)) {
00338         res = real_open(path, flags, mode, undersc, is64, creat);
00339         local = __av_is_local(res, path);
00340     }
00341     
00342     if(!local) {
00343         int errnosave;
00344         char pathbuf[PATHBUF_LEN];
00345 
00346         errnosave = errno;
00347         res = do_open(path, flags, mode, pathbuf);
00348         errno = errnosave;
00349         if(pathbuf[0])
00350             res = real_open(pathbuf, flags, mode, undersc, is64, creat);
00351         else if(res < 0)
00352             errno = -res, res = -1;
00353     }
00354 
00355     return res;
00356 }
00357 
00358 static int virt_close(int fd, int undersc)
00359 {
00360     int res;
00361 
00362     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00363         res =  real_close(fd, undersc);
00364     else {
00365         int errnosave = errno;
00366         res = cmd_close(SERVERFH(fd));
00367         real_close(__av_dtable[fd].holderfd, 1);
00368         free_handle(fd);
00369         if(res < 0) 
00370             errno = -res, res = -1;
00371         else
00372             errno = errnosave;
00373     }
00374 
00375     return res;
00376 }
00377 
00378 #ifdef HAVE_OPEN64
00379 int open64(const char *path, int flags, ...)
00380 {
00381     va_list ap;
00382     mode_t mode;
00383     
00384     va_start(ap, flags);
00385     mode = va_arg(ap, mode_t);
00386     va_end(ap);
00387 
00388     return virt_open(path, flags, mode, 0, 1, 0);
00389 }
00390 
00391 int _open64(const char *path, int flags, mode_t mode)
00392 {
00393     return virt_open(path, flags, mode, 1, 1, 0);
00394 }
00395 #endif
00396 
00397 int open(const char *path, int flags, ...)
00398 {
00399     va_list ap;
00400     mode_t mode;
00401     
00402     va_start(ap, flags);
00403     mode = va_arg(ap, mode_t);
00404     va_end(ap);
00405 
00406     return virt_open(path, flags, mode, 0, 0, 0);
00407 }
00408 
00409 int _open(const char *path, int flags, mode_t mode)
00410 {
00411     return virt_open(path, flags, mode, 1, 0, 0);
00412 }
00413 
00414 #ifdef HAVE_CREAT64
00415 int creat64(const char *path, mode_t mode)
00416 {
00417     return virt_open(path, CREATFLAGS, mode, 0, 1, 1);
00418 }
00419 
00420 int _creat64(const char *path, mode_t mode)
00421 {
00422     return virt_open(path, CREATFLAGS, mode, 1, 1, 1);
00423 }
00424 #endif
00425 
00426 int creat(const char *path, mode_t mode)
00427 {
00428     return virt_open(path, CREATFLAGS, mode, 0, 0, 1);
00429 }
00430 
00431 int _creat(const char *path, mode_t mode)
00432 {
00433     return virt_open(path, CREATFLAGS, mode, 1, 0, 1);
00434 }
00435 
00436 int close(int fd)
00437 {
00438     return virt_close(fd, 0);
00439 }
00440 
00441 int _close(int fd)
00442 {
00443     return virt_close(fd, 1);
00444 }
00445