* direntry.c (vfs_s_add_dots): Remove. Fix all callers.
(vfs_s_free_inode): Remove support for "." and ".." entries. * ftpfs.c (dir_load): Likewise. Support for "." and ".." entries was a hack that could make the cache non-traversible from inodes to the root and cause infinite loop in vfs_s_fullpath(). Reported by Frdric L. W. Meunier <lists1@pervalidus.net>
Этот коммит содержится в:
родитель
290426d17a
Коммит
511321bcfd
@ -1,3 +1,13 @@
|
|||||||
|
2003-10-26 Pavel Roskin <proski@gnu.org>
|
||||||
|
|
||||||
|
* direntry.c (vfs_s_add_dots): Remove. Fix all callers.
|
||||||
|
(vfs_s_free_inode): Remove support for "." and ".." entries.
|
||||||
|
* ftpfs.c (dir_load): Likewise.
|
||||||
|
Support for "." and ".." entries was a hack that could make the
|
||||||
|
cache non-traversible from inodes to the root and cause infinite
|
||||||
|
loop in vfs_s_fullpath().
|
||||||
|
Reported by Frщdщric L. W. Meunier <lists1@pervalidus.net>
|
||||||
|
|
||||||
2003-10-25 Pavel Roskin <proski@gnu.org>
|
2003-10-25 Pavel Roskin <proski@gnu.org>
|
||||||
|
|
||||||
* tar.h: Merge into tar.c, as it doesn't provide any external
|
* tar.h: Merge into tar.c, as it doesn't provide any external
|
||||||
|
@ -168,7 +168,6 @@ static int cpio_open_cpio_file(struct vfs_class *me, struct vfs_s_super *super,
|
|||||||
root->st.st_nlink++;
|
root->st.st_nlink++;
|
||||||
root->st.st_dev = MEDATA->rdev++;
|
root->st.st_dev = MEDATA->rdev++;
|
||||||
|
|
||||||
vfs_s_add_dots(me, root, NULL);
|
|
||||||
super->root = root;
|
super->root = root;
|
||||||
|
|
||||||
CPIO_SEEK_SET(super, 0);
|
CPIO_SEEK_SET(super, 0);
|
||||||
@ -479,9 +478,6 @@ static int cpio_create_entry(struct vfs_class *me, struct vfs_s_super *super, st
|
|||||||
entry = vfs_s_new_entry(me, tn, inode);
|
entry = vfs_s_new_entry(me, tn, inode);
|
||||||
vfs_s_insert_entry(me, root, entry);
|
vfs_s_insert_entry(me, root, entry);
|
||||||
|
|
||||||
if(S_ISDIR(stat->st_mode))
|
|
||||||
vfs_s_add_dots(me, inode, root);
|
|
||||||
|
|
||||||
if(S_ISLNK(stat->st_mode)) {
|
if(S_ISLNK(stat->st_mode)) {
|
||||||
inode->linkname = g_malloc(stat->st_size + 1);
|
inode->linkname = g_malloc(stat->st_size + 1);
|
||||||
if(mc_read(super->u.arch.fd, inode->linkname, stat->st_size) < stat->st_size) {
|
if(mc_read(super->u.arch.fd, inode->linkname, stat->st_size) < stat->st_size) {
|
||||||
|
@ -103,7 +103,6 @@ vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
|
|||||||
void
|
void
|
||||||
vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
|
vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
|
||||||
{
|
{
|
||||||
int is_dot = 0;
|
|
||||||
if (ent->prevp){ /* It is possible that we are deleting freshly created entry */
|
if (ent->prevp){ /* It is possible that we are deleting freshly created entry */
|
||||||
*ent->prevp = ent->next;
|
*ent->prevp = ent->next;
|
||||||
if (ent->next)
|
if (ent->next)
|
||||||
@ -111,12 +110,11 @@ vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ent->name){
|
if (ent->name){
|
||||||
is_dot = (!strcmp (ent->name, ".")) || (!strcmp (ent->name, ".."));
|
|
||||||
g_free (ent->name);
|
g_free (ent->name);
|
||||||
ent->name = NULL;
|
ent->name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_dot && ent->ino){
|
if (ent->ino){
|
||||||
ent->ino->ent = NULL;
|
ent->ino->ent = NULL;
|
||||||
vfs_s_free_inode (me, ent->ino);
|
vfs_s_free_inode (me, ent->ino);
|
||||||
ent->ino = NULL;
|
ent->ino = NULL;
|
||||||
@ -163,21 +161,6 @@ vfs_s_default_stat (struct vfs_class *me, mode_t mode)
|
|||||||
return &st;
|
return &st;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
vfs_s_add_dots (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_inode *parent)
|
|
||||||
{
|
|
||||||
struct vfs_s_entry *dot, *dotdot;
|
|
||||||
|
|
||||||
if (!parent)
|
|
||||||
parent = dir;
|
|
||||||
dot = vfs_s_new_entry (me, ".", dir);
|
|
||||||
dotdot = vfs_s_new_entry (me, "..", parent);
|
|
||||||
vfs_s_insert_entry (me, dir, dot);
|
|
||||||
vfs_s_insert_entry (me, dir, dotdot);
|
|
||||||
dir->st.st_nlink--;
|
|
||||||
parent->st.st_nlink--; /* We do not count "." and ".." into nlinks */
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vfs_s_entry *
|
struct vfs_s_entry *
|
||||||
vfs_s_generate_entry (struct vfs_class *me, char *name, struct vfs_s_inode *parent, mode_t mode)
|
vfs_s_generate_entry (struct vfs_class *me, char *name, struct vfs_s_inode *parent, mode_t mode)
|
||||||
{
|
{
|
||||||
@ -186,8 +169,6 @@ vfs_s_generate_entry (struct vfs_class *me, char *name, struct vfs_s_inode *pare
|
|||||||
|
|
||||||
st = vfs_s_default_stat (me, mode);
|
st = vfs_s_default_stat (me, mode);
|
||||||
inode = vfs_s_new_inode (me, parent->super, st);
|
inode = vfs_s_new_inode (me, parent->super, st);
|
||||||
if (S_ISDIR (mode))
|
|
||||||
vfs_s_add_dots (me, inode, parent);
|
|
||||||
|
|
||||||
return vfs_s_new_entry (me, name, inode);
|
return vfs_s_new_entry (me, name, inode);
|
||||||
}
|
}
|
||||||
|
118
vfs/ftpfs.c
118
vfs/ftpfs.c
@ -1174,47 +1174,49 @@ dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
|
|||||||
struct vfs_s_entry *ent;
|
struct vfs_s_entry *ent;
|
||||||
struct vfs_s_super *super = dir->super;
|
struct vfs_s_super *super = dir->super;
|
||||||
int sock, num_entries = 0;
|
int sock, num_entries = 0;
|
||||||
#ifdef FIXME_LATER
|
|
||||||
int has_symlinks = 0;
|
|
||||||
#endif
|
|
||||||
char buffer[BUF_8K];
|
char buffer[BUF_8K];
|
||||||
int cd_first;
|
int cd_first;
|
||||||
|
|
||||||
cd_first = ftpfs_first_cd_then_ls || (SUP.strict == RFC_STRICT)
|
cd_first = ftpfs_first_cd_then_ls || (SUP.strict == RFC_STRICT)
|
||||||
|| (strchr (remote_path, ' ') != NULL);
|
|| (strchr (remote_path, ' ') != NULL);
|
||||||
|
|
||||||
again:
|
again:
|
||||||
print_vfs_message(_("ftpfs: Reading FTP directory %s... %s%s"), remote_path,
|
print_vfs_message (_("ftpfs: Reading FTP directory %s... %s%s"),
|
||||||
SUP.strict == RFC_STRICT ? _("(strict rfc959)") : "",
|
remote_path,
|
||||||
cd_first ? _("(chdir first)") : "");
|
SUP.strict ==
|
||||||
|
RFC_STRICT ? _("(strict rfc959)") : "",
|
||||||
|
cd_first ? _("(chdir first)") : "");
|
||||||
|
|
||||||
if (cd_first) {
|
if (cd_first) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = translate_path (me, super, remote_path);
|
p = translate_path (me, super, remote_path);
|
||||||
|
|
||||||
if (ftpfs_chdir_internal (me, super, p) != COMPLETE) {
|
if (ftpfs_chdir_internal (me, super, p) != COMPLETE) {
|
||||||
g_free (p);
|
g_free (p);
|
||||||
my_errno = ENOENT;
|
my_errno = ENOENT;
|
||||||
print_vfs_message(_("ftpfs: CWD failed."));
|
print_vfs_message (_("ftpfs: CWD failed."));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
g_free (p);
|
g_free (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
gettimeofday(&dir->timestamp, NULL);
|
gettimeofday (&dir->timestamp, NULL);
|
||||||
dir->timestamp.tv_sec += ftpfs_directory_timeout;
|
dir->timestamp.tv_sec += ftpfs_directory_timeout;
|
||||||
|
|
||||||
if (SUP.strict == RFC_STRICT)
|
if (SUP.strict == RFC_STRICT)
|
||||||
sock = open_data_connection (me, super, "LIST", 0, TYPE_ASCII, 0);
|
sock = open_data_connection (me, super, "LIST", 0, TYPE_ASCII, 0);
|
||||||
else if (cd_first)
|
else if (cd_first)
|
||||||
/* Dirty hack to avoid autoprepending / to . */
|
/* Dirty hack to avoid autoprepending / to . */
|
||||||
/* Wu-ftpd produces strange output for '/' if 'LIST -la .' used */
|
/* Wu-ftpd produces strange output for '/' if 'LIST -la .' used */
|
||||||
sock = open_data_connection (me, super, "LIST -la", 0, TYPE_ASCII, 0);
|
sock =
|
||||||
|
open_data_connection (me, super, "LIST -la", 0, TYPE_ASCII, 0);
|
||||||
else {
|
else {
|
||||||
/* Trailing "/." is necessary if remote_path is a symlink */
|
/* Trailing "/." is necessary if remote_path is a symlink */
|
||||||
char *path = concat_dir_and_file (remote_path, ".");
|
char *path = concat_dir_and_file (remote_path, ".");
|
||||||
sock = open_data_connection (me, super, "LIST -la", path, TYPE_ASCII, 0);
|
sock =
|
||||||
|
open_data_connection (me, super, "LIST -la", path, TYPE_ASCII,
|
||||||
|
0);
|
||||||
g_free (path);
|
g_free (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1224,104 +1226,64 @@ again:
|
|||||||
/* Clear the interrupt flag */
|
/* Clear the interrupt flag */
|
||||||
enable_interrupt_key ();
|
enable_interrupt_key ();
|
||||||
|
|
||||||
#if 1
|
|
||||||
{
|
|
||||||
/* added 20001006 by gisburn
|
|
||||||
* add dots '.' and '..'. This must be _executed_ before scanning the dir as the
|
|
||||||
* code below may jump directly into error handling code (without executing
|
|
||||||
* remaining code). And C doesn't have try {...} finally {}; :-)
|
|
||||||
*/
|
|
||||||
struct vfs_s_inode *parent = dir->ent->dir;
|
|
||||||
|
|
||||||
if( parent==NULL )
|
|
||||||
parent = dir;
|
|
||||||
|
|
||||||
ent = vfs_s_generate_entry(me, ".", dir, 0);
|
|
||||||
ent->ino->st=dir->st;
|
|
||||||
num_entries++;
|
|
||||||
vfs_s_insert_entry(me, dir, ent);
|
|
||||||
|
|
||||||
ent = vfs_s_generate_entry(me, "..", parent, 0);
|
|
||||||
ent->ino->st=parent->st;
|
|
||||||
num_entries++;
|
|
||||||
vfs_s_insert_entry(me, dir, ent);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int i;
|
int i;
|
||||||
int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), sock);
|
int res =
|
||||||
|
vfs_s_get_line_interruptible (me, buffer, sizeof (buffer),
|
||||||
|
sock);
|
||||||
if (!res)
|
if (!res)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (res == EINTR) {
|
if (res == EINTR) {
|
||||||
me->verrno = ECONNRESET;
|
me->verrno = ECONNRESET;
|
||||||
close (sock);
|
close (sock);
|
||||||
disable_interrupt_key();
|
disable_interrupt_key ();
|
||||||
get_reply(me, SUP.sock, NULL, 0);
|
get_reply (me, SUP.sock, NULL, 0);
|
||||||
print_vfs_message (_("%s: failure"), me->name);
|
print_vfs_message (_("%s: failure"), me->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MEDATA->logfile){
|
if (MEDATA->logfile) {
|
||||||
fputs (buffer, MEDATA->logfile);
|
fputs (buffer, MEDATA->logfile);
|
||||||
fputs ("\n", MEDATA->logfile);
|
fputs ("\n", MEDATA->logfile);
|
||||||
fflush (MEDATA->logfile);
|
fflush (MEDATA->logfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
ent = vfs_s_generate_entry(me, NULL, dir, 0);
|
ent = vfs_s_generate_entry (me, NULL, dir, 0);
|
||||||
i = ent->ino->st.st_nlink;
|
i = ent->ino->st.st_nlink;
|
||||||
if (!vfs_parse_ls_lga (buffer, &ent->ino->st, &ent->name, &ent->ino->linkname)) {
|
if (!vfs_parse_ls_lga
|
||||||
|
(buffer, &ent->ino->st, &ent->name, &ent->ino->linkname)) {
|
||||||
vfs_s_free_entry (me, ent);
|
vfs_s_free_entry (me, ent);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ent->ino->st.st_nlink = i; /* Ouch, we need to preserve our counts :-( */
|
ent->ino->st.st_nlink = i; /* Ouch, we need to preserve our counts :-( */
|
||||||
num_entries++;
|
num_entries++;
|
||||||
if ((!strcmp(ent->name, ".")) || (!strcmp (ent->name, ".."))) {
|
vfs_s_insert_entry (me, dir, ent);
|
||||||
g_free (ent->name);
|
|
||||||
ent->name = NULL; /* Ouch, vfs_s_free_entry "knows" about . and .. being special :-( */
|
|
||||||
vfs_s_free_entry (me, ent);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfs_s_insert_entry(me, dir, ent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vfs_s_add_dots(me, dir, NULL);
|
close (sock);
|
||||||
FIXME This really should be here; but we need to provide correct parent.
|
|
||||||
Disabled for now, please fix it. Pavel
|
|
||||||
*/
|
|
||||||
close(sock);
|
|
||||||
me->verrno = E_REMOTE;
|
me->verrno = E_REMOTE;
|
||||||
if ((get_reply (me, SUP.sock, NULL, 0) != COMPLETE) || !num_entries)
|
if ((get_reply (me, SUP.sock, NULL, 0) != COMPLETE) || !num_entries)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
if (SUP.strict == RFC_AUTODETECT)
|
if (SUP.strict == RFC_AUTODETECT)
|
||||||
SUP.strict = RFC_DARING;
|
SUP.strict = RFC_DARING;
|
||||||
|
|
||||||
#ifdef FIXME_LATER
|
|
||||||
if (has_symlinks) {
|
|
||||||
if (resolve_symlinks)
|
|
||||||
resolve_symlink(me, super, dcache);
|
|
||||||
else
|
|
||||||
dcache->symlink_status = FTPFS_UNRESOLVED_SYMLINKS;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
print_vfs_message (_("%s: done."), me->name);
|
print_vfs_message (_("%s: done."), me->name);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fallback:
|
fallback:
|
||||||
if (SUP.strict == RFC_AUTODETECT) {
|
if (SUP.strict == RFC_AUTODETECT) {
|
||||||
/* It's our first attempt to get a directory listing from this
|
/* It's our first attempt to get a directory listing from this
|
||||||
server (UNIX style LIST command) */
|
server (UNIX style LIST command) */
|
||||||
SUP.strict = RFC_STRICT;
|
SUP.strict = RFC_STRICT;
|
||||||
/* I hate goto, but recursive call needs another 8K on stack */
|
/* I hate goto, but recursive call needs another 8K on stack */
|
||||||
/* return dir_load (me, dir, remote_path); */
|
/* return dir_load (me, dir, remote_path); */
|
||||||
cd_first = 1;
|
cd_first = 1;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
print_vfs_message(_("ftpfs: failed; nowhere to fallback to"));
|
print_vfs_message (_("ftpfs: failed; nowhere to fallback to"));
|
||||||
ERRNOR(-1, EACCES);
|
ERRNOR (-1, EACCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
License along with this program; if not, write to the Free Software
|
License along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
/* Namespace: vfs_tarfs_ops */
|
/* Namespace: init_tarfs */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -242,7 +242,6 @@ static int tar_open_archive (struct vfs_class *me, char *name, struct vfs_s_supe
|
|||||||
root->st.st_nlink++;
|
root->st.st_nlink++;
|
||||||
root->st.st_dev = MEDATA->rdev++;
|
root->st.st_dev = MEDATA->rdev++;
|
||||||
|
|
||||||
vfs_s_add_dots (me, root, NULL);
|
|
||||||
archive->root = root;
|
archive->root = root;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -161,8 +161,6 @@ void vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir,
|
|||||||
struct vfs_s_entry *ent);
|
struct vfs_s_entry *ent);
|
||||||
struct stat *vfs_s_default_stat (struct vfs_class *me, mode_t mode);
|
struct stat *vfs_s_default_stat (struct vfs_class *me, mode_t mode);
|
||||||
|
|
||||||
void vfs_s_add_dots (struct vfs_class *me, struct vfs_s_inode *dir,
|
|
||||||
struct vfs_s_inode *parent);
|
|
||||||
struct vfs_s_entry *vfs_s_generate_entry (struct vfs_class *me, char *name,
|
struct vfs_s_entry *vfs_s_generate_entry (struct vfs_class *me, char *name,
|
||||||
struct vfs_s_inode *parent,
|
struct vfs_s_inode *parent,
|
||||||
mode_t mode);
|
mode_t mode);
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user