Back to index

avfs  1.0.1
misc.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 <stdlib.h>
00011 
00012 static int real_chdir(const char *path, int undersc)
00013 {
00014     if(undersc == 0) {
00015         static int (*prev)(const char *);
00016         
00017         if(!prev)
00018             prev = (int (*)(const char *)) 
00019                 __av_get_real("chdir");
00020         
00021         return prev(path);
00022     }
00023     else {
00024         static int (*prev)(const char *);
00025         
00026         if(!prev)
00027             prev = (int (*)(const char *)) 
00028                 __av_get_real("_chdir");
00029         
00030         return prev(path);
00031     }
00032 }
00033 
00034 static char *real_getcwd(char *buf, size_t size, int undersc)
00035 {
00036     if(undersc == 0) {
00037         static char *(*prev)(char *, size_t);
00038         
00039         if(!prev)
00040             prev = (char *(*)(char *, size_t)) 
00041                 __av_get_real("getcwd");
00042         
00043         return prev(buf, size);
00044     }
00045     else {
00046         static char *(*prev)(char *, size_t);
00047         
00048         if(!prev)
00049             prev = (char *(*)(char *, size_t)) 
00050                 __av_get_real("_getcwd");
00051         
00052         return prev(buf, size);
00053     }    
00054 }
00055 
00056 static int real_readlink(const char *path, char *buf, size_t bufsiz,
00057                            int undersc)
00058 {
00059     if(undersc == 0) {
00060         static int (*prev)(const char *, char *, size_t);
00061         
00062         if(!prev)
00063             prev = (int (*)(const char *, char *, size_t))
00064                 __av_get_real("readlink");
00065         
00066         return prev(path, buf, bufsiz);
00067     }
00068     else {
00069         static int (*prev)(const char *, char *, size_t);
00070         
00071         if(!prev)
00072             prev = (int (*)(const char *, char *, size_t))
00073                 __av_get_real("_readlink");
00074         
00075         return prev(path, buf, bufsiz);
00076     }
00077 }
00078 
00079 static int cmd_resolve(const char *path, char *pathbuf, int *isvirtualp)
00080 {
00081     int res;
00082     struct avfs_out_message outmsg;
00083     struct avfs_in_message inmsg;
00084     struct avfs_cmd cmd;
00085     struct avfs_result result;
00086     const char *abspath;
00087 
00088     res = __av_get_abs_path(path, pathbuf, &abspath);
00089     if(res < 0)
00090         return res;
00091     
00092     cmd.type = CMD_RESOLVE;
00093     
00094     outmsg.num = 2;
00095     outmsg.seg[0].len = sizeof(cmd);
00096     outmsg.seg[0].buf = &cmd;
00097     outmsg.seg[1].len = strlen(abspath) + 1;
00098     outmsg.seg[1].buf = abspath;
00099 
00100     inmsg.seg[0].buf = &result;
00101     inmsg.seg[1].buf = pathbuf;
00102 
00103     res = __av_send_message(&outmsg, &inmsg, 0);
00104     if(res == -1)
00105         return -EIO;
00106 
00107     *isvirtualp = result.u.resolve.isvirtual;
00108 
00109     return result.result;
00110 }
00111 
00112 static void set_avfs_cwd(const char *cwd, int isvirtual)
00113 {
00114     pthread_mutex_lock(&__av_cwdlock);
00115     strcpy(__av_cwd, cwd);
00116     __av_virtcwd = isvirtual;
00117     pthread_mutex_unlock(&__av_cwdlock);
00118 }
00119 
00120 static int virt_chdir(const char *path, int undersc)
00121 {
00122     int res = 0;
00123     int local = 0;
00124 
00125     if(__av_maybe_local(path)) {
00126         res = real_chdir(path, undersc);
00127         if(res == 0)
00128             set_avfs_cwd("", 0);
00129         local = __av_is_local(res, path);
00130     }
00131     
00132     if(!local) {
00133         int errnosave;
00134         char pathbuf[PATHBUF_LEN];
00135         int isvirtual;
00136 
00137         errnosave = errno;
00138         res = cmd_resolve(path, pathbuf, &isvirtual);
00139         errno = errnosave;
00140         if(res < 0)
00141             errno = -res, res = -1;
00142         else if(!isvirtual) {
00143             res = real_chdir(pathbuf, undersc);
00144             if(res == 0)
00145                 set_avfs_cwd("", 0);
00146         }
00147         else {
00148             res = real_chdir("/", undersc);
00149             if(res == 0)
00150                 set_avfs_cwd(pathbuf, 1);
00151         }
00152     }
00153 
00154     return res;
00155 }
00156 
00157 static char *getcwd_virt(char *buf, size_t size)
00158 {
00159     if(size == 0) {
00160         errno = EINVAL;
00161         return NULL;
00162     }
00163 
00164     if(size < strlen(__av_cwd) + 1) {
00165         errno = ERANGE;
00166         return NULL;
00167     }
00168 
00169     if(buf == NULL) {
00170         buf = malloc(size);
00171         if(buf == NULL)
00172             return NULL;
00173     }
00174     
00175     strcpy(buf, __av_cwd);
00176     
00177     return buf;
00178 }
00179 
00180 static char *virt_getcwd(char *buf, size_t size, int undersc)
00181 {
00182     char *cwd;
00183 
00184     pthread_mutex_lock(&__av_cwdlock);
00185     if(!__av_virtcwd) {
00186         pthread_mutex_unlock(&__av_cwdlock);
00187         return real_getcwd(buf, size, undersc);
00188     }
00189     
00190     cwd = getcwd_virt(buf, size);
00191     pthread_mutex_unlock(&__av_cwdlock);
00192 
00193     return cwd;
00194 }
00195 
00196 static int cmd_readlink(const char *path, char *buf, size_t bufsiz,
00197                         char *pathbuf)
00198 {
00199     int res;
00200     struct avfs_out_message outmsg;
00201     struct avfs_in_message inmsg;
00202     struct avfs_cmd cmd;
00203     struct avfs_result result;
00204     const char *abspath;
00205 
00206     res = __av_get_abs_path(path, pathbuf, &abspath);
00207     if(res < 0)
00208         return res;
00209     
00210     cmd.type = CMD_READLINK;
00211     cmd.u.readlink.bufsize = bufsiz;
00212     
00213     outmsg.num = 2;
00214     outmsg.seg[0].len = sizeof(cmd);
00215     outmsg.seg[0].buf = &cmd;
00216     outmsg.seg[1].len = strlen(abspath) + 1;
00217     outmsg.seg[1].buf = abspath;
00218 
00219     inmsg.seg[0].buf = &result;
00220     inmsg.seg[1].buf = pathbuf;
00221     inmsg.seg[2].buf = buf;
00222 
00223     res = __av_send_message(&outmsg, &inmsg, 0);
00224     if(res == -1)
00225         return -EIO;
00226 
00227     if(inmsg.seg[1].len == 0)
00228         pathbuf[0] = '\0';
00229 
00230     return result.result;
00231 }
00232 
00233 static int virt_readlink(const char *path, char *buf, size_t bufsiz,
00234                          int undersc)
00235 {
00236     int res = 0;
00237     int local = 0;
00238 
00239     if(__av_maybe_local(path)) {
00240         res = real_readlink(path, buf, bufsiz, undersc);
00241         local = __av_is_local(res, path);
00242     }
00243     
00244     if(!local) {
00245         int errnosave;
00246         char pathbuf[PATHBUF_LEN];
00247 
00248         errnosave = errno;
00249         res = cmd_readlink(path, buf, bufsiz, pathbuf);
00250         errno = errnosave;
00251         if(pathbuf[0])
00252             res = real_readlink(pathbuf, buf, bufsiz, undersc);
00253         else if(res < 0)
00254             errno = -res, res = -1;
00255     }
00256 
00257     return res;
00258 }
00259 
00260 
00261 int chdir(const char *path)
00262 {
00263     return virt_chdir(path, 0);
00264 }
00265 
00266 int _chdir(const char *path)
00267 {
00268     return virt_chdir(path, 1);
00269 }
00270 
00271 char *getcwd(char *buf, size_t size)
00272 {
00273     return virt_getcwd(buf, size, 0);
00274 }
00275 
00276 char *_getcwd(char *buf, size_t size)
00277 {
00278     return virt_getcwd(buf, size, 1);
00279 }
00280 
00281 int readlink(const char *path, char *buf, size_t bufsiz)
00282 {
00283     return virt_readlink(path, buf, bufsiz, 0);
00284 }
00285 
00286 int _readlink(const char *path, char *buf, size_t bufsiz)
00287 {
00288     return virt_readlink(path, buf, bufsiz, 1);
00289 }