Back to index

avfs  1.0.1
file.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 <dirent.h>
00013 
00014 
00015 #ifdef HAVE_LSEEK64
00016 static off64_t real_lseek64(int fd, off64_t offset, int whence, int undersc)
00017 {
00018     if(undersc == 0) {
00019         static off64_t (*prev)(int, off64_t, int);
00020         
00021         if(!prev)
00022             prev = (off64_t (*)(int, off64_t, int)) __av_get_real("lseek64");
00023         
00024         return prev(fd, offset, whence);
00025     }
00026     else {
00027         static off64_t (*prev)(int, off64_t, int);
00028         
00029         if(!prev)
00030             prev = (off64_t (*)(int, off64_t, int)) __av_get_real("_lseek64");
00031         
00032         return prev(fd, offset, whence);
00033     }
00034 }
00035 #endif
00036 
00037 static off_t real_lseek(int fd, off_t offset, int whence, int undersc)
00038 {
00039     if(undersc == 0) {
00040         static off_t (*prev)(int, off_t, int);
00041         
00042         if(!prev)
00043             prev = (off_t (*)(int, off_t, int)) __av_get_real("lseek");
00044         
00045         return prev(fd, offset, whence);
00046     }
00047     else {
00048         static off_t (*prev)(int, off_t, int);
00049         
00050         if(!prev)
00051             prev = (off_t (*)(int, off_t, int)) __av_get_real("_lseek");
00052         
00053         return prev(fd, offset, whence);
00054     }
00055 }
00056 
00057 
00058 static ssize_t real_read(int fd, void *buf, size_t nbyte, int undersc)
00059 {
00060     if(undersc == 0) {
00061         static ssize_t (*prev)(int, void *, size_t);
00062         
00063         if(!prev)
00064             prev = (ssize_t (*)(int, void *, size_t)) __av_get_real("read");
00065         
00066         return prev(fd, buf, nbyte);
00067     }
00068     else {
00069         static ssize_t (*prev)(int, void *, size_t);
00070         
00071         if(!prev)
00072             prev = (ssize_t (*)(int, void *, size_t)) __av_get_real("_read");
00073         
00074         return prev(fd, buf, nbyte);
00075 
00076     }
00077 }
00078 
00079 static ssize_t real_write(int fd, const void *buf, size_t nbyte, int undersc)
00080 {
00081     if(undersc == 0) {
00082         static ssize_t (*prev)(int, const void *, size_t);
00083         
00084         if(!prev)
00085             prev = (ssize_t (*)(int, const void *, size_t))
00086                 __av_get_real("write");
00087         
00088         return prev(fd, buf, nbyte);
00089     }
00090     else {
00091         static ssize_t (*prev)(int, const void *, size_t);
00092         
00093         if(!prev)
00094             prev = (ssize_t (*)(int, const void *, size_t))
00095                 __av_get_real("_write");
00096         
00097         return prev(fd, buf, nbyte);
00098 
00099     }
00100 }
00101 
00102 #ifdef HAVE_GETDENTS64
00103 static int real_getdents64(int fd, struct dirent64 *buf, size_t nbyte,
00104                            int undersc)
00105 {
00106     if(undersc == 0) {
00107         static int (*prev)(int, struct dirent64 *, size_t);
00108         
00109         if(!prev)
00110             prev = (int (*)(int, struct dirent64 *, size_t)) 
00111                 __av_get_real("getdents64");
00112         
00113         return prev(fd, buf, nbyte);
00114     }
00115     else {
00116         static int (*prev)(int, struct dirent64 *, size_t);
00117         
00118         if(!prev)
00119             prev = (int (*)(int, struct dirent64 *, size_t)) 
00120                 __av_get_real("_getdents64");
00121         
00122         return prev(fd, buf, nbyte);
00123     }
00124 }
00125 #endif
00126 
00127 static int real_getdents(int fd, struct dirent *buf, size_t nbyte,
00128                            int undersc)
00129 {
00130     if(undersc == 0) {
00131         static int (*prev)(int, struct dirent *, size_t);
00132         
00133         if(!prev)
00134             prev = (int (*)(int, struct dirent *, size_t)) 
00135                 __av_get_real("getdents");
00136         
00137         return prev(fd, buf, nbyte);
00138     }
00139     else {
00140         static int (*prev)(int, struct dirent *, size_t);
00141         
00142         if(!prev)
00143             prev = (int (*)(int, struct dirent *, size_t)) 
00144                 __av_get_real("_getdents");
00145         
00146         return prev(fd, buf, nbyte);
00147     }
00148 }
00149 
00150 static avoff_t cmd_lseek(int serverfh, avoff_t offset, int whence)
00151 {
00152     int res;
00153     struct avfs_out_message outmsg;
00154     struct avfs_in_message inmsg;
00155     struct avfs_cmd cmd;
00156     struct avfs_result result;
00157 
00158     cmd.type = CMD_LSEEK;
00159     cmd.u.lseek.serverfh = serverfh;
00160     cmd.u.lseek.offset = offset;
00161     cmd.u.lseek.whence = whence;
00162     
00163     outmsg.num = 1;
00164     outmsg.seg[0].len = sizeof(cmd);
00165     outmsg.seg[0].buf = &cmd;
00166 
00167     inmsg.seg[0].buf = &result;
00168 
00169     res = __av_send_message(&outmsg, &inmsg, 0);
00170     if(res == -1)
00171         return -EIO;
00172 
00173     return result.u.lseek.offset;
00174 }
00175 
00176 static ssize_t cmd_read(int serverfh, void *buf, size_t nbyte)
00177 {
00178     int res;
00179     struct avfs_out_message outmsg;
00180     struct avfs_in_message inmsg;
00181     struct avfs_cmd cmd;
00182     struct avfs_result result;
00183 
00184     cmd.type = CMD_READ;
00185     cmd.u.readwrite.serverfh = serverfh;
00186     cmd.u.readwrite.nbyte = nbyte;
00187     
00188     outmsg.num = 1;
00189     outmsg.seg[0].len = sizeof(cmd);
00190     outmsg.seg[0].buf = &cmd;
00191 
00192     inmsg.seg[0].buf = &result;
00193     inmsg.seg[1].buf = buf;
00194 
00195     res = __av_send_message(&outmsg, &inmsg, 0);
00196     if(res == -1)
00197         return -EIO;
00198 
00199     return result.result;
00200 }
00201 
00202 static ssize_t cmd_write(int serverfh, const void *buf, size_t nbyte)
00203 {
00204     int res;
00205     struct avfs_out_message outmsg;
00206     struct avfs_in_message inmsg;
00207     struct avfs_cmd cmd;
00208     struct avfs_result result;
00209 
00210     cmd.type = CMD_WRITE;
00211     cmd.u.readwrite.serverfh = serverfh;
00212     cmd.u.readwrite.nbyte = nbyte;
00213     
00214     outmsg.num = 2;
00215     outmsg.seg[0].len = sizeof(cmd);
00216     outmsg.seg[0].buf = &cmd;
00217     outmsg.seg[1].len = nbyte;
00218     outmsg.seg[1].buf = buf;
00219 
00220     inmsg.seg[0].buf = &result;
00221 
00222     res = __av_send_message(&outmsg, &inmsg, 0);
00223     if(res == -1)
00224         return -EIO;
00225 
00226     return result.result;
00227 }
00228 
00229 #ifdef HAVE_LSEEK64
00230 static off64_t virt_lseek64(int fd, off64_t offset, int whence, int undersc)
00231 {
00232     off64_t res;
00233 
00234     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00235         res = real_lseek64(fd, offset, whence, undersc);
00236     else {
00237         int errnosave = errno;
00238 
00239         res = cmd_lseek(SERVERFH(fd), offset, whence);
00240         if(res < 0)
00241             errno = -res, res = -1;
00242         else
00243             errno = errnosave;
00244     }
00245 
00246     return res;
00247 }
00248 #endif
00249 
00250 static off_t virt_lseek(int fd, off_t offset, int whence, int undersc)
00251 {
00252     off_t res;
00253 
00254     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00255         res = real_lseek(fd, offset, whence, undersc);
00256     else {
00257         int errnosave = errno;
00258 
00259         res = cmd_lseek(SERVERFH(fd), offset, whence);
00260         if(res < 0)
00261             errno = -res, res = -1;
00262         else
00263             errno = errnosave;
00264     }
00265 
00266     return res;
00267 }
00268 
00269 static ssize_t virt_read(int fd, void *buf, size_t nbyte, int undersc)
00270 {
00271     ssize_t res;
00272 
00273     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00274         res = real_read(fd, buf, nbyte, undersc);
00275     else {
00276         int errnosave = errno;
00277 
00278         res = cmd_read(SERVERFH(fd), buf, nbyte);
00279         if(res < 0)
00280             errno = -res, res = -1;
00281         else
00282             errno = errnosave;
00283     }
00284 
00285     return res;
00286 }
00287 
00288 static ssize_t virt_write(int fd, const void *buf, size_t nbyte, int undersc)
00289 {
00290     ssize_t res;
00291 
00292     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00293         res = real_write(fd, buf, nbyte, undersc);
00294     else {
00295         int errnosave = errno;
00296 
00297         res = cmd_write(SERVERFH(fd), buf, nbyte);
00298         if(res < 0)
00299             errno = -res, res = -1;
00300         else
00301             errno = errnosave;
00302     }
00303 
00304     return res;
00305 }
00306 
00307 
00308 static int cmd_readdir(int serverfh, struct avfs_direntry *de, char *name)
00309 {
00310     int res;
00311     struct avfs_out_message outmsg;
00312     struct avfs_in_message inmsg;
00313     struct avfs_cmd cmd;
00314     struct avfs_result result;
00315 
00316     cmd.type = CMD_READDIR;
00317     cmd.u.fdops.serverfh = serverfh;
00318     
00319     outmsg.num = 1;
00320     outmsg.seg[0].len = sizeof(cmd);
00321     outmsg.seg[0].buf = &cmd;
00322 
00323     inmsg.seg[0].buf = &result;
00324     inmsg.seg[1].buf = de;
00325     inmsg.seg[2].buf = name;
00326 
00327     res = __av_send_message(&outmsg, &inmsg, 0);
00328     if(res == -1)
00329         return -EIO;
00330 
00331     return result.result;
00332 }
00333 
00334 #ifdef HAVE_GETDENTS64
00335 #define AVFS_DIR_RECLEN64 ((size_t)(((struct dirent64 *)0)->d_name)+NAME_MAX+1)
00336 
00337 static void avfs_direntry_to_dirent64(struct dirent64 *ent,
00338                                  struct avfs_direntry *avent)
00339 {
00340     ent->d_ino = avent->ino;
00341     ent->d_off = avent->n * AVFS_DIR_RECLEN64; 
00342     ent->d_reclen = AVFS_DIR_RECLEN64;
00343 }
00344 
00345 static int virt_getdents64(int fd, struct dirent64 *buf, size_t nbyte,
00346                            int undersc)
00347 {
00348     int res;
00349 
00350     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00351         res =  real_getdents64(fd, buf, nbyte, undersc);
00352     else {
00353         struct avfs_direntry de;
00354         int errnosave;
00355 
00356         if(nbyte < AVFS_DIR_RECLEN64) {
00357             errno = EINVAL;
00358             return -1;
00359         }
00360 
00361         errnosave = errno;
00362         res = cmd_readdir(SERVERFH(fd), &de, buf->d_name);
00363         errno = errnosave;
00364         if(res < 0) 
00365             errno = -res, res = -1;
00366         else if(res > 0) {
00367             avfs_direntry_to_dirent64(buf, &de);
00368             res = AVFS_DIR_RECLEN64;
00369         }
00370     }
00371 
00372     return res;
00373 }
00374 #endif
00375 
00376 #define AVFS_DIR_RECLEN ((size_t)(((struct dirent *)0)->d_name)+NAME_MAX+1)
00377 
00378 static void avfs_direntry_to_dirent(struct dirent *ent,
00379                                  struct avfs_direntry *avent)
00380 {
00381     ent->d_ino = avent->ino;
00382     ent->d_off = avent->n * AVFS_DIR_RECLEN; 
00383     ent->d_reclen = AVFS_DIR_RECLEN;
00384 }
00385 
00386 static int virt_getdents(int fd, struct dirent *buf, size_t nbyte,
00387                            int undersc)
00388 {
00389     int res;
00390 
00391     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00392         res =  real_getdents(fd, buf, nbyte, undersc);
00393     else {
00394         struct avfs_direntry de;
00395         int errnosave;
00396 
00397         if(nbyte < AVFS_DIR_RECLEN) {
00398             errno = EINVAL;
00399             return -1;
00400         }
00401 
00402         errnosave = errno;
00403         res = cmd_readdir(SERVERFH(fd), &de, buf->d_name);
00404         errno = errnosave;
00405         if(res < 0) 
00406             errno = -res, res = -1;
00407         else if(res > 0) {
00408             avfs_direntry_to_dirent(buf, &de);
00409             res = AVFS_DIR_RECLEN;
00410         }
00411     }
00412 
00413     return res;
00414 }
00415 
00416 
00417 #ifdef HAVE_LSEEK64
00418 off64_t lseek64(int fd, off64_t offset, int whence)
00419 {
00420     return virt_lseek64(fd, offset, whence, 0);
00421 }
00422 
00423 off64_t _lseek64(int fd, off64_t offset, int whence)
00424 {
00425     return virt_lseek64(fd, offset, whence, 1);
00426 }
00427 #endif
00428 
00429 off_t lseek(int fd, off_t offset, int whence)
00430 {
00431     return virt_lseek(fd, offset, whence, 0);
00432 }
00433 
00434 off_t _lseek(int fd, off_t offset, int whence)
00435 {
00436     return virt_lseek(fd, offset, whence, 1);
00437 }
00438 
00439 
00440 ssize_t read(int fd, void *buf, size_t nbyte)
00441 {
00442     return virt_read(fd, buf, nbyte, 0);
00443 }
00444 
00445 ssize_t _read(int fd, void *buf, size_t nbyte)
00446 {
00447     return virt_read(fd, buf, nbyte, 1);
00448 }
00449 
00450 ssize_t write(int fd, const void *buf, size_t nbyte)
00451 {
00452     return virt_write(fd, buf, nbyte, 0);
00453 }
00454 
00455 ssize_t _write(int fd, const void *buf, size_t nbyte)
00456 {
00457     return virt_write(fd, buf, nbyte, 1);
00458 }
00459 
00460 #ifdef HAVE_GETDENTS64
00461 int getdents64(int fd, struct dirent64 *buf, size_t nbyte)
00462 {
00463     return virt_getdents64(fd, buf, nbyte, 0);
00464 }
00465 
00466 int _getdents64(int fd, struct dirent64 *buf, size_t nbyte)
00467 {
00468     return virt_getdents64(fd, buf, nbyte, 1);
00469 }
00470 #endif
00471 
00472 int getdents(int fd, struct dirent *buf, size_t nbyte)
00473 {
00474     return virt_getdents(fd, buf, nbyte, 0);
00475 }
00476 
00477 int _getdents(int fd, struct dirent *buf, size_t nbyte)
00478 {
00479     return virt_getdents(fd, buf, nbyte, 1);
00480 }