a7d9ce80c3
- cmkdir now uses /dev/srandom (actually changed to arandom by me) - support for filenames w/ 8bit chars - sprintf() replaced with snprintf() - some bugfixes from Andreas Voegele <voegelas at gmx.net>
421 lines
11 KiB
Plaintext
421 lines
11 KiB
Plaintext
--- cfs_fh.c.orig Thu May 3 20:24:59 2001
|
|
+++ cfs_fh.c Sat Mar 12 20:21:46 2005
|
|
@@ -177,6 +177,13 @@
|
|
perror("write");
|
|
return -1;
|
|
}
|
|
+ /* due to the way the file is padded we may actually have to
|
|
+ truncate it here. This happens when the write is at the end of
|
|
+ the file, is shorter than CFSBLOCK and brings the file to a length
|
|
+ which is evenly dividable by CFSBLOCK */
|
|
+ if (offset+len > dtov(sb.st_size) && vtod(offset+len) < sb.st_size) {
|
|
+ ftruncate(fd, vtod(offset+len));
|
|
+ }
|
|
/* iolen may contain CFSBLOCK extra chars */
|
|
return(dtov(iolen)-fronterr);
|
|
}
|
|
@@ -195,30 +202,39 @@
|
|
char *s;
|
|
{
|
|
static char cryptname[NFS_MAXNAMLEN+1];
|
|
+ static const u_char hexdigit[16] = {
|
|
+ '0', '1', '2', '3', '4', '5', '6', '7',
|
|
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
|
+ };
|
|
u_char cryptstring[MAXCLEARNAME+CFSBLOCK+1];
|
|
- u_char x[3];
|
|
u_long l;
|
|
- int i;
|
|
+ int i, j;
|
|
|
|
if ((s==NULL) || ((l=strlen(s)+1)>MAXCLEARNAME))
|
|
return NULL;
|
|
if (!strcmp(s,".") || !strcmp(s,".."))
|
|
return s;
|
|
l=(l+(CFSBLOCK-1)) & (~(CFSBLOCK-1));
|
|
+ if (l >= (sizeof(cryptname) >> 1))
|
|
+ return NULL;
|
|
bzero((char *)cryptstring,l);
|
|
strcpy(cryptstring,s);
|
|
chksum(cryptstring,l);
|
|
doencrypt(key,cryptstring,l,10241,zerovect);
|
|
- cryptname[0]='\0';
|
|
+ j = 0;
|
|
for (i=0; i<l; i++) {
|
|
- sprintf((char *)x,"%02x",cryptstring[i]);
|
|
- strcat(cryptname,x);
|
|
+ u_char b = cryptstring[i];
|
|
+ cryptname[j++] = hexdigit[(b >> 4) & 15];
|
|
+ cryptname[j++] = hexdigit[b & 15];
|
|
}
|
|
+ cryptname[j] = '\0';
|
|
return cryptname;
|
|
}
|
|
|
|
/*
|
|
- * set high order bits
|
|
+ * Carefully frob the high order bits of s in a way that is both easily
|
|
+ * reversible (see unchksum) and backwards-compatible (at least for 7-bit
|
|
+ * characters).
|
|
*/
|
|
chksum(s,l)
|
|
char *s;
|
|
@@ -229,17 +245,47 @@
|
|
u_char bits[8];
|
|
|
|
acc=0;
|
|
- for (i=0; s[i]!='\0'; i++)
|
|
- acc += s[i]*((i%6)+1);
|
|
+ /* Everything we do here must be reproducible without knowledge of
|
|
+ bit 7 because unchksum won't have that information. Therefore,
|
|
+ only accumulate the lower 7 bits of each char and stop at the
|
|
+ first occurrence of either 0x00 or 0x80. Note that, for inputs
|
|
+ with bit 7 constantly zero, this is equivalent to looking at the
|
|
+ whole string. */
|
|
+ for (i=0; (s[i]&0x7f) != '\0'; i++)
|
|
+ acc += (s[i]&0x7f)*((i%6)+1);
|
|
+ for (; s[i]!='\0'; i++) /* advance i if we stopped at a 0x80 */
|
|
+ ;
|
|
for (i++; i<l; i++) /* fill up the end */
|
|
s[i] = s[i%8];
|
|
for (i=0; i<8; i++)
|
|
bits[i] = (acc<<(i%8))&0x80;
|
|
for (i=0; i<l; i++)
|
|
- s[i] |= bits[i%8];
|
|
+ s[i] ^= bits[i%8];
|
|
}
|
|
|
|
+void
|
|
+unchksum(s,l)
|
|
+ char *s;
|
|
+ long l;
|
|
+{
|
|
+ u_long acc;
|
|
+ int i;
|
|
+ u_char bits[8];
|
|
|
|
+ acc=0;
|
|
+ for (i=0; (s[i]&0x7f) != '\0'; i++)
|
|
+ acc += (s[i]&0x7f)*((i%6)+1);
|
|
+ for (i=0; i<8; i++)
|
|
+ bits[i] = (acc<<(i%8))&0x80;
|
|
+ for (i=0; i<l; i++) {
|
|
+ s[i] ^= bits[i%8];
|
|
+ /* not sure whether this actually buys any performance */
|
|
+ if(s[i]=='\0')
|
|
+ break; /* found end of filename, can stop here */
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
/*
|
|
* decrypt path component
|
|
* leaving "." and ".."
|
|
@@ -279,9 +325,7 @@
|
|
if (l%CFSBLOCK)
|
|
return NULL;
|
|
dodecrypt(key,clearstring,l,10241,zerovect);
|
|
- for (i=0; (clearstring[i]&0x7f) !='\0'; i++)
|
|
- clearstring[i] &= 0x7f;
|
|
- clearstring[i]='\0';
|
|
+ unchksum(clearstring,l);
|
|
return clearstring;
|
|
}
|
|
|
|
@@ -359,11 +403,11 @@
|
|
|
|
|
|
static fh_u roothandle;
|
|
-cfs_fileid rootnode={1,0,"\0\0\0\0\0\0\0\0","/NOWHERE/null",NULL,NULL,0,NULL,NULL};/* fileid=1; should be unique */
|
|
+cfs_fileid rootnode={1,0,{0,0,0,0,0,0,0,0},{'/','N','O','W','H','E','R','E','/','n','u','l','l'},NULL,NULL,0,NULL,NULL};/* fileid=1; should be unique */
|
|
nfstime roottime={0,0};
|
|
|
|
/* Had to change this - someone else was using the same magic number! */
|
|
-/* PLEASE change this value if you're going to re-use this code for
|
|
+/* PLEASE change this value if you're going to re-use this code for */
|
|
/* something else! Otherwise your FS and CFS can't both run... */
|
|
/* static u_char magictest[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; */
|
|
static u_char magictest[8]="M.Blaze";
|
|
@@ -514,10 +558,44 @@
|
|
cfsno(err)
|
|
int err;
|
|
{
|
|
-/* if (err==ENOENT)
|
|
+ switch (err) {
|
|
+ case 0:
|
|
+ return NFS_OK;
|
|
+ case EPERM:
|
|
+ return NFSERR_PERM;
|
|
+ case ENOENT:
|
|
+ return NFSERR_NOENT;
|
|
+ case EIO:
|
|
+ return NFSERR_IO;
|
|
+ case ENXIO:
|
|
+ return NFSERR_NXIO;
|
|
+ case EACCES:
|
|
+ return NFSERR_ACCES;
|
|
+ case EEXIST:
|
|
+ return NFSERR_EXIST;
|
|
+ case ENODEV:
|
|
+ return NFSERR_NODEV;
|
|
+ case ENOTDIR:
|
|
+ return NFSERR_NOTDIR;
|
|
+ case EISDIR:
|
|
+ return NFSERR_ISDIR;
|
|
+ case EFBIG:
|
|
+ return NFSERR_FBIG;
|
|
+ case ENOSPC:
|
|
+ return NFSERR_NOSPC;
|
|
+ case EROFS:
|
|
+ return NFSERR_ROFS;
|
|
+ case ENAMETOOLONG:
|
|
+ return NFSERR_NAMETOOLONG;
|
|
+ case ENOTEMPTY:
|
|
+ return NFSERR_NOTEMPTY;
|
|
+ case EDQUOT:
|
|
+ return NFSERR_DQUOT;
|
|
+ case ESTALE:
|
|
return NFSERR_STALE;
|
|
- else */
|
|
+ default:
|
|
return err;
|
|
+ }
|
|
}
|
|
|
|
|
|
@@ -732,12 +810,17 @@
|
|
{
|
|
char path[NFS_MAXPATHLEN+1];
|
|
struct stat sb;
|
|
+ int l;
|
|
|
|
if (p==NULL) {
|
|
cfserrno=NFSERR_STALE;
|
|
return -2;
|
|
}
|
|
- sprintf(path,"%s/%s",p->name,comp);
|
|
+ l = snprintf(path, sizeof(path), "%s/%s", p->name, comp);
|
|
+ if (l < 0 || l >= sizeof(path)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
if (mkdir(path,0)<0)
|
|
return -1;
|
|
if (stat(path,&sb)<0)
|
|
@@ -766,12 +849,22 @@
|
|
u_long i[2];
|
|
} buf;
|
|
char linkname[NFS_MAXPATHLEN+1];
|
|
+ int l;
|
|
|
|
if (p==NULL) {
|
|
cfserrno=NFSERR_STALE;
|
|
return -2;
|
|
}
|
|
- sprintf(path,"%s/%s",p->name,comp);
|
|
+ l = snprintf(path, sizeof(path), "%s/%s", p->name, comp);
|
|
+ if (l < 0 || l >= sizeof(path)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", p->name, comp);
|
|
+ if (l < 0 || l >= sizeof(linkname)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
|
|
if ((fd=open(path,O_CREAT|O_WRONLY|O_EXCL,0))<0) {
|
|
if (errno==EEXIST) {
|
|
@@ -785,7 +878,6 @@
|
|
if (fstat(fd,&sb)<0)
|
|
return -1;
|
|
close(fd);
|
|
- sprintf(linkname,"%s/.pvect_%s",p->name,comp);
|
|
if (!rs) {
|
|
if (p->ins->highsec) { /* create new pert file iff highsec */
|
|
/* note that there's a race condition here until the simlink */
|
|
@@ -800,8 +892,8 @@
|
|
/* hash. but this doesn't really matter since collisions */
|
|
/* are rare. we could save all 64 bits, but the encoding */
|
|
/* of the link would get messy and large */
|
|
- sprintf(vect,"%02x%02x%02x%02x",
|
|
- buf.ch[0],buf.ch[1],buf.ch[2],buf.ch[3]);
|
|
+ (void)snprintf(vect, sizeof(vect), "%02x%02x%02x%02x",
|
|
+ buf.ch[0], buf.ch[1], buf.ch[2], buf.ch[3]);
|
|
if (symlink(vect,linkname) != 0) {
|
|
strcpy(linkname,"/NOWHERE/null");
|
|
bcopy((char *)zerovect,(char *)vect,8);
|
|
@@ -839,6 +931,7 @@
|
|
char linkname[NFS_MAXPATHLEN+1];
|
|
char vect[NFS_MAXPATHLEN+1];
|
|
struct stat sb;
|
|
+ int l;
|
|
|
|
if (p==NULL) {
|
|
cfserrno=NFSERR_STALE;
|
|
@@ -852,12 +945,20 @@
|
|
}
|
|
if ((p->parent==0) && (!strcmp(comp,"..")))
|
|
return fhrootlook(p->ins->name,h);
|
|
- sprintf(path,"%s/%s",p->name,comp);
|
|
+ l = snprintf(path, sizeof(path), "%s/%s", p->name, comp);
|
|
+ if (l < 0 || l >= sizeof(path)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
if (lstat(path,&sb)<0) {
|
|
return -1; /* just need the inode */
|
|
}
|
|
/* check for a linkfile */
|
|
- sprintf(linkname,"%s/.pvect_%s",p->name,comp);
|
|
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", p->name, comp);
|
|
+ if (l < 0 || l >= sizeof(linkname)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
if (readlink(linkname,vect,9) != 8) {
|
|
bcopy((char *)zerovect,(char *)vect,8);
|
|
strcpy(linkname,"/NOWHERE/null");
|
|
@@ -980,13 +1081,22 @@
|
|
char path[NFS_MAXPATHLEN+1];
|
|
char linkname[NFS_MAXPATHLEN+1];
|
|
int ret;
|
|
+ int l;
|
|
|
|
if (f==NULL) {
|
|
cfserrno=NFSERR_STALE;
|
|
return -2;
|
|
}
|
|
- sprintf(linkname,"%s/.pvect_%s",f->name,s);
|
|
- sprintf(path,"%s/%s",f->name,s);
|
|
+ l = snprintf(path, sizeof(path), "%s/%s", f->name, s);
|
|
+ if (l < 0 || l >= sizeof(path)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", f->name, s);
|
|
+ if (l < 0 || l >= sizeof(linkname)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
/* note that we don't bother to check and see if there's a
|
|
handle allocated for this - just wait for the inode to be
|
|
reclaimed */
|
|
@@ -1001,13 +1111,21 @@
|
|
char *s;
|
|
{
|
|
char path[NFS_MAXPATHLEN+1];
|
|
+ int l;
|
|
+ int err;
|
|
|
|
if (f==NULL) {
|
|
cfserrno=NFSERR_STALE;
|
|
return -2;
|
|
}
|
|
- sprintf(path,"%s/%s",f->name,s);
|
|
- return (rmdir(path));
|
|
+ l = snprintf(path, sizeof(path), "%s/%s", f->name, s);
|
|
+ if (l < 0 || l >= sizeof(path)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
+ if ((err = rmdir(path)) < 0)
|
|
+ cfserrno = cfsno(errno);
|
|
+ return err;
|
|
}
|
|
|
|
DIR *
|
|
@@ -1055,15 +1173,24 @@
|
|
char linkname[NFS_MAXPATHLEN+1];
|
|
char vectval[9];
|
|
int ret;
|
|
+ int l;
|
|
|
|
if ((f==NULL)||(t==NULL)) {
|
|
cfserrno=NFSERR_STALE;
|
|
return -2;
|
|
}
|
|
- sprintf(buf,"%s/%s",t->name,n);
|
|
+ l = snprintf(buf, sizeof(buf), "%s/%s", t->name, n);
|
|
+ if (l < 0 || l >= sizeof(buf)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", t->name, n);
|
|
+ if (l < 0 || l >= sizeof(buf)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
if ((ret=link(f->name,buf))!=0)
|
|
return ret;
|
|
- sprintf(linkname,"%s/.pvect_%s",t->name,n);
|
|
unlink(linkname);
|
|
if (readlink(f->vectname,vectval,9) == 8) {
|
|
vectval[8]='\0';
|
|
@@ -1079,12 +1206,17 @@
|
|
char *t;
|
|
{
|
|
char buf[NFS_MAXPATHLEN+1];
|
|
+ int l;
|
|
|
|
if (f==NULL) {
|
|
cfserrno=NFSERR_STALE;
|
|
return -2;
|
|
}
|
|
- sprintf(buf,"%s/%s",f->name,n);
|
|
+ l = snprintf(buf, sizeof(buf), "%s/%s", f->name, n);
|
|
+ if (l < 0 || l >= sizeof(buf)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
return (symlink(t,buf));
|
|
}
|
|
|
|
@@ -1100,15 +1232,32 @@
|
|
char fblink[NFS_MAXPATHLEN+1];
|
|
char tblink[NFS_MAXPATHLEN+1];
|
|
char vectval[9];
|
|
+ int l;
|
|
|
|
if ((f==NULL)||(t==NULL)) {
|
|
cfserrno=NFSERR_STALE;
|
|
return -2;
|
|
}
|
|
- sprintf(fb,"%s/%s",f->name,fn);
|
|
- sprintf(tb,"%s/%s",t->name,tn);
|
|
- sprintf(fblink,"%s/.pvect_%s",f->name,fn);
|
|
- sprintf(tblink,"%s/.pvect_%s",t->name,tn);
|
|
+ l = snprintf(fb, sizeof(fb), "%s/%s", f->name, fn);
|
|
+ if (l < 0 || l >= sizeof(fb)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
+ l = snprintf(tb, sizeof(tb), "%s/%s", t->name, tn);
|
|
+ if (l < 0 || l >= sizeof(tb)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
+ l = snprintf(fblink, sizeof(fblink), "%s/.pvect_%s", f->name, fn);
|
|
+ if (l < 0 || l >= sizeof(fblink)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
+ l = snprintf(tblink, sizeof(tblink), "%s/.pvect_%s", t->name, tn);
|
|
+ if (l < 0 || l >= sizeof(tblink)) {
|
|
+ cfserrno = NFSERR_NAMETOOLONG;
|
|
+ return -2;
|
|
+ }
|
|
if (rename(fb,tb)==0) { /* now we have to do a lookup */
|
|
unlink(tblink); /* may be a quick race cndtn here */
|
|
if (readlink(fblink,vectval,9)==8) {
|
|
@@ -1160,7 +1309,8 @@
|
|
} else while (cookie<(NINSTANCES+2)) {
|
|
if (instances[cookie-2] != NULL) {
|
|
if (instances[cookie-2]->anon)
|
|
- sprintf(d.d_name,".ANON_%d",cookie-2);
|
|
+ (void)snprintf(d.d_name, sizeof(d.d_name),
|
|
+ ".ANON_%ld", cookie-2);
|
|
else
|
|
strcpy(d.d_name,
|
|
instances[cookie-2]->name);
|