Back to index

avfs  1.0.1
stat.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 <sys/stat.h>
00013 #ifdef HAVE_ACL
00014 #include <sys/acl.h>
00015 #endif
00016 
00017 #ifdef HAVE_STAT64
00018 static int real_stat64(const char *path, struct stat64 *buf, int deref,
00019                        int undersc)
00020 {
00021     if(!deref) {
00022         if(undersc == 0) {
00023             static int (*prev)(const char *, struct stat64 *);
00024             if(!prev) 
00025                 prev = (int (*)(const char *, struct stat64 *))
00026                     __av_get_real("lstat64");
00027             
00028             return prev(path, buf);
00029         }
00030         else {
00031             static int (*prev)(const char *, struct stat64 *);
00032             if(!prev) 
00033                 prev = (int (*)(const char *, struct stat64 *))
00034                     __av_get_real("_lstat64");
00035             
00036             return prev(path, buf);
00037         }
00038     }
00039     else {
00040         if(undersc == 0) {
00041             static int (*prev)(const char *, struct stat64 *);
00042             if(!prev) 
00043                 prev = (int (*)(const char *, struct stat64 *)) 
00044                     __av_get_real("stat64");
00045             
00046             return prev(path, buf);
00047         }
00048         else {
00049             static int (*prev)(const char *, struct stat64 *);
00050             if(!prev) 
00051                 prev = (int (*)(const char *, struct stat64 *)) 
00052                     __av_get_real("_stat64");
00053             
00054             return prev(path, buf);
00055         }
00056     }
00057 }
00058 
00059 static int real_fstat64(int fd, struct stat64 *buf, int undersc)
00060 {
00061     if(undersc == 0) {
00062         static int (*prev)(int, struct stat64 *);
00063         if(!prev)
00064             prev = (int (*)(int, struct stat64 *)) __av_get_real("fstat64");
00065         
00066         return prev(fd, buf);
00067     }
00068     else {
00069         static int (*prev)(int, struct stat64 *);
00070         if(!prev)
00071             prev = (int (*)(int, struct stat64 *)) __av_get_real("_fstat64");
00072         
00073         return prev(fd, buf);        
00074     }
00075 }
00076 #endif
00077 
00078 static int real_stat(const char *path, struct stat *buf, int deref,
00079                      int undersc)
00080 {
00081     if(!deref) {
00082         if(undersc == 0) {
00083             static int (*prev)(const char *, struct stat *);
00084             if(!prev) 
00085                 prev = (int (*)(const char *, struct stat *))
00086                     __av_get_real("lstat");
00087             
00088             return prev(path, buf);
00089         }
00090         else {
00091             static int (*prev)(const char *, struct stat *);
00092             if(!prev) 
00093                 prev = (int (*)(const char *, struct stat *))
00094                     __av_get_real("_lstat");
00095             
00096             return prev(path, buf);
00097         }
00098     }
00099     else {
00100         if(undersc == 0) {
00101             static int (*prev)(const char *, struct stat *);
00102             if(!prev) 
00103                 prev = (int (*)(const char *, struct stat *))
00104                     __av_get_real("stat");
00105             
00106             return prev(path, buf);
00107         }
00108         else {
00109             static int (*prev)(const char *, struct stat *);
00110             if(!prev) 
00111                 prev = (int (*)(const char *, struct stat *))
00112                     __av_get_real("_stat");
00113             
00114             return prev(path, buf);
00115         }
00116     }
00117 }
00118 
00119 static int real_fstat(int fd, struct stat *buf, int undersc)
00120 {
00121     if(undersc == 0) {
00122         static int (*prev)(int, struct stat *);
00123         if(!prev)
00124             prev = (int (*)(int, struct stat *)) __av_get_real("fstat");
00125         
00126         return prev(fd, buf);
00127     }
00128     else {
00129         static int (*prev)(int, struct stat *);
00130         if(!prev)
00131             prev = (int (*)(int, struct stat *)) __av_get_real("_fstat");
00132         
00133         return prev(fd, buf);        
00134     }
00135 }
00136 
00137 #ifdef HAVE_ACL
00138 static int real_acl(const char *path, int cmd, int nent, aclent_t *aclbuf,
00139                     int undersc)
00140 {
00141     if(undersc == 0) {
00142         static int (*prev)(const char *, int, int, aclent_t *);
00143         if(!prev)
00144             prev = (int (*)(const char *, int, int, aclent_t *)) 
00145                 __av_get_real("acl");
00146         
00147         return prev(path, cmd, nent, aclbuf);
00148     }
00149     else {
00150         static int (*prev)(const char *, int, int, aclent_t *);
00151         if(!prev)
00152             prev = (int (*)(const char *, int, int, aclent_t *)) 
00153                 __av_get_real("_acl");
00154         
00155         return prev(path, cmd, nent, aclbuf);
00156     }
00157 }
00158 #endif
00159 
00160 static int real_access(const char *path, int amode, int undersc)
00161 {
00162     if(undersc == 0) {
00163         static int (*prev)(const char *, int);
00164         if(!prev)
00165             prev = (int (*)(const char *, int))  __av_get_real("access");
00166         
00167         return prev(path, amode);
00168     }
00169     else {
00170         static int (*prev)(const char *, int);
00171         if(!prev)
00172             prev = (int (*)(const char *, int))  __av_get_real("_access");
00173         
00174         return prev(path, amode);
00175     }
00176 }
00177 
00178 static int cmd_getattr(const char *path, struct avstat *buf, int deref,
00179                        char *pathbuf, int attrmask)
00180 {
00181     int res;
00182     struct avfs_out_message outmsg;
00183     struct avfs_in_message inmsg;
00184     struct avfs_cmd cmd;
00185     struct avfs_result result;
00186     const char *abspath;
00187 
00188     res = __av_get_abs_path(path, pathbuf, &abspath);
00189     if(res < 0)
00190         return res;
00191     
00192     cmd.type = CMD_GETATTR;
00193     if(deref)
00194         cmd.u.getattr.flags = 0;
00195     else
00196         cmd.u.getattr.flags = AVO_NOFOLLOW;
00197     cmd.u.getattr.attrmask = attrmask;
00198     
00199     outmsg.num = 2;
00200     outmsg.seg[0].len = sizeof(cmd);
00201     outmsg.seg[0].buf = &cmd;
00202     outmsg.seg[1].len = strlen(abspath) + 1;
00203     outmsg.seg[1].buf = abspath;
00204 
00205     inmsg.seg[0].buf = &result;
00206     inmsg.seg[1].buf = pathbuf;
00207     inmsg.seg[2].buf = buf;
00208 
00209     res = __av_send_message(&outmsg, &inmsg, 0);
00210     if(res == -1)
00211         return -EIO;
00212 
00213     if(inmsg.seg[1].len == 0)
00214         pathbuf[0] = '\0';
00215 
00216     return result.result;
00217 }
00218 
00219 static int cmd_access(const char *path, int amode,  char *pathbuf)
00220 {
00221     int res;
00222     struct avfs_out_message outmsg;
00223     struct avfs_in_message inmsg;
00224     struct avfs_cmd cmd;
00225     struct avfs_result result;
00226     const char *abspath;
00227 
00228     res = __av_get_abs_path(path, pathbuf, &abspath);
00229     if(res < 0)
00230         return res;
00231     
00232     cmd.type = CMD_ACCESS;
00233     cmd.u.access.amode = amode;
00234     
00235     outmsg.num = 2;
00236     outmsg.seg[0].len = sizeof(cmd);
00237     outmsg.seg[0].buf = &cmd;
00238     outmsg.seg[1].len = strlen(abspath) + 1;
00239     outmsg.seg[1].buf = abspath;
00240 
00241     inmsg.seg[0].buf = &result;
00242     inmsg.seg[1].buf = pathbuf;
00243 
00244     res = __av_send_message(&outmsg, &inmsg, 0);
00245     if(res == -1)
00246         return -EIO;
00247 
00248     if(inmsg.seg[1].len == 0)
00249         pathbuf[0] = '\0';
00250 
00251     return result.result;
00252 }
00253 
00254 
00255 static int fstat_server(int serverfh, struct avstat *buf)
00256 {
00257     int res;
00258     struct avfs_out_message outmsg;
00259     struct avfs_in_message inmsg;
00260     struct avfs_cmd cmd;
00261     struct avfs_result result;
00262 
00263     cmd.type = CMD_FSTAT;
00264     cmd.u.fdops.serverfh = serverfh;
00265     
00266     outmsg.num = 1;
00267     outmsg.seg[0].len = sizeof(cmd);
00268     outmsg.seg[0].buf = &cmd;
00269 
00270     inmsg.seg[0].buf = &result;
00271     inmsg.seg[1].buf = buf;
00272 
00273     res = __av_send_message(&outmsg, &inmsg, 0);
00274     if(res == -1)
00275         return -EIO;
00276 
00277     return result.result;
00278 }
00279 
00280 
00281 
00282 #ifdef HAVE_STAT64
00283 static void convert_stat64(struct avstat *vbuf, struct stat64 *lbuf)
00284 {
00285     memset((void *) lbuf, 0, sizeof(*lbuf));
00286   
00287     lbuf->st_dev      = vbuf->dev;
00288     lbuf->st_ino      = vbuf->ino;
00289     lbuf->st_mode     = vbuf->mode;
00290     lbuf->st_nlink    = vbuf->nlink;
00291     lbuf->st_uid      = vbuf->uid;
00292     lbuf->st_gid      = vbuf->gid;
00293     lbuf->st_rdev     = vbuf->rdev;
00294     lbuf->st_size     = vbuf->size;
00295     lbuf->st_blksize  = vbuf->blksize;
00296     lbuf->st_blocks   = vbuf->blocks;
00297     lbuf->st_atime    = vbuf->atime.sec;
00298     lbuf->st_mtime    = vbuf->mtime.sec;
00299     lbuf->st_ctime    = vbuf->ctime.sec;
00300 }
00301 
00302 static int virt_stat64(const char *path, struct stat64 *buf, int deref,
00303                        int undersc)
00304 {
00305     int res = 0;
00306     int local = 0;
00307 
00308     if(__av_maybe_local(path)) {
00309         res = real_stat64(path, buf, deref, undersc);
00310         local = __av_is_local(res, path);
00311     }
00312     
00313     if(!local) {
00314         int errnosave;
00315         struct avstat vbuf;
00316         char pathbuf[PATHBUF_LEN];
00317 
00318         errnosave = errno;
00319         res = cmd_getattr(path, &vbuf, deref, pathbuf, AVA_ALL);
00320         errno = errnosave;
00321         if(pathbuf[0])
00322             res = real_stat64(pathbuf, buf, deref, undersc);
00323         else if(res < 0)
00324             errno = -res, res = -1;
00325         else
00326             convert_stat64(&vbuf, buf);
00327     }
00328 
00329     return res;
00330 }
00331 
00332 static int virt_fstat64(int fd, struct stat64 *buf, int undersc)
00333 {
00334     int res;
00335 
00336     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00337         res =  real_fstat64(fd, buf, undersc);
00338     else {
00339         struct avstat vbuf;
00340         int errnosave = errno;
00341         res = fstat_server(SERVERFH(fd), &vbuf);
00342         if(res < 0)
00343             errno = -res, res = -1;
00344         else {
00345             errno = errnosave;
00346             convert_stat64(&vbuf, buf);
00347         }
00348     }
00349 
00350     return res;
00351 }
00352 #endif
00353 
00354 static void convert_stat(struct avstat *vbuf, struct stat *lbuf)
00355 {
00356     memset((void *) lbuf, 0, sizeof(*lbuf));
00357   
00358     lbuf->st_dev      = vbuf->dev;
00359     lbuf->st_ino      = vbuf->ino;
00360     lbuf->st_mode     = vbuf->mode;
00361     lbuf->st_nlink    = vbuf->nlink;
00362     lbuf->st_uid      = vbuf->uid;
00363     lbuf->st_gid      = vbuf->gid;
00364     lbuf->st_rdev     = vbuf->rdev;
00365     lbuf->st_size     = vbuf->size;
00366     lbuf->st_blksize  = vbuf->blksize;
00367     lbuf->st_blocks   = vbuf->blocks;
00368     lbuf->st_atime    = vbuf->atime.sec;
00369     lbuf->st_mtime    = vbuf->mtime.sec;
00370     lbuf->st_ctime    = vbuf->ctime.sec;
00371 }
00372 
00373 static int virt_stat(const char *path, struct stat *buf, int deref, 
00374                      int undersc)
00375 {
00376     int res = 0;
00377     int local = 0;
00378 
00379     if(__av_maybe_local(path)) {
00380         res = real_stat(path, buf, deref, undersc);
00381         local = __av_is_local(res, path);
00382     }
00383     
00384     if(!local) {
00385         int errnosave;
00386         struct avstat vbuf;
00387         char pathbuf[PATHBUF_LEN];
00388 
00389         errnosave = errno;
00390         res = cmd_getattr(path, &vbuf, deref, pathbuf, AVA_ALL);
00391         errno = errnosave;
00392         if(pathbuf[0])
00393             res = real_stat(pathbuf, buf, deref, undersc);
00394         else if(res < 0)
00395             errno = -res, res = -1;
00396         else
00397             convert_stat(&vbuf, buf);
00398     }
00399 
00400     return res;
00401 }
00402 
00403 static int virt_fstat(int fd, struct stat *buf, int undersc)
00404 {
00405     int res;
00406 
00407     if(!FD_OK(fd) || !ISVIRTUAL(fd))
00408         res =  real_fstat(fd, buf, undersc);
00409     else {
00410         struct avstat vbuf;
00411         int errnosave = errno;
00412         res = fstat_server(SERVERFH(fd), &vbuf);
00413         if(res < 0)
00414             errno = -res, res = -1;
00415         else {
00416             errno = errnosave;
00417             convert_stat(&vbuf, buf);
00418         }
00419     }
00420 
00421     return res;
00422 }
00423 
00424 #ifdef HAVE_ACL
00425 static int convert_acl(struct avstat *vbuf, int cmd, int nent,
00426                        aclent_t *aclbuf)
00427 {
00428     int res;
00429 
00430     switch(cmd) {
00431     case GETACLCNT:
00432         res = 4;
00433         break;
00434         
00435     case SETACL:
00436         errno = ENOSYS;
00437         res = -1;
00438         break;
00439 
00440     case GETACL:
00441         if(nent < 4) {
00442             errno = ENOSPC;
00443             res = -1;
00444         }
00445         else {
00446             aclbuf[0].a_type = USER_OBJ;
00447             aclbuf[0].a_id   = vbuf->uid;
00448             aclbuf[0].a_perm = (vbuf->mode & 0700) >> 6;
00449 
00450             aclbuf[1].a_type = GROUP_OBJ;
00451             aclbuf[1].a_id   = vbuf->gid;
00452             aclbuf[1].a_perm = (vbuf->mode & 0070) >> 3;
00453 
00454             aclbuf[2].a_type = CLASS_OBJ;
00455             aclbuf[2].a_id   = -1;
00456             aclbuf[2].a_perm = 0777;
00457 
00458             aclbuf[3].a_type = OTHER_OBJ;
00459             aclbuf[3].a_id   = -1;
00460             aclbuf[3].a_perm = (vbuf->mode & 0007);
00461             res = 4;
00462         }
00463         break;
00464 
00465         default:
00466             errno = EINVAL;
00467             res = -1;
00468             break;
00469     }
00470 
00471     return res;
00472 }
00473 
00474 static int virt_acl(const char *path, int cmd, int nent, aclent_t *aclbuf,
00475                     int undersc)
00476 {
00477     int res = 0;
00478     int local = 0;
00479 
00480     if(__av_maybe_local(path)) {
00481         res = real_acl(path, cmd, nent, aclbuf, undersc);
00482         local = __av_is_local(res, path);
00483     }
00484     
00485     if(!local) {
00486         int errnosave;
00487         struct avstat vbuf;
00488         char pathbuf[PATHBUF_LEN];
00489         int attrmask = AVA_UID | AVA_GID | AVA_MODE;
00490 
00491         errnosave = errno;
00492         res = cmd_getattr(path, &vbuf, 1, pathbuf, attrmask);
00493         errno = errnosave;
00494         if(pathbuf[0])
00495             res = real_acl(pathbuf, cmd, nent, aclbuf, undersc);
00496         else if(res < 0)
00497             errno = -res, res = -1;
00498         else
00499             res = convert_acl(&vbuf, cmd, nent, aclbuf);
00500     }
00501 
00502     return res;
00503 }
00504 #endif
00505 
00506 static int virt_access(const char *path, int amode, int undersc)
00507 {
00508     int res = 0;
00509     int local = 0;
00510 
00511     if(__av_maybe_local(path)) {
00512         res = real_access(path, amode, undersc);
00513         local = __av_is_local(res, path);
00514     }
00515     
00516     if(!local) {
00517         int errnosave;
00518         char pathbuf[PATHBUF_LEN];
00519 
00520         errnosave = errno;
00521         res = cmd_access(path, amode, pathbuf);
00522         errno = errnosave;
00523         if(pathbuf[0])
00524             res = real_access(pathbuf, amode, undersc);
00525         else if(res < 0)
00526             errno = -res, res = -1;
00527     }
00528 
00529     return res;
00530 }
00531 
00532 
00533 #ifdef HAVE_STAT64
00534 int lstat64(const char *path, struct stat64 *buf)
00535 {
00536     return virt_stat64(path, buf, 0, 0);
00537 }
00538 
00539 int _lstat64(const char *path, struct stat64 *buf)
00540 {
00541     return virt_stat64(path, buf, 0, 1);
00542 }
00543 
00544 int stat64(const char *path, struct stat64 *buf)
00545 {
00546     return virt_stat64(path, buf, 1, 0);
00547 }
00548 
00549 int _stat64(const char *path, struct stat64 *buf)
00550 {
00551     return virt_stat64(path, buf, 1, 1);
00552 }
00553 
00554 int fstat64(int fd, struct stat64 *buf)
00555 {
00556     return virt_fstat64(fd, buf, 0);
00557 }
00558 
00559 int _fstat64(int fd, struct stat64 *buf)
00560 {
00561     return virt_fstat64(fd, buf, 1);
00562 }
00563 #endif
00564 
00565 int lstat(const char *path, struct stat *buf)
00566 {
00567     return virt_stat(path, buf, 0, 0);
00568 }
00569 
00570 int _lstat(const char *path, struct stat *buf)
00571 {
00572     return virt_stat(path, buf, 0, 1);
00573 }
00574 
00575 int stat(const char *path, struct stat *buf)
00576 {
00577     return virt_stat(path, buf, 1, 0);
00578 }
00579 
00580 int _stat(const char *path, struct stat *buf)
00581 {
00582     return virt_stat(path, buf, 1, 1);
00583 }
00584 
00585 int fstat(int fd, struct stat *buf)
00586 {
00587     return virt_fstat(fd, buf, 0);
00588 }
00589 
00590 int _fstat(int fd, struct stat *buf)
00591 {
00592     return virt_fstat(fd, buf, 1);
00593 }
00594 
00595 #ifdef HAVE_ACL
00596 int acl(const char *path, int cmd, int nent, aclent_t *aclbuf)
00597 {
00598     return virt_acl(path, cmd, nent, aclbuf, 0);
00599 }
00600 
00601 int _acl(const char *path, int cmd, int nent, aclent_t *aclbuf)
00602 {
00603     return virt_acl(path, cmd, nent, aclbuf, 1);
00604 }
00605 #endif
00606 
00607 int access(const char *path, int amode)
00608 {
00609     return virt_access(path, amode, 0);
00610 }
00611 
00612 int _access(const char *path, int amode)
00613 {
00614     return virt_access(path, amode, 1);
00615 }