This patch improves the error handling in xget such that it can handle
the accidental export of procfs, devfs, sysfs or anything else.
It does the following things
a) While the xget server sets up files to be served, if it cannot
open/read a file it just skips it and goes on to serve the other files.
b) Some special files (from procfs) are set up properly by the xget
server but when it tries to read from them, it returns an EINVAL.
Now if the server cannot handle a read request on a file, it simply
prints an error in the log, and the clients exit saying that the file
cannot be downloaded.
c) another minor bug in which the client segfaulted while unmounting the
filesystem during an error.
Part of the patch is based on some improvements Hugh was doing with the
error handling.
Signed-off-by: Abhishek Kulkarni <[EMAIL PROTECTED]>
Index: xget.c
===================================================================
--- xget.c (revision 710)
+++ xget.c (working copy)
@@ -484,8 +484,21 @@
if (f->finished == 1)
file_finalize(f, 0);
- if(f->finished == 2)
+ if (f->finished == 2)
continue;
+
+ if (f->finished == 4) {
+ debug(Dbgfn, "Error downloading file %s
\n", f->lname);
+ if (f->datafid) {
+ spc_close(f->datafid);
+ f->datafid = NULL;
+ }
+
+ if (f->fs && f->fs != masterfs)
+
spc_umount(f->fs);
+
+ f->finished = 2;
+ }
fdone = 0;
if (time(NULL) - f->progress > retrytime) {
@@ -656,7 +669,8 @@
continue;
debug(Dbgfn, "Adding file: %s\n", buf);
- if (localfileread(dir, buf) == NULL)
+ localfileread(dir, buf);
+ if (sp_haserror())
goto error;
}
closedir(d);
@@ -714,10 +728,9 @@
par = dir->parent;
parent_remove(dir);
dir_remove(dir);
- if ((ret = localfileread(par, name)) == NULL) {
- sp_uerror(errno);
+ ret = localfileread(par, name);
+ if (sp_haserror())
goto error;
- }
}
else if (S_ISDIR(st.st_mode))
ret = updatedir(dir, name);
@@ -871,6 +884,8 @@
Spfile *file;
f = sp_malloc(sizeof(*f) + strlen(nname) + strlen(lname) + 2);
+ if (!f)
+ return NULL;
qp = qpath++ * 16;
f->nname = ((char *) f) + sizeof(*f);
strcpy(f->nname, nname);
@@ -879,6 +894,7 @@
f->datasize = datasize;
f->datalen = datalen;
f->numworkers = 0;
+ f->fs = NULL;
f->firstworker = NULL;
f->lastworker = NULL;
f->nextworker = NULL;
@@ -911,13 +927,13 @@
static Spfile*
localfileread(Spfile *parent, char *filename)
{
- char *name, *nextf;
+ char *name, *nextf, *ename;
struct stat st;
File *f;
Spfile *dir, *ret;
DIR *dirstr;
struct dirent *de;
- int fd;
+ int fd, ecode;
u32 crc, npmode;
Spuser *usr;
Spgroup *grp;
@@ -927,6 +943,8 @@
ret = NULL;
usr = NULL;
grp = NULL;
+ nextf = NULL;
+
if ((name = strrchr(filename, '/')))
name++;
else
@@ -934,7 +952,7 @@
if (lstat(filename, &st) < 0) {
sp_uerror(errno);
- return NULL;
+ goto error;
}
npmode = umode2npmode(st.st_mode);
@@ -956,14 +974,19 @@
goto error;
close(fd);
+
+ if (sp_haserror())
+ goto error;
+
debug(Dbgsrvfn, "Added file: %s\n", f->dir->name);
ret = f->dir;
+
} else if (S_ISDIR(st.st_mode)) {
if (strcmp(path, filename)) {
dir = create_file(parent, name, npmode,
qpath++ * 16, &dir_ops, usr, grp,
NULL);
if (!dir)
- return NULL;
+ goto error;
debug(Dbgsrvfn, "Added dir: %s\n", dir->name);
}
@@ -980,22 +1003,42 @@
continue;
nextf = (char *) sp_malloc(strlen(filename) +
- strlen(de->d_name) + 2);
+ strlen(de->d_name) +
2);
+
+ if (!nextf)
+ goto error;
+
sprintf(nextf, "%s/%s", filename, de->d_name);
localfileread(dir, nextf);
+
free(nextf);
+ nextf = NULL;
}
closedir(dirstr);
}
ret->mtime = ret->atime = st.st_mtime;
- }
-
+ if (sp_haserror())
+ goto error;
+ } else
+ goto error;
+
return ret;
error:
+ if (sp_haserror()) {
+ sp_rerror(&ename, &ecode);
+ debug(Dbgfn, "Error: Skipping %s : %s\n",
+ filename, ename);
+ sp_werror(NULL, 0);
+ }
+
if (fd > -1)
close(fd);
+
+ if (nextf)
+ free(nextf);
+
return NULL;
}
@@ -1060,11 +1103,16 @@
return;
error:
- xget_uerror(errno);
+ debug(Dbgfn, "Error: Cannot process request for file %s : %s\n",
+ f->lname, strerror(errno));
+
if (buf)
free(buf);
if (fd > 0)
close(fd);
+
+ rc = sp_create_rflush();
+ sp_respond(req->req, rc);
}
static void
@@ -1104,6 +1152,9 @@
readsize = fd->iounit;
buf = sp_malloc(readsize);
n = spcfd_read(fd, buf, readsize);
+ if (n < 0)
+ goto error;
+
if ((lfd = open(f->lname, O_CREAT | O_RDWR, 0600)) == -1) {
xget_uerror(errno);
goto error;
@@ -1142,12 +1193,15 @@
return;
error:
+ f->finished = 4;
+
if (st)
free(st);
if (buf)
free(buf);
if (lfd > -1)
close(lfd);
+
return;
}
@@ -1359,6 +1413,7 @@
}
free(fnames[i]);
+ fnames[i] = NULL;
}
free(fnames);
@@ -1374,6 +1429,10 @@
done:
spc_close(fid);
+ for (i=0; i < n; i++) {
+ if (fnames[i])
+ free(fnames[i]);
+ }
return ret;
}
@@ -1756,10 +1815,8 @@
chdir("/");
}
- if (!masterfs) {
- if (localfileread(root, path) == NULL)
- goto error;
- }
+ if (!masterfs)
+ localfileread(root, path);
while (1) {
if (xget_haserror())
@@ -1797,7 +1854,7 @@
if (f->availfid)
spc_close(f->availfid);
- if (f->fs && f->fs != masterfs)
+ if (netaddress && f->fs && f->fs != masterfs)
spc_umount(f->fs);
f1 = f->next;