Back to index

avfs  1.0.1
rsh.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 2000-2001  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 "remote.h"
00010 #include "runprog.h"
00011 #include "parsels.h"
00012 #include "filebuf.h"
00013 
00014 #include <unistd.h>
00015 #include <fcntl.h>
00016 #include <sys/stat.h>
00017 
00018 #define RSH_LIST_TIMEOUT 20000
00019 
00020 struct rshlocalfile {
00021     char *tmpfile;
00022     struct program *pr;
00023     avoff_t currsize;
00024 };
00025 
00026 static void rsh_parse_line(struct lscache *lc, const char *line,
00027                            struct remdirlist *dl)
00028 {
00029     int res;
00030     char *filename;
00031     char *linkname;
00032     struct avstat stbuf;
00033 
00034     res = av_parse_ls(lc, line, &stbuf, &filename, &linkname);
00035     if(res != 1)
00036         return;
00037 
00038     av_remote_add(dl, filename, linkname, &stbuf);
00039 
00040     av_free(filename);
00041     av_free(linkname);
00042 }
00043 
00044 static int rsh_read_list(struct program *pr, struct lscache *lc,
00045                          struct remdirlist *dl)
00046 {
00047     int res;
00048 
00049     while(1) {
00050         char *line;
00051 
00052         res = av_program_getline(pr, &line, RSH_LIST_TIMEOUT);
00053         if(res < 0)
00054             return res;
00055         if(res == 0) {
00056             av_log(AVLOG_ERROR, "RSH: timeout");
00057             return -EIO;
00058         }
00059         if(line == NULL)
00060             return 0;
00061 
00062         rsh_parse_line(lc, line, dl);
00063         av_free(line);
00064     }
00065 }
00066 
00067 static int rsh_isspecial(int c)
00068 {
00069     const char *normchars = "/.~@#%^-_=+:";
00070 
00071     if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || 
00072        (c >= 'a' && c <= 'z') || c >= 160 || strchr(normchars, c) != NULL)
00073         return 0;
00074     else
00075         return 1;
00076 }
00077 
00078 static char *rsh_code_name(const char *name)
00079 {
00080     char *newname = (char *) av_malloc(strlen(name) * 2 + 1);
00081     const char *s;
00082     char *d;
00083     
00084     for(s = name, d = newname; *s != '\0'; s++, d++) {
00085         if(rsh_isspecial((unsigned char) *s))
00086             *d++ = '\\';
00087         
00088         *d = *s;
00089     }
00090     *d = '\0';
00091     
00092     return newname;
00093 }
00094 
00095 static char *rsh_split_hostpart(const char *hostpart, const char **hostp)
00096 {
00097     unsigned int i;
00098     
00099     for(i = 0; hostpart[i] != '\0'; i++) {
00100         if(hostpart[i] == '@') {
00101             *hostp = hostpart + i + 1;
00102             return av_strndup(hostpart, i);
00103         }
00104     }
00105     *hostp = hostpart;
00106     return NULL;
00107 }
00108 
00109 static int rsh_list(struct remote *rem, struct remdirlist *dl)
00110 {
00111     int res;
00112     struct program *pr;
00113     const char *prog[8];
00114     char *escaped_path;
00115     unsigned int arg;
00116     const char *host;
00117     char *username;
00118 
00119     escaped_path = rsh_code_name(dl->hostpath.path);
00120     username = rsh_split_hostpart(dl->hostpath.host, &host);
00121 
00122     arg = 0;
00123     prog[arg++] = rem->name;
00124     if(username != NULL) {
00125         prog[arg++] = "-l";
00126         prog[arg++] = username;
00127     }
00128     prog[arg++] = host;
00129     prog[arg++] = "/bin/ls";
00130     if((dl->flags & REM_LIST_SINGLE) != 0)
00131         prog[arg++] = "-ldn";
00132     else
00133         prog[arg++] = "-lan";
00134     prog[arg++] = escaped_path;
00135     prog[arg++] = NULL;
00136   
00137     res = av_start_program(prog, &pr);
00138     if(res == 0) {
00139         struct lscache *lc = av_new_lscache();
00140         res = rsh_read_list(pr, lc, dl);
00141         av_unref_obj(lc);
00142         av_unref_obj(pr);
00143     }
00144     av_free(escaped_path);
00145     av_free(username);
00146 
00147     return res;
00148 }
00149 
00150 static void rsh_free_localfile(struct rshlocalfile *lf)
00151 {
00152     
00153     if(lf->pr != NULL) {
00154         av_program_log_output(lf->pr);
00155         av_unref_obj(lf->pr);
00156     }
00157 }
00158 
00159 static int rsh_get(struct remote *rem, struct remgetparam *gp)
00160 {
00161     int res;
00162     struct rshlocalfile *lf;
00163     char *tmpfile;
00164     char *codedpath;
00165     char *path;
00166     const char *prog[4];
00167     char progname[4];
00168 
00169     strcpy(progname, "rcp");
00170     progname[0] = rem->name[0];
00171 
00172     res = av_get_tmpfile(&tmpfile);
00173     if(res < 0)
00174        return res;
00175 
00176     AV_NEW_OBJ(lf, rsh_free_localfile);
00177     lf->pr = NULL;
00178 
00179     codedpath = rsh_code_name(gp->hostpath.path);
00180     path = av_stradd(NULL, gp->hostpath.host, ":", codedpath, NULL);
00181     av_free(codedpath);
00182 
00183     lf->tmpfile = tmpfile;
00184 
00185     prog[0] = progname;
00186     prog[1] = path;
00187     prog[2] = lf->tmpfile;
00188     prog[3] = NULL;
00189 
00190     res = av_start_program(prog, &lf->pr);
00191     av_free(path);
00192     if(res < 0) {
00193         av_unref_obj(lf);
00194         av_del_tmpfile(tmpfile);
00195         return res;
00196     }
00197 
00198     lf->currsize = 0;
00199 
00200     gp->data = lf;
00201     gp->localname = lf->tmpfile;
00202 
00203     return 0;
00204 }
00205 
00206 static int rsh_wait(struct remote *rem, void *data, avoff_t end)
00207 {
00208     int res;
00209     struct rshlocalfile *lf = (struct rshlocalfile *) data;
00210 
00211     /* FIXME: timeout? */
00212     do {
00213         struct stat stbuf;
00214         
00215         res = av_program_log_output(lf->pr);
00216         if(res <= 0)
00217             return res;
00218 
00219         res = stat(lf->tmpfile, &stbuf);
00220         if(res == 0)
00221             lf->currsize = stbuf.st_size;
00222 
00223         if(lf->currsize < end)
00224             av_sleep(250);
00225 
00226     } while(lf->currsize < end);
00227 
00228     return 1;
00229 }
00230 
00231 static void rsh_destroy(struct remote *rem)
00232 {
00233     av_free(rem->name);
00234     av_free(rem);
00235 }
00236 
00237 static int init_rsh(struct vmodule *module, const char *name)
00238 {
00239     struct remote *rem;
00240     struct avfs *avfs;
00241 
00242     AV_NEW(rem);
00243 
00244     rem->data    = NULL;
00245     rem->name    = av_strdup(name);
00246     rem->list    = rsh_list;
00247     rem->get     = rsh_get;
00248     rem->wait    = rsh_wait;
00249     rem->destroy = rsh_destroy;
00250     
00251     return av_remote_init(module, rem, &avfs);
00252 }
00253 
00254 extern int av_init_module_rsh(struct vmodule *module);
00255 
00256 int av_init_module_rsh(struct vmodule *module)
00257 {
00258     int res;
00259 
00260     res = init_rsh(module, "rsh");
00261     if(res < 0)
00262         return res;
00263 
00264     res = init_rsh(module, "ssh");
00265     if(res < 0)
00266         return res;
00267 
00268     return 0;
00269 }