Back to index

avfs  1.0.1
client.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 "send.h"
00010 
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <errno.h>
00015 #include <unistd.h>
00016 #include <pthread.h>
00017 #include <pwd.h>
00018 #include <signal.h>
00019 #include <sys/types.h>
00020 #include <sys/stat.h>
00021 #include <sys/wait.h>
00022 #include <sys/socket.h>
00023 #include <sys/un.h>
00024 
00025 #ifndef AVFS_SERVER_DIR
00026 #define AVFS_SERVER_DIR "/usr/lib/avfs"
00027 #endif
00028 
00029 #define AVFS_SERVER_PATH AVFS_SERVER_DIR "/avfs_server"
00030 
00031 #define PWBUFSIZE 256
00032 #define MAXUSERNAME 32
00033 
00034 extern char **environ;
00035 
00036 static const char *get_conndir()
00037 {
00038     static char conndir[64];
00039     static pthread_mutex_t mutex;
00040     static int inited;
00041     char username[MAXUSERNAME + 1];
00042     struct passwd pw;
00043     struct passwd *pwres;
00044     char buf[PWBUFSIZE];
00045     int uid;
00046     int res;
00047     struct stat stbuf;
00048     
00049     pthread_mutex_lock(&mutex);
00050     if(!inited) {
00051         char *variant;
00052         char varbuf[32];
00053 
00054         inited = 1;
00055 
00056         uid = getuid();
00057         res = getpwuid_r(uid, &pw, buf, PWBUFSIZE, &pwres);
00058         if(res == 0) {
00059             strncpy(username, pwres->pw_name, MAXUSERNAME);
00060             username[MAXUSERNAME] = '\0';
00061         }
00062         else 
00063             sprintf(username, "%i", uid);
00064 
00065         varbuf[0] = '\0';
00066         variant = getenv("AVFS_VARIANT");
00067         if(variant != NULL) {
00068             unsigned long i = strtol(variant, NULL, 10);
00069             sprintf(varbuf, "-%lu", i);
00070         }
00071         
00072         sprintf(conndir, "/tmp/.avfsconn-%s%s", username, varbuf);
00073 
00074         res = stat(conndir, &stbuf);
00075         if(res == -1 && errno == ENOENT) {
00076             mkdir(conndir, 0700);
00077             res = stat(conndir, &stbuf);
00078         }
00079         
00080         if(res == -1 || stbuf.st_uid != uid || (stbuf.st_mode & 0077) != 0) {
00081             fprintf(stderr, "AVFS: please check permissions of <%s>\n",
00082                     conndir);
00083             conndir[0] = '\0';
00084         }
00085     }
00086     pthread_mutex_unlock(&mutex);
00087     
00088     if(conndir[0] != '\0')
00089         return conndir;
00090     else
00091         return NULL;
00092 }
00093 
00094 static int start_server()
00095 {
00096     int res;
00097     int pid;
00098     int status;
00099     sigset_t oldset;
00100     sigset_t newset;
00101     int success;
00102     const char *serverpath;
00103     
00104     serverpath = getenv("AVFS_SERVER_PATH");
00105     if(serverpath == NULL || serverpath[0] == '\0')
00106         serverpath = AVFS_SERVER_PATH;
00107 
00108     sigfillset(&newset);
00109     sigprocmask(SIG_SETMASK, &newset, &oldset);
00110 
00111     pid = fork();
00112     if(pid == -1)
00113         return -1;
00114 
00115     if(pid == 0) {
00116         int i;
00117         char **envp = environ;
00118 
00119         for(i = 0; envp[i] != NULL; i++) {
00120             if(strncmp(envp[i], "PWD=", 4) == 0)
00121                 envp[i][4] = '\0';
00122             else if(strncmp(envp[i], "LD_PRELOAD=", 11) == 0)
00123                 envp[i][11] = '\0';
00124         }
00125         
00126         res = execl(serverpath, "avfs_server", NULL);
00127         if(res == -1)
00128             fprintf(stderr, "AVFS: could not start server (%s): %s\n",
00129                     serverpath, strerror(errno));
00130         exit(1);
00131     }
00132 
00133     res = waitpid(pid, &status, 0);
00134     if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
00135         success = 0;
00136     else
00137         success = -1;
00138 
00139     sigprocmask(SIG_SETMASK, &oldset, NULL);
00140     
00141     return success;
00142 }
00143 
00144 static int connect_server(int sock)
00145 {
00146     int res;
00147     struct sockaddr_un addr;
00148     unsigned int addrlen;
00149     const char *conndir = get_conndir();
00150 
00151     if(conndir == NULL)
00152         return -1;
00153 
00154     addr.sun_family = AF_UNIX;
00155     sprintf(addr.sun_path, "%s/server", conndir);
00156     addrlen = (size_t) (((struct sockaddr_un *) 0)->sun_path)
00157         + strlen(addr.sun_path);
00158 
00159     res = connect(sock, (struct sockaddr *) &addr, addrlen);
00160     if(res == -1) {
00161         res = start_server();
00162         if(res == -1)
00163             return -1;
00164 
00165         res = connect(sock, (struct sockaddr *) &addr, addrlen);
00166         if(res == -1)
00167             fprintf(stderr,
00168                     "AVFS: could not connect to server socket (%s): %s\n",
00169                     addr.sun_path, strerror(errno));
00170     }
00171     
00172     return res;
00173 }
00174 
00175 static int sock_send_message(int sock, struct avfs_out_message *out,
00176                              struct avfs_in_message *in)
00177 {
00178     int res;
00179 
00180     res = connect_server(sock);
00181     if(res == -1)
00182         return -1;
00183 
00184     res = __av_write_message(sock, out);
00185     if(res == -1)
00186         return -1;
00187     
00188     res = __av_read_message(sock, in);
00189     if(res == -1)
00190         return -1;
00191     
00192     return 0;
00193 }
00194 
00195 int __av_send_message(struct avfs_out_message *out,
00196                       struct avfs_in_message *in, int keepsock)
00197 {
00198     int res;
00199     int sock;
00200 
00201     sock = socket(AF_UNIX, SOCK_STREAM, 0);
00202     if(sock == -1)
00203         return -1;
00204 
00205     res = sock_send_message(sock, out, in);
00206     if(res == -1)
00207         return -1;
00208 
00209     if(keepsock)
00210         return sock;
00211     else {
00212         close(sock);
00213         return 0;
00214     }
00215 }