|
Packit |
8f70b4 |
/*
|
|
Packit |
8f70b4 |
* lftp - file transfer program
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* Copyright (c) 1996-2012 by Alexander V. Lukyanov (lav@yars.free.net)
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8f70b4 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8f70b4 |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit |
8f70b4 |
* (at your option) any later version.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
8f70b4 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8f70b4 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8f70b4 |
* GNU General Public License for more details.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
8f70b4 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
8f70b4 |
*/
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Get information about a path (dir or file). If _dir is a file, get
|
|
Packit |
8f70b4 |
* information about that file only. If it's a directory, get information
|
|
Packit |
8f70b4 |
* about files in it. If _showdir is true, act like ls -d: get information
|
|
Packit |
8f70b4 |
* about the directory itself.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* To find out if a path is a directory, attempt to chdir into it. If it
|
|
Packit |
8f70b4 |
* succeeds it's a directory, otherwise it's a file (or there was an error).
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* If the cache knows the file type of _dir, avoid changing directories if
|
|
Packit |
8f70b4 |
* possible, so cached listings don't touch the connection at all.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* List of cases:
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* showdirs off:
|
|
Packit |
8f70b4 |
* 1. We CD into the directory.
|
|
Packit |
8f70b4 |
* a. We get a listing. Success.
|
|
Packit |
8f70b4 |
* b. We fail to get a listing. Fail.
|
|
Packit |
8f70b4 |
* 2. We fail to CD into the path. We fail to CD to the parent. Fail.
|
|
Packit |
8f70b4 |
* 3. We fail to CD into the path. We CD to the parent and fail to get a listing.
|
|
Packit |
8f70b4 |
* Do GetInfoArray case.
|
|
Packit |
8f70b4 |
* 4. We fail to CD into the path. We CD to the parent and get a listing.
|
|
Packit |
8f70b4 |
* a. The path we were looking for is a directory. Fail. (If it's a directory,
|
|
Packit |
8f70b4 |
* we need to get its contents or nothing at all.)
|
|
Packit |
8f70b4 |
* b. The path we were looking for is not a directory. Success.
|
|
Packit |
8f70b4 |
* c. The path we were looking for isn't there. Do GetInfoArray case.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* showdirs on:
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* 1. We CD to the parent and get a listing. The path we were looking for
|
|
Packit |
8f70b4 |
* is there. Success.
|
|
Packit |
8f70b4 |
* 2. We CD to the parent and fail to get a listing.
|
|
Packit |
8f70b4 |
* a. We CD to the path. (Partial success: we know it exists and is a directory.)
|
|
Packit |
8f70b4 |
* b. We fail to CD to the path. Do GetInfoArray case.
|
|
Packit |
8f70b4 |
* 3. We fail to CD to the parent.
|
|
Packit |
8f70b4 |
* a. We CD to the path. The path is a directory. Success (don't try to
|
|
Packit |
8f70b4 |
* get more information.)
|
|
Packit |
8f70b4 |
* b. We fail to CD to the path. Fail.
|
|
Packit |
8f70b4 |
* 4. We CD to the parent and fail to get a listing OR
|
|
Packit |
8f70b4 |
* We CD to the parent and the listing does not contain the path.
|
|
Packit |
8f70b4 |
* a. We CD to the path. The path is a directory. Success (don't try to
|
|
Packit |
8f70b4 |
* get more information.)
|
|
Packit |
8f70b4 |
* b. We fail to CD to the path. Do GetInfoArray case.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* GetInfoArray case:
|
|
Packit |
8f70b4 |
* A. We GetInfoArray in the parent, which tells us something. We
|
|
Packit |
8f70b4 |
* know the path exists, and is not a directory that we have access
|
|
Packit |
8f70b4 |
* to. Success.
|
|
Packit |
8f70b4 |
* B. We GetInfoArray in the parent, which doesn't tell us anything.
|
|
Packit |
8f70b4 |
* We have no evidence the path exists at all. Fail.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* If we fail from something in cache, we don't know why, so turn cache off
|
|
Packit |
8f70b4 |
* and attempt to CD into the path to get an error message.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* All of these cases can operate out of cache, so be sure to test both, as
|
|
Packit |
8f70b4 |
* the code flow is often different. (GetInfoArray never operates out of cache.)
|
|
Packit |
8f70b4 |
*/
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include <config.h>
|
|
Packit |
8f70b4 |
#include <assert.h>
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include "GetFileInfo.h"
|
|
Packit |
8f70b4 |
#include "misc.h"
|
|
Packit |
8f70b4 |
#include "LsCache.h"
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
GetFileInfo::GetFileInfo(const FileAccessRef& a, const char *_dir, bool _showdir)
|
|
Packit |
8f70b4 |
: ListInfo(0,0), session(a), dir(_dir?_dir:""), origdir(a->GetCwd())
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
showdir=_showdir;
|
|
Packit |
8f70b4 |
state=INITIAL;
|
|
Packit |
8f70b4 |
tried_dir=tried_file=tried_info=false;
|
|
Packit |
8f70b4 |
result=0;
|
|
Packit |
8f70b4 |
li=0;
|
|
Packit |
8f70b4 |
from_cache=0;
|
|
Packit |
8f70b4 |
was_directory=false;
|
|
Packit |
8f70b4 |
prepend_path=true;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *bn=basename_ptr(dir);
|
|
Packit |
8f70b4 |
if((bn[0]=='.' && (bn[1]==0 || bn[1]=='/' ||
|
|
Packit |
8f70b4 |
(bn[1]=='.' && (bn[2]==0 || bn[2]=='/'))))
|
|
Packit |
8f70b4 |
|| (bn[0]=='/'))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
// . .. / are directories, don't try them as a file.
|
|
Packit |
8f70b4 |
tried_file=true;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
GetFileInfo::~GetFileInfo() {}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void GetFileInfo::PrepareToDie()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(session)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
session->Close();
|
|
Packit |
8f70b4 |
session->SetCwd(origdir);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int GetFileInfo::Do()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int res;
|
|
Packit |
8f70b4 |
int m=STALL;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(Done())
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
switch(state)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case INITIAL:
|
|
Packit |
8f70b4 |
state=CHANGE_DIR;
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(use_cache)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int is_dir=-1;
|
|
Packit |
8f70b4 |
if(last_char(dir)=='/')
|
|
Packit |
8f70b4 |
is_dir=1;
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
is_dir=FileAccess::cache->IsDirectory(session,dir);
|
|
Packit |
8f70b4 |
switch(is_dir)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case 0:
|
|
Packit |
8f70b4 |
tried_dir = true; /* it's a file */
|
|
Packit |
8f70b4 |
from_cache = true;
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
case 1:
|
|
Packit |
8f70b4 |
if(!showdir)
|
|
Packit |
8f70b4 |
tried_file = true; /* it's a dir */
|
|
Packit |
8f70b4 |
from_cache = true;
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
assert(!tried_dir || !tried_file || !tried_info); /* always do at least one */
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
case CHANGE_DIR:
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(tried_dir && tried_file && tried_info) {
|
|
Packit |
8f70b4 |
/* We tried everything; no luck. Fail. */
|
|
Packit |
8f70b4 |
if(saved_error_text)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SetError(saved_error_text);
|
|
Packit |
8f70b4 |
state=DONE;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* We don't have an error message. We may have done everything
|
|
Packit |
8f70b4 |
* out of cache. */
|
|
Packit |
8f70b4 |
tried_dir=false; // this will get error message.
|
|
Packit |
8f70b4 |
from_cache=false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
session->SetCwd(origdir);
|
|
Packit |
8f70b4 |
const char *cd_path=0;
|
|
Packit |
8f70b4 |
if(!tried_dir && (tried_file || !showdir))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* First, try to treat the path as a directory,
|
|
Packit |
8f70b4 |
* if we are going to show its contents */
|
|
Packit |
8f70b4 |
tried_dir=true;
|
|
Packit |
8f70b4 |
cd_path = dir;
|
|
Packit |
8f70b4 |
path_to_prefix.set(dir);
|
|
Packit |
8f70b4 |
was_directory=true;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
else if(!tried_file)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* Try to treat the path as a file. If showdir is true,
|
|
Packit |
8f70b4 |
* this is done first. */
|
|
Packit |
8f70b4 |
tried_file=true;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Chdir to the parent directory of the path: */
|
|
Packit |
8f70b4 |
session->Chdir(dir, false);
|
|
Packit |
8f70b4 |
cd_path = "..";
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
path_to_prefix.set(dirname(dir));
|
|
Packit |
8f70b4 |
was_directory=false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
else if(!tried_info)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
tried_info=true;
|
|
Packit |
8f70b4 |
/* This is always done after tried_file or a failed tried_dir,
|
|
Packit |
8f70b4 |
* so we should be in the parent, but let's make sure: */
|
|
Packit |
8f70b4 |
session->Chdir(dir, false);
|
|
Packit |
8f70b4 |
session->Chdir("..", false);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
path_to_prefix.set(dirname(dir));
|
|
Packit |
8f70b4 |
was_directory=false;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* We tried both; no luck. Fall back on ARRAY_INFO. */
|
|
Packit |
8f70b4 |
state=GETTING_INFO_ARRAY;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* We still need to Chdir() if we're operating out of cache (that's how you
|
|
Packit |
8f70b4 |
* look up cache entries). However, we don't really want to change the
|
|
Packit |
8f70b4 |
* directory of the session (ie. send a CWD if we're FTP), so set verify to
|
|
Packit |
8f70b4 |
* false if we're operating out of cache. */
|
|
Packit |
8f70b4 |
bool cd_verify = !from_cache;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* We can *not* do this out of cache if 1: dir starts with a ~ and 2: we don't
|
|
Packit |
8f70b4 |
* know the home path.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* Yes we can, usually--we may know the home path in home_auto (FTP), but
|
|
Packit |
8f70b4 |
* GetHome won't return that. We need to do this if we *really* don't know
|
|
Packit |
8f70b4 |
* it. */
|
|
Packit |
8f70b4 |
/* if(dir[0] == '~' && !session->GetHome())
|
|
Packit |
8f70b4 |
cd_verify = true; */
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
session->Chdir(cd_path, cd_verify);
|
|
Packit |
8f70b4 |
state=CHANGING_DIR;
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
case CHANGING_DIR:
|
|
Packit |
8f70b4 |
res=session->Done();
|
|
Packit |
8f70b4 |
if(res==FA::IN_PROGRESS)
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(res<0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* Failed. Save the error, then go back and try to CD again.
|
|
Packit |
8f70b4 |
* Only save the first error, so error texts contain the full
|
|
Packit |
8f70b4 |
* path. */
|
|
Packit |
8f70b4 |
if(!saved_error_text)
|
|
Packit |
8f70b4 |
saved_error_text.set(session->StrError(res));
|
|
Packit |
8f70b4 |
session->Close();
|
|
Packit |
8f70b4 |
if(res==FA::NO_FILE)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* If this is a CWD to the parent, and it failed, we
|
|
Packit |
8f70b4 |
* can't do GetInfoArray. */
|
|
Packit |
8f70b4 |
if(!was_directory)
|
|
Packit |
8f70b4 |
tried_info=true;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
state=CHANGE_DIR;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
SetError(saved_error_text);
|
|
Packit |
8f70b4 |
state=DONE;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
session->Close();
|
|
Packit |
8f70b4 |
if(!from_cache)
|
|
Packit |
8f70b4 |
FileAccess::cache->SetDirectory(session,"",true);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Now that we've connected, we should have the home directory path. Find out
|
|
Packit |
8f70b4 |
* the real name of the path. (We may have something like "~/..".) */
|
|
Packit |
8f70b4 |
if(!verify_fn)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileAccess::Path pwd(session->GetCwd());
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
session->SetCwd(origdir);
|
|
Packit |
8f70b4 |
session->Chdir(dir, false);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
verify_fn.set(basename_ptr(session->GetCwd()));
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* go back */
|
|
Packit |
8f70b4 |
session->SetCwd(pwd);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Special case: looking up "/". Make a phony entry. */
|
|
Packit |
8f70b4 |
if(showdir && !strcmp(verify_fn, "/"))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileInfo *fi = new FileInfo(verify_fn);
|
|
Packit |
8f70b4 |
fi->SetType(fi->DIRECTORY);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
result = new FileSet;
|
|
Packit |
8f70b4 |
result->Add(fi);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
path_to_prefix.set(dirname(dir));
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
state=DONE;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(was_directory && showdir)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* We could chdir to the dir, but we should not get dir listing.
|
|
Packit |
8f70b4 |
* We got here because either we could not get dir listing of
|
|
Packit |
8f70b4 |
* parent directory or the file name was not found in parent
|
|
Packit |
8f70b4 |
* directory index. */
|
|
Packit |
8f70b4 |
FileInfo *fi = new FileInfo(dir);
|
|
Packit |
8f70b4 |
fi->SetType(fi->DIRECTORY);
|
|
Packit |
8f70b4 |
path_to_prefix.set(dirname(dir));
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
result = new FileSet;
|
|
Packit |
8f70b4 |
result->Add(fi);
|
|
Packit |
8f70b4 |
state=DONE;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Get a listing: */
|
|
Packit |
8f70b4 |
li=session->MakeListInfo();
|
|
Packit |
8f70b4 |
if(follow_symlinks) li->FollowSymlinks();
|
|
Packit |
8f70b4 |
li->UseCache(use_cache);
|
|
Packit |
8f70b4 |
li->NoNeed(FileInfo::ALL_INFO); /* clear need */
|
|
Packit |
8f70b4 |
li->Need(need);
|
|
Packit |
8f70b4 |
li->SetExclude(exclude_prefix, exclude);
|
|
Packit |
8f70b4 |
state=GETTING_LIST;
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
case GETTING_LIST:
|
|
Packit |
8f70b4 |
if(li->Error()) {
|
|
Packit |
8f70b4 |
/* If we're listing contents of dirs, and this was listing
|
|
Packit |
8f70b4 |
* a path (as a directory), fail: */
|
|
Packit |
8f70b4 |
if(!showdir && was_directory)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SetError(li->ErrorText());
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(!saved_error_text)
|
|
Packit |
8f70b4 |
saved_error_text.set(li->ErrorText());
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Otherwise, go on to try the next mode. */
|
|
Packit |
8f70b4 |
state=CHANGE_DIR;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(!li->Done())
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
state=DONE;
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Got the list. Steal it from the listinfo: */
|
|
Packit |
8f70b4 |
result=li->GetResult();
|
|
Packit |
8f70b4 |
li=0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* If this was a listing of the basename: */
|
|
Packit |
8f70b4 |
if(!was_directory) {
|
|
Packit |
8f70b4 |
verify_fn.rtrim('/');
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Find the file with our filename: */
|
|
Packit |
8f70b4 |
const FileInfo *file = result->FindByName(verify_fn);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(!file) {
|
|
Packit |
8f70b4 |
/* It doesn't exist, or we have no result (failed). */
|
|
Packit |
8f70b4 |
result=0;
|
|
Packit |
8f70b4 |
tried_file=true;
|
|
Packit |
8f70b4 |
from_cache=false;
|
|
Packit |
8f70b4 |
state=CHANGE_DIR;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* If we're not listing directories as files, and the file is a
|
|
Packit |
8f70b4 |
* directory, we should have been able to Chdir into it to begin
|
|
Packit |
8f70b4 |
* with. We probably got Access Denied. Fail. */
|
|
Packit |
8f70b4 |
if(!showdir && (file->defined&file->TYPE) && file->filetype==FileInfo::DIRECTORY) {
|
|
Packit |
8f70b4 |
result=0;
|
|
Packit |
8f70b4 |
if(saved_error_text)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SetError(saved_error_text);
|
|
Packit |
8f70b4 |
goto done;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
tried_file=true;
|
|
Packit |
8f70b4 |
from_cache=false;
|
|
Packit |
8f70b4 |
state=CHANGE_DIR;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileInfo *copy = new FileInfo(*file);
|
|
Packit |
8f70b4 |
result=new FileSet();
|
|
Packit |
8f70b4 |
result->Add(copy);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
goto done;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
case GETTING_INFO_ARRAY:
|
|
Packit |
8f70b4 |
if(session->IsClosed())
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/*
|
|
Packit |
8f70b4 |
* Try to get requested information with GetInfoArray. This
|
|
Packit |
8f70b4 |
* also serves as a last attempt to see if the file exists--we
|
|
Packit |
8f70b4 |
* only get here if everything else thinks the path doesn't exist.
|
|
Packit |
8f70b4 |
*/
|
|
Packit |
8f70b4 |
FileInfo *fi=new FileInfo(verify_fn);
|
|
Packit |
8f70b4 |
fi->need=need;
|
|
Packit |
8f70b4 |
/* We need to do at least one. */
|
|
Packit |
8f70b4 |
if(!fi->need)
|
|
Packit |
8f70b4 |
fi->need=fi->DATE;
|
|
Packit |
8f70b4 |
get_info.Empty();
|
|
Packit |
8f70b4 |
get_info.Add(fi);
|
|
Packit |
8f70b4 |
session->GetInfoArray(&get_info);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
res=session->Done();
|
|
Packit |
8f70b4 |
if(res==FA::IN_PROGRESS)
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(res < 0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!saved_error_text)
|
|
Packit |
8f70b4 |
saved_error_text.set(session->StrError(res));
|
|
Packit |
8f70b4 |
state=CHANGE_DIR;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
session->Close();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileInfo *fi=get_info[0];
|
|
Packit |
8f70b4 |
if(!fi->HasAny(fi->SIZE|fi->DATE))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* We didn't get any information. The file probably doesn't
|
|
Packit |
8f70b4 |
* exist. Not necessarily: it might have been a directory
|
|
Packit |
8f70b4 |
* that we don't have access to CD into. Some servers will
|
|
Packit |
8f70b4 |
* refuse to give even an MDTM for directories. We could
|
|
Packit |
8f70b4 |
* scan the MDTM and/or SIZE responses for "not a plain file"
|
|
Packit |
8f70b4 |
* for some servers (proftpd). */
|
|
Packit |
8f70b4 |
state=CHANGE_DIR;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* We got at least one, so the file exists. Return what we know. */
|
|
Packit |
8f70b4 |
was_directory = false;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
result = new FileSet;
|
|
Packit |
8f70b4 |
result->Add(new FileInfo(*fi));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
state=DONE;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
done:
|
|
Packit |
8f70b4 |
case DONE:
|
|
Packit |
8f70b4 |
if(!done)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(result && showdir && result->get_fnum()>0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileInfo *f = (*result)[0];
|
|
Packit |
8f70b4 |
/* Make sure the filename is what was requested (ie ".."). */
|
|
Packit |
8f70b4 |
const char *fn = basename_ptr(dir);
|
|
Packit |
8f70b4 |
f->SetName(*fn? fn:".");
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* If we're in show_dir mode, was_directory will always be false;
|
|
Packit |
8f70b4 |
* set it to whether the single file is actually a directory or not. */
|
|
Packit |
8f70b4 |
if(f->defined&f->TYPE)
|
|
Packit |
8f70b4 |
was_directory = (f->filetype == f->DIRECTORY);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(result && prepend_path)
|
|
Packit |
8f70b4 |
result->PrependPath(path_to_prefix);
|
|
Packit |
8f70b4 |
done=true;
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
abort();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *GetFileInfo::Status()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(Done())
|
|
Packit |
8f70b4 |
return "";
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(li && !li->Done()) return li->Status();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(session->IsOpen())
|
|
Packit |
8f70b4 |
return session->CurrentStatus();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
return "";
|
|
Packit |
8f70b4 |
}
|