[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FDclone-users:00311] Re: cannot enter ./ in an archive
- Subject: [FDclone-users:00311] Re: cannot enter ./ in an archive
- From: Takashi SHIRAI <shirai@unixusers.net>
- Date: Fri, 16 Jul 2004 19:22:46 +0900
しらいです。
In Message-Id <86brihclsp.knu@iDaemons.org>
"Akinori MUSHA" <knu@iDaemons.org>さんwrites:
> FDclone 2.05g で、 ./foo のようなパス名のファイルが入った
> tarball をブラウズしたとき、「.」のところで Enter を押しても
> その下に移動できません。2.05f までは問題ありませんでした。
ああ、そういうケースがありましたね。
例えば「tar cf foo.tar .」なんてすると archive の中に不要
な「.」という entry が出来てしまい、archive browser で「.」
に移動しても中が空で無意味なので、「.」へは移動出来ないよう
にしようとしたのでした。
でも「./foo」の場合は無意味でも「.」に移動しないと「foo」
が見えなくなってしまいますよね。どうしましょうか。
そもそも「.」は「./foo」のような pathname の時でも不要なの
で、pathname の取得の際に無駄な「.」や「..」は削除してしまう
realpath() 的な処理の方がいいかも知れません。
それだと、ついでに「../foo」とか「foo/../bar」とか混在する
場合にも対処出来るようになりますし。
一応仕様としては、
./foo -> foo
foo/./bar -> foo/bar
foo/../bar -> bar
/../foo -> /foo
../foo -> ../foo
のように正規化するルールにしてみました。
最後のケースだけがちょっと特殊で、「..」への移動が archive
browser の終了ではなくて、疑似的な directory「..」への移動に
なってしまいますので、混乱を生じさせてしまうかも知れません。
この実装では、こういうケースでは明示的に「..」への移動を選
択した場合と「Bs」で戻る場合とで挙動を敢えて分けてみましたが、
使い勝手はどうでしょうね?
尤も、こういった entry の入った archive file なんて滅多に
存在しないんでしょうけど。
---- Cut Here ----
diff -u ../old/FD-2.05g/archive.c ./archive.c
--- ../old/FD-2.05g/archive.c Wed Jul 7 00:00:00 2004
+++ ./archive.c Fri Jul 16 18:51:51 2004
@@ -163,13 +163,10 @@
static VOID NEAR poparchdupl __P_((VOID_A));
#endif
static int NEAR readattr __P_((namelist *, char *));
+static VOID NEAR archrealpath __P_((char *, char *));
+static char *NEAR readfname __P_((char *, int));
#if FD >= 2
static char *NEAR checkspace __P_((char *, int *));
-# ifdef _NOKANJIFCONV
-#define readfname strndup2
-# else
-static char *NEAR readfname __P_((char *, int));
-# endif
static int NEAR readfileent __P_((namelist *, char *, char *, int));
#else /* FD < 2 */
static int NEAR countfield __P_((char *, u_char [], int, int *));
@@ -188,6 +185,7 @@
static VOID NEAR unpackerror __P_((VOID_A));
static int NEAR readarchive __P_((char *, launchtable *, int));
static char *NEAR searcharcdir __P_((char *, int));
+static char *NEAR archoutdir __P_((VOID_A));
static int NEAR undertmp __P_((char *));
#ifdef _NODOSDRIVE
static char *NEAR genfullpath __P_((char *, char *, char *));
@@ -457,9 +455,7 @@
int i, c, len;
u_int mode;
- if (!*buf) return(0);
len = strlen(buf);
-
if (len < 9) {
mode = (tmp -> st_mode & S_IFMT) | S_IREAD_ALL | S_IWRITE_ALL;
while (--len >= 0) {
@@ -547,7 +543,65 @@
}
tmp -> st_mode = mode;
- return(1);
+ return(len);
+}
+
+static VOID NEAR archrealpath(path, resolved)
+char *path, *resolved;
+{
+ char *cp;
+
+ if (!*path || !strcmp(path, ".")) return;
+ else if ((cp = strdelim(path, 0))) {
+ *cp = '\0';
+ archrealpath(path, resolved);
+ *(cp++) = _SC_;
+ archrealpath(cp, resolved);
+ return;
+ }
+
+ if (!strcmp(path, "..") && *resolved) {
+ if (!(cp = strrdelim(resolved, 0))) cp = resolved;
+ else if (cp == resolved) cp++;
+ *cp = '\0';
+ }
+ else {
+ cp = strcatdelim(resolved);
+ strcpy(cp, path);
+ }
+}
+
+static char *NEAR readfname(s, len)
+char *s;
+int len;
+{
+ char *cp, *tmp;
+ int c;
+
+ cp = malloc2(len + 1);
+ c = s[len];
+ s[len] = '\0';
+ tmp = s;
+ if (*tmp != _SC_) *cp = '\0';
+ else {
+ strcpy(cp, _SS_);
+ tmp++;
+ }
+ archrealpath(tmp, cp);
+ s[len] = c;
+
+ if (len && !*cp) {
+ free(cp);
+ return(NULL);
+ }
+
+#ifdef _NOKANJIFCONV
+ return(cp);
+#else
+ tmp = newkanjiconv(cp, fnamekcode, DEFCODE, L_FNAME);
+ if (tmp != cp) free(cp);
+ return(tmp);
+#endif
}
#if FD >= 2
@@ -572,20 +626,6 @@
return(strndup2(s, len));
}
-# ifndef _NOKANJIFCONV
-static char *NEAR readfname(s, len)
-char *s;
-int len;
-{
- char *cp, *tmp;
-
- cp = strndup2(s, len);
- tmp = newkanjiconv(cp, fnamekcode, DEFCODE, L_FNAME);
- if (tmp != cp) free(cp);
- return(tmp);
-}
-# endif /* !_NOKANJIFCONV */
-
static int NEAR readfileent(tmp, line, form, skip)
namelist *tmp;
char *line, *form;
@@ -813,6 +853,10 @@
}
if (tmp -> name) free(tmp -> name);
tmp -> name = readfname(rawbuf, i);
+ if (!(tmp -> name)) {
+ hit = -2;
+ break;
+ }
hit++;
err = 0;
# ifndef NOSYMLINK
@@ -836,21 +880,24 @@
err = 0;
break;
default:
- free(buf);
- free(rawbuf);
- if (tmp -> name) free(tmp -> name);
+ hit = -1;
+ break;
+ }
+
+ free(buf);
+ free(rawbuf);
+
+ if (hit < 0) {
+ if (tmp -> name) free(tmp -> name);
# ifndef NOSYMLINK
- if (tmp -> linkname) free(tmp -> linkname);
+ if (tmp -> linkname) free(tmp -> linkname);
# endif
- return(-1);
-/*NOTREACHED*/
- break;
+ return(hit);
}
+
if (!hit) score += 5;
else if (hit <= err2) score += err2;
score += err;
- free(buf);
- free(rawbuf);
line += len;
if (!ch) while (iswhitespace(*line)) line++;
}
@@ -1021,10 +1068,13 @@
if (i > 0) buf[i] = '\0';
tmp -> st_mode |= S_IFDIR;
}
- tmp -> name = strdup2(buf);
+ if (!(tmp -> name = readfname(buf, strlen(buf)))) {
+ free(buf);
+ return(-1);
+ }
getfield(buf, line, skip, list, F_MODE);
- if (!readattr(tmp, buf)) tmp -> st_mode = 0644;
+ readattr(tmp, buf);
if (!(tmp -> st_mode & S_IFMT)) tmp -> st_mode |= S_IFREG;
if (s_isdir(tmp)) tmp -> flags |= F_ISDIR;
else if (s_islnk(tmp)) tmp -> flags |= F_ISLNK;
@@ -1241,41 +1291,44 @@
static char *NEAR pseudodir(namep)
namelist *namep;
{
- char *cp, *tmp;
+ char *cp, *next;
int i, len;
u_short ent;
- cp = namep -> name;
- while ((tmp = strdelim(cp, 0))) {
- while (*(tmp + 1) == _SC_) tmp++;
- if (!*(tmp + 1)) break;
- len = tmp - (namep -> name);
+ for (cp = namep -> name; (next = strdelim(cp, 0)); cp = next + 1) {
+ while (*(next + 1) == _SC_) next++;
+ if (!*(next + 1)) break;
+ len = next - namep -> name;
if (!len) len++;
- for (i = 0; i < maxfile; i++) {
+
+ /* omit filelist[0] as pseudo ".." */
+ for (i = 1; i < maxfile; i++) {
if (isdir(&(filelist[i]))
&& len == dirmatchlen(filelist[i].name, namep -> name))
break;
}
+
if (i >= maxfile) return(strndup2(namep -> name, len));
if (strncmp(filelist[i].name, namep -> name, len)) {
filelist[i].name = realloc2(filelist[i].name, len + 1);
strncpy2(filelist[i].name, namep -> name, len);
}
- cp = tmp + 1;
}
+
if (isdir(namep) && !isdotdir(namep -> name))
for (i = 0; i < maxfile; i++) {
if (isdir(&(filelist[i]))
&& !dircmp(filelist[i].name, namep -> name)) {
- tmp = filelist[i].name;
+ cp = filelist[i].name;
ent = filelist[i].ent;
memcpy((char *)&(filelist[i]), (char *)namep,
sizeof(namelist));
- filelist[i].name = tmp;
+ filelist[i].name = cp;
filelist[i].ent = ent;
return(NULL);
}
}
+
return(namep -> name);
}
@@ -1492,6 +1545,7 @@
free(cp);
if (score < 0) {
+ if (score < -1) break;
if (formlist[nf]) {
free(formlist[nf]);
for (i = nf; formlist[i]; i++)
@@ -1715,6 +1769,7 @@
char *cp, *tmp;
int i, j, n, len;
+ /* omit filelist[0] as pseudo ".." */
for (i = 1; i < maxarcf; i++) {
if (!*archivedir) len = 0;
else if (!(len = dirmatchlen(archivedir, arcflist[i].name)))
@@ -1791,6 +1846,29 @@
return(NULL);
}
+static char *NEAR archoutdir(VOID_A)
+{
+ char *cp, *file;
+
+ if (!*archivedir) return((char *)-1);
+ if (!(file = searcharcdir(NULL, 0))) return(NULL);
+
+ cp = file + (int)strlen(file) - 1;
+ while (cp > file && *cp == _SC_) cp--;
+#ifdef BSPATHDELIM
+ if (onkanji1(file, cp - file)) cp++;
+#endif
+ cp = strrdelim2(file, cp);
+ if (!cp) *archivedir = '\0';
+ else {
+ if (cp == file) strcpy(archivedir, _SS_);
+ else strncpy2(archivedir, file, cp - file);
+ file = cp + 1;
+ }
+
+ return(file);
+}
+
char *archchdir(path)
char *path;
{
@@ -1799,11 +1877,11 @@
if (findpattern) free(findpattern);
findpattern = NULL;
- if (!path || !*path) path = "..";
#ifndef _NOBROWSE
if (browselist) {
int i, n, dupfilepos;
+ if (!path || !*path) path = "..";
if ((cp = strdelim(path, 0))) {
for (i = 1; cp[i]; i++) if (cp[i] != _SC_) break;
if (cp[i]) {
@@ -1846,43 +1924,28 @@
return("..");
}
#endif /* !_NOBROWSE */
+
+ if (!path) return(archoutdir());
+ if (!*path) path = "..";
strcpy(duparcdir, archivedir);
do {
if (*path == _SC_) len = 1;
else if ((cp = strdelim(path, 0))) len = cp - path;
else len = strlen(path);
- if (len == 1 && *path == '.') file = "..";
- else if (len != 2 || strncmp(path, "..", len)) {
- if (!searcharcdir(path, len)) {
- strcpy(archivedir, duparcdir);
- errno = ENOENT;
- return(NULL);
- }
+ if (searcharcdir(path, len)) {
if (*(cp = archivedir)) cp = strcatdelim(archivedir);
strncpy2(cp, path, len);
file = "..";
}
- else if (!*archivedir) return((char *)-1);
- else {
- if (!(file = searcharcdir(NULL, 0))) {
- strcpy(archivedir, duparcdir);
- errno = ENOENT;
- return(NULL);
- }
- cp = file + (int)strlen(file) - 1;
- while (cp > file && *cp == _SC_) cp--;
-#ifdef BSPATHDELIM
- if (onkanji1(file, cp - file)) cp++;
-#endif
- cp = strrdelim2(file, cp);
- if (!cp) *archivedir = '\0';
- else {
- if (cp == file) strcpy(archivedir, _SS_);
- else strncpy2(archivedir, file, cp - file);
- file = cp + 1;
- }
+ else if (len != 2 || strncmp(path, "..", len)
+ || !(file = archoutdir())) {
+ strcpy(archivedir, duparcdir);
+ errno = ENOENT;
+ return(NULL);
}
+ else if (file == (char *)-1) break;
+
path += len;
while (*path == _SC_) path++;
} while (*path);
diff -u ../old/FD-2.05g/browse.c ./browse.c
--- ../old/FD-2.05g/browse.c Wed Jul 7 00:00:00 2004
+++ ./browse.c Fri Jul 16 18:53:30 2004
@@ -1657,7 +1657,7 @@
else if (no > 4) {
char *tmp;
- tmp = (filepos < 0) ? ".." : filelist[filepos].name;
+ tmp = (filepos >= 0) ? filelist[filepos].name : NULL;
if (!(cp = archchdir(tmp))) {
warning(-1, tmp);
strcpy(file, tmp);
---- Cut Here ----
しらい たかし