Back to index

avfs  1.0.1
virtual.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 2000  Miklos Szeredi <miklos@szeredi.hu>
00004 
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 */
00008 
00009 #include "virtual.h"
00010 #include "operutil.h"
00011 #include "oper.h"
00012 #include "internal.h"
00013 
00014 #include <dirent.h>
00015 #include <fcntl.h>
00016 #include <utime.h>
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 
00020 static int oflags_to_avfs(int flags)
00021 {
00022     int avflags;
00023   
00024     avflags = flags & O_ACCMODE;
00025     if(avflags == AVO_NOPERM)
00026        avflags = AVO_RDWR;
00027 
00028     if(flags & O_CREAT)    avflags |= AVO_CREAT;
00029     if(flags & O_EXCL)     avflags |= AVO_EXCL;
00030     if(flags & O_TRUNC)    avflags |= AVO_TRUNC;
00031     if(flags & O_APPEND)   avflags |= AVO_APPEND;
00032     if(flags & O_NONBLOCK) avflags |= AVO_NONBLOCK;
00033 #ifdef O_SYNC
00034     if(flags & O_SYNC)     avflags |= AVO_SYNC;
00035 #endif
00036 
00037     return avflags;
00038 }
00039 
00040 int virt_open(const char *path, int flags, mode_t mode)
00041 {
00042     int res;
00043     int errno_save = errno;
00044 
00045     res = av_fd_open(path, oflags_to_avfs(flags), mode & 07777);
00046     if(res < 0) {
00047         errno = -res;
00048         return -1;
00049     }
00050 
00051     errno = errno_save;
00052     return res;
00053 }
00054 
00055 int virt_close(int fd)
00056 {
00057     int res;
00058     int errno_save = errno;
00059 
00060     res = av_fd_close(fd);
00061     if(res < 0) {
00062         errno = -res;
00063         return -1;
00064     }
00065     
00066     errno = errno_save;
00067     return 0;
00068 }
00069 
00070 
00071 ssize_t virt_write(int fd, const void *buf, size_t nbyte)
00072 {
00073     ssize_t res;
00074     int errno_save = errno;
00075 
00076     res = av_fd_write(fd, buf, nbyte);
00077     if(res < 0) {
00078         errno = -res;
00079         return -1;
00080     }
00081 
00082     errno = errno_save;
00083     return res;
00084 }
00085 
00086 ssize_t virt_read(int fd, void *buf, size_t nbyte)
00087 {
00088     ssize_t res;
00089     int errno_save = errno;
00090 
00091     res = av_fd_read(fd, buf, nbyte);
00092     if(res < 0) {
00093         errno = -res;
00094         return -1;
00095     }
00096 
00097     errno = errno_save;
00098     return res;
00099 }
00100 
00101 off_t virt_lseek(int fd, off_t offset, int whence)
00102 {
00103     off_t res;
00104     int errno_save = errno;
00105 
00106     res = av_fd_lseek(fd, offset, whence);
00107     if(res < 0) {
00108         errno = -res;
00109         return -1;
00110     }
00111 
00112     errno = errno_save;
00113     return res;
00114 }
00115 
00116 static void avstat_to_stat(struct stat *buf, struct avstat *avbuf)
00117 {
00118     buf->st_dev     = avbuf->dev;
00119     buf->st_ino     = avbuf->ino;
00120     buf->st_mode    = avbuf->mode;
00121     buf->st_nlink   = avbuf->nlink;
00122     buf->st_uid     = avbuf->uid;
00123     buf->st_gid     = avbuf->gid;
00124     buf->st_rdev    = avbuf->rdev;
00125     buf->st_size    = avbuf->size;
00126     buf->st_blksize = avbuf->blksize;
00127     buf->st_blocks  = avbuf->blocks;
00128     buf->st_atime   = avbuf->atime.sec;
00129     buf->st_mtime   = avbuf->mtime.sec;
00130     buf->st_ctime   = avbuf->ctime.sec;
00131 }
00132 
00133 int virt_fstat(int fd, struct stat *buf)
00134 {
00135     int res;
00136     struct avstat avbuf;
00137     int errno_save = errno;
00138 
00139     res = av_fd_getattr(fd, &avbuf, AVA_ALL);
00140     if(res < 0) {
00141         errno = -res;
00142         return -1;
00143     }
00144     avstat_to_stat(buf, &avbuf);
00145 
00146     errno = errno_save;
00147     return 0;
00148 }
00149 
00150 static int open_path(vfile *vf, const char *path, int flags, avmode_t mode)
00151 {
00152     int res;
00153     ventry *ve;
00154 
00155     res = av_get_ventry(path, !(flags & AVO_NOFOLLOW), &ve);
00156     if(res < 0)
00157         return res;
00158 
00159     res = av_file_open(vf, ve, flags, mode);
00160     av_free_ventry(ve);
00161 
00162     return res;
00163 }
00164 
00165 
00166 static int common_stat(const char *path, struct stat *buf, int flags)
00167 {
00168     int res;
00169     vfile vf;
00170     struct avstat avbuf;
00171     int errno_save = errno;
00172 
00173     res = open_path(&vf, path, AVO_NOPERM | flags, 0);
00174     if(res == 0) {
00175         res = av_file_getattr(&vf, &avbuf, AVA_ALL);
00176         av_file_close(&vf);
00177        if(res == 0)
00178            avstat_to_stat(buf, &avbuf);
00179     }
00180     if(res < 0) {
00181         errno = -res;
00182         return -1;
00183     }
00184     
00185     errno = errno_save;
00186     return 0;
00187 }
00188 
00189 int virt_stat(const char *path, struct stat *buf)
00190 {
00191     return common_stat(path, buf, 0); 
00192 }
00193 
00194 int virt_lstat(const char *path, struct stat *buf)
00195 {
00196     return common_stat(path, buf, AVO_NOFOLLOW); 
00197 }
00198 
00199 
00200 #ifndef NAME_MAX
00201 #define NAME_MAX 255
00202 #endif
00203 
00204 typedef struct {
00205     int fd;
00206     struct dirent entry;
00207     char _trail[NAME_MAX + 1];
00208 } AVDIR;
00209 
00210 DIR *virt_opendir(const char *path)
00211 {
00212     AVDIR *dp;
00213     int res;
00214     int errno_save = errno;
00215 
00216     res = av_fd_open(path, AVO_DIRECTORY, 0);
00217     if(res < 0) {
00218         errno = -res;
00219         return NULL;
00220     }
00221 
00222     AV_NEW(dp);
00223     dp->fd = res;
00224 
00225     errno = errno_save;
00226     return (DIR *) dp;
00227 }
00228 
00229 int virt_closedir(DIR *dirp)
00230 {
00231     int res;
00232     AVDIR *dp = (AVDIR *) dirp;
00233     int errno_save = errno;
00234     int fd;
00235 
00236     if(dp == NULL) {
00237        errno = EINVAL;
00238        return -1;
00239     }
00240     
00241     fd = dp->fd;
00242     av_free(dp);
00243     res = av_fd_close(fd);
00244     if(res < 0) {
00245         errno = -res;
00246         return -1;
00247     }
00248 
00249     errno = errno_save;
00250     return 0;
00251 }
00252 
00253 void virt_rewinddir(DIR *dirp)
00254 {
00255     int res;
00256     AVDIR *dp = (AVDIR *) dirp;
00257     int errno_save = errno;
00258 
00259     if(dp == NULL) {
00260        errno = EINVAL;
00261        return;
00262     }
00263 
00264     res = av_fd_lseek(dp->fd, 0, AVSEEK_SET);
00265     if(res < 0)
00266         errno = -res;
00267 
00268     errno = errno_save;
00269 }
00270 
00271 #define AVFS_DIR_RECLEN 256 /* just an arbitary number */
00272 
00273 static void avdirent_to_dirent(struct dirent *ent, struct avdirent *avent,
00274                             avoff_t n)
00275 {
00276     ent->d_ino = avent->ino;
00277 #ifdef HAVE_D_OFF
00278     ent->d_off = n * AVFS_DIR_RECLEN; 
00279 #endif
00280     ent->d_reclen = AVFS_DIR_RECLEN;
00281 #ifdef HAVE_D_TYPE
00282     ent->d_type = avent->type;
00283 #endif
00284     strncpy(ent->d_name, avent->name, NAME_MAX);
00285     ent->d_name[NAME_MAX] = '\0';
00286 }
00287 
00288 struct dirent *virt_readdir(DIR *dirp)
00289 {
00290     int res;
00291     struct avdirent buf;
00292     avoff_t n;
00293     AVDIR *dp = (AVDIR *) dirp;
00294     int errno_save = errno;
00295 
00296     if(dp == NULL) {
00297        errno = EINVAL;
00298        return NULL;
00299     }
00300     res = av_fd_readdir(dp->fd, &buf, &n);
00301     if(res <= 0) {
00302         if(res < 0)
00303             errno = -res;
00304         else
00305             errno = errno_save;
00306         return NULL;
00307     }
00308 
00309     avdirent_to_dirent(&dp->entry, &buf, n);
00310     av_free(buf.name);
00311 
00312     errno = errno_save;
00313     return &dp->entry;
00314 }
00315 
00316 
00317 int virt_truncate(const char *path, off_t length)
00318 {
00319     int res;
00320     vfile vf;
00321     int errno_save = errno;
00322 
00323     res = open_path(&vf, path, AVO_WRONLY, 0);
00324     if(res == 0) {
00325         av_file_truncate(&vf, length);
00326         av_file_close(&vf);
00327     }
00328     if(res < 0) {
00329         errno = -res;
00330         return -1;
00331     }
00332 
00333     errno = errno_save;
00334     return 0;
00335 }
00336 
00337 static int common_setattr(const char *path, struct avstat *buf, int attrmask,
00338                        int flags)
00339 {
00340     int res;
00341     int errno_save = errno;
00342     vfile vf;
00343 
00344     res = open_path(&vf, path, AVO_NOPERM | flags, 0);
00345     if(res == 0) {
00346         res = av_file_setattr(&vf, buf, attrmask);
00347        av_file_close(&vf);
00348     }
00349     if(res < 0) {
00350         errno = -res;
00351         return -1;
00352     }
00353 
00354     errno = errno_save;
00355     return 0;
00356 }
00357 
00358 int virt_utime(const char *path, struct utimbuf *buf)
00359 {
00360     struct avstat stbuf;
00361 
00362     if(buf == NULL) {
00363         int errno_save = errno;
00364        av_curr_time(&stbuf.mtime);
00365         errno = errno_save;
00366        stbuf.atime = stbuf.mtime;
00367     }
00368     else {
00369        stbuf.mtime.sec = buf->modtime;
00370        stbuf.mtime.nsec = 0;
00371        stbuf.atime.sec = buf->actime;
00372        stbuf.atime.nsec = 0;
00373     }
00374     
00375     return common_setattr(path, &stbuf, AVA_MTIME | AVA_ATIME, 0);
00376 }
00377 
00378 int virt_chmod(const char *path, mode_t mode)
00379 {
00380     struct avstat stbuf;
00381 
00382     stbuf.mode = mode & 07777;
00383 
00384     return common_setattr(path, &stbuf, AVA_MODE, 0);
00385 }
00386 
00387 static int common_chown(const char *path, uid_t owner, gid_t grp, int flags)
00388 {
00389     struct avstat stbuf;
00390     int attrmask = 0;
00391     
00392     stbuf.uid = owner;
00393     stbuf.gid = grp;
00394 
00395     if(owner != (uid_t) -1)
00396        attrmask |= AVA_UID;
00397     if(grp != (gid_t) -1)
00398        attrmask |= AVA_GID;
00399 
00400     return common_setattr(path, &stbuf, attrmask, flags);
00401 }
00402 
00403 int virt_chown(const char *path, uid_t owner, gid_t grp)
00404 {
00405     return common_chown(path, owner, grp, 0);
00406 }
00407 
00408 int virt_lchown(const char *path, uid_t owner, gid_t grp)
00409 {
00410     return common_chown(path, owner, grp, AVO_NOFOLLOW);
00411 }
00412 
00413 int virt_ftruncate(int fd, off_t length)
00414 {
00415     int res;
00416     int errno_save = errno;
00417     
00418     res = av_fd_truncate(fd, length);
00419     if(res < 0) {
00420         errno = -res;
00421         return -1;
00422     }
00423 
00424     errno = errno_save;
00425     return 0;
00426 }
00427 
00428 static int common_fsetattr(int fd, struct avstat *stbuf, int attrmask)
00429 {
00430     int res;
00431     int errno_save = errno;
00432     
00433     res = av_fd_setattr(fd, stbuf, attrmask);
00434     if(res < 0) {
00435         errno = -res;
00436         return -1;
00437     }
00438 
00439     errno = errno_save;
00440     return 0;
00441 }
00442 
00443 int virt_fchmod(int fd, mode_t mode)
00444 {
00445     struct avstat stbuf;
00446     
00447     stbuf.mode = mode & 07777;
00448 
00449     return common_fsetattr(fd, &stbuf, AVA_MODE);
00450 }
00451 
00452 int virt_fchown(int fd, uid_t owner, gid_t grp)
00453 {
00454     struct avstat stbuf;
00455     int attrmask = 0;
00456         
00457     stbuf.uid = owner;
00458     stbuf.gid = grp;
00459 
00460     if(owner != (uid_t) -1)
00461        attrmask |= AVA_UID;
00462     if(grp != (gid_t) -1)
00463        attrmask |= AVA_GID;
00464 
00465     return common_fsetattr(fd, &stbuf, attrmask);
00466 }
00467 
00468 int virt_access(const char *path, int amode)
00469 {
00470     int res;
00471     ventry *ve;
00472     int errno_save = errno;
00473 
00474     res = av_get_ventry(path, 1, &ve);
00475     if(res == 0) {
00476        res = av_access(ve, amode);
00477        av_free_ventry(ve);
00478     }
00479     if(res < 0) {
00480         errno = -res;
00481         return -1;
00482     }
00483 
00484     errno = errno_save;
00485     return 0;
00486 }
00487 
00488 static int copy_readlink(char *buf, size_t bsiz, const char *avbuf)
00489 {
00490     size_t nact;
00491 
00492     nact = strlen(avbuf);
00493     nact = AV_MIN(nact, bsiz);
00494 
00495     strncpy(buf, avbuf, nact);
00496 
00497     return (int) nact;
00498 }
00499 
00500 int virt_readlink(const char *path, char *buf, size_t bsiz)
00501 {
00502     int res;
00503     ventry *ve;
00504     char *avbuf;
00505     int errno_save = errno;
00506    
00507     res = av_get_ventry(path, 0, &ve);
00508     if(res == 0) {
00509         res = av_readlink(ve, &avbuf);
00510        if(res == 0) {
00511            res = copy_readlink(buf, bsiz, avbuf);
00512            av_free(avbuf);
00513        }
00514        av_free_ventry(ve);
00515     }
00516     if(res < 0) {
00517         errno = -res;
00518         return -1;
00519     }
00520 
00521     errno = errno_save;
00522     return res;
00523 }
00524 
00525 int virt_unlink(const char *path)
00526 {
00527     int res;
00528     ventry *ve;
00529     int errno_save = errno;
00530 
00531     res = av_get_ventry(path, 0, &ve);
00532     if(res == 0) {
00533         res = av_unlink(ve);
00534        av_free_ventry(ve);
00535     }
00536     if(res < 0) {
00537         errno = -res;
00538         return -1;
00539     }
00540     
00541     errno = errno_save;
00542     return 0;
00543 }
00544 
00545 int virt_rmdir(const char *path)
00546 {
00547     int res;
00548     ventry *ve;
00549     int errno_save = errno;
00550 
00551     res = av_get_ventry(path, 0, &ve);
00552     if(res == 0) {
00553         res = av_rmdir(ve);
00554        av_free_ventry(ve);
00555     }
00556     if(res < 0) {
00557         errno = -res;
00558         return -1;
00559     }
00560     
00561     errno = errno_save;
00562     return 0;
00563 }
00564 
00565 int virt_mkdir(const char *path, mode_t mode)
00566 {
00567     int res;
00568     ventry *ve;
00569     int errno_save = errno;
00570 
00571     res = av_get_ventry(path, 0, &ve);
00572     if(res == 0) {
00573         res = av_mkdir(ve, mode);
00574         av_free_ventry(ve);
00575     }
00576     if(res < 0) {
00577         errno = -res;
00578         return -1;
00579     }
00580     
00581     errno = errno_save;
00582     return 0;
00583 }
00584 
00585 int virt_mknod(const char *path, mode_t mode, dev_t dev)
00586 {
00587     int res;
00588     ventry *ve;
00589     int errno_save = errno;
00590 
00591     res = av_get_ventry(path, 0, &ve);
00592     if(res == 0) {
00593         res = av_mknod(ve, mode, dev);
00594        av_free_ventry(ve);
00595     }
00596     if(res < 0) {
00597         errno = -res;
00598         return -1;
00599     }
00600     
00601     errno = errno_save;
00602     return 0;
00603 }
00604 
00605 int virt_symlink(const char *path, const char *newpath)
00606 {
00607     int res;
00608     ventry *newve;
00609     int errno_save = errno;
00610 
00611     res = av_get_ventry(newpath, 0, &newve);
00612     if(res == 0) {
00613         res = av_symlink(path, newve);
00614        av_free_ventry(newve);
00615     }
00616     if(res < 0) {
00617         errno = -res;
00618         return -1;
00619     }
00620     
00621     errno = errno_save;
00622     return 0;
00623 }
00624 
00625 int virt_rename(const char *path, const char *newpath)
00626 {
00627     int res;
00628     ventry *ve;
00629     ventry *newve;
00630     int errno_save = errno;
00631 
00632     res = av_get_ventry(path, 0, &ve);
00633     if(res == 0) {
00634        res = av_get_ventry(newpath, 0, &newve);
00635        if(res == 0) {
00636             res = av_rename(ve, newve);
00637            av_free_ventry(newve);
00638        }
00639        av_free_ventry(ve);
00640     }
00641     if(res < 0) {
00642         errno = -res;
00643         return -1;
00644     }
00645     
00646     errno = errno_save;
00647     return 0;
00648 }
00649 
00650 int virt_link(const char *path, const char *newpath)
00651 {
00652     int res;
00653     ventry *ve;
00654     ventry *newve;
00655     int errno_save = errno;
00656 
00657     res = av_get_ventry(path, 0, &ve);
00658     if(res == 0) {
00659        res = av_get_ventry(newpath, 0, &newve);
00660        if(res == 0) {
00661             res = av_link(ve, newve);
00662            av_free_ventry(newve);
00663        }
00664        av_free_ventry(ve);
00665     }
00666     if(res < 0) {
00667         errno = -res;
00668         return -1;
00669     }
00670     
00671     errno = errno_save;
00672     return 0;
00673 }
00674 
00675 int virt_remove(const char *path)
00676 {
00677     struct stat stbuf;
00678 
00679     if(path != NULL) {
00680         if(virt_lstat(path, &stbuf) == 0) {
00681             if(S_ISDIR(stbuf.st_mode)) {
00682                 return virt_rmdir(path);
00683             } else {
00684                 return virt_unlink(path);
00685             }
00686         }
00687     }
00688 
00689     errno = EFAULT;
00690     return -1;
00691 }
00692 
00693 int virt_islocal(const char *path)
00694 {
00695     int res;
00696     ventry *ve;
00697     int errno_save = errno;
00698     int erg = 0;
00699 
00700     res = av_get_ventry(path, 0, &ve);
00701     if(res == 0) {
00702         if(ve->mnt->base == NULL)
00703             erg = 1;
00704         else
00705             erg = 0;
00706         av_free_ventry(ve);
00707     }
00708     if(res < 0) {
00709         errno = -res;
00710         return -1;
00711     }
00712 
00713     errno = errno_save;
00714     return erg;
00715 }