|
Packit |
8f70b4 |
/*
|
|
Packit |
8f70b4 |
* lftp - file transfer program
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* Copyright (c) 1996-2016 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 |
#ifndef FILEACCESS_H
|
|
Packit |
8f70b4 |
#define FILEACCESS_H
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include <sys/types.h>
|
|
Packit |
8f70b4 |
#include <time.h>
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include "SMTask.h"
|
|
Packit |
8f70b4 |
#include "trio.h"
|
|
Packit |
8f70b4 |
#include "xstring.h"
|
|
Packit |
8f70b4 |
#include "ResMgr.h"
|
|
Packit |
8f70b4 |
#include "FileSet.h"
|
|
Packit |
8f70b4 |
#include "ArgV.h"
|
|
Packit |
8f70b4 |
#include "ProtoLog.h"
|
|
Packit |
8f70b4 |
#include "xlist.h"
|
|
Packit |
8f70b4 |
#include "xmap.h"
|
|
Packit |
8f70b4 |
#include "Timer.h"
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#define FILE_END ((off_t)-1L)
|
|
Packit |
8f70b4 |
#define UNKNOWN_POS ((off_t)-1L)
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
class ListInfo;
|
|
Packit |
8f70b4 |
class Glob;
|
|
Packit |
8f70b4 |
class NoGlob;
|
|
Packit |
8f70b4 |
class DirList;
|
|
Packit |
8f70b4 |
class FileAccessRef;
|
|
Packit |
8f70b4 |
class Buffer;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
class FileAccess : public SMTask, public ResClient, protected ProtoLog
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
static bool class_inited;
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
static class LsCache *cache;
|
|
Packit |
8f70b4 |
enum open_mode
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
CLOSED,
|
|
Packit |
8f70b4 |
RETRIEVE,
|
|
Packit |
8f70b4 |
STORE,
|
|
Packit |
8f70b4 |
LONG_LIST,
|
|
Packit |
8f70b4 |
LIST,
|
|
Packit |
8f70b4 |
MP_LIST,
|
|
Packit |
8f70b4 |
CHANGE_DIR,
|
|
Packit |
8f70b4 |
MAKE_DIR,
|
|
Packit |
8f70b4 |
REMOVE_DIR,
|
|
Packit |
8f70b4 |
REMOVE,
|
|
Packit |
8f70b4 |
QUOTE_CMD,
|
|
Packit |
8f70b4 |
RENAME,
|
|
Packit |
8f70b4 |
ARRAY_INFO,
|
|
Packit |
8f70b4 |
CONNECT_VERIFY,
|
|
Packit |
8f70b4 |
CHANGE_MODE,
|
|
Packit |
8f70b4 |
LINK,
|
|
Packit |
8f70b4 |
SYMLINK,
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
class Path
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
void init();
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
int device_prefix_len;
|
|
Packit |
8f70b4 |
xstring path;
|
|
Packit |
8f70b4 |
bool is_file;
|
|
Packit |
8f70b4 |
xstring url;
|
|
Packit |
8f70b4 |
Path() { init(); }
|
|
Packit |
8f70b4 |
Path(const Path *o) { init(); Set(o); }
|
|
Packit |
8f70b4 |
Path(const Path &o) { init(); Set(o); }
|
|
Packit |
8f70b4 |
Path(const char *new_path) { init(); Set(new_path); }
|
|
Packit |
8f70b4 |
Path(const char *new_path,bool new_is_file,const char *new_url=0,int new_device_prefix_len=0)
|
|
Packit |
8f70b4 |
{ init(); Set(new_path,new_is_file,new_url,new_device_prefix_len); }
|
|
Packit |
8f70b4 |
~Path();
|
|
Packit |
8f70b4 |
void Set(const Path*);
|
|
Packit |
8f70b4 |
void Set(const Path &o) { Set(&o); }
|
|
Packit |
8f70b4 |
void Set(const char *new_path,bool new_is_file=false,const char *new_url=0,int device_prefix_len=0);
|
|
Packit |
8f70b4 |
void SetURL(const char *u) { url.set(u); }
|
|
Packit |
8f70b4 |
void Change(const char *new_path,bool new_is_file=false,const char *new_path_enc=0,int device_prefix_len=0);
|
|
Packit |
8f70b4 |
const xstring& GetDirectory() const { return is_file?dirname(path):path; }
|
|
Packit |
8f70b4 |
void ExpandTilde(const Path &home;;
|
|
Packit |
8f70b4 |
static void Optimize(xstring& p,int dev_prefix=0);
|
|
Packit |
8f70b4 |
void Optimize() { Optimize(path,device_prefix_len); }
|
|
Packit |
8f70b4 |
const Path& operator=(const Path &o)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Set(&o);
|
|
Packit |
8f70b4 |
return *this;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
operator const char *() const { return path; }
|
|
Packit |
8f70b4 |
bool operator==(const Path &p2) const;
|
|
Packit |
8f70b4 |
bool operator!=(const Path &p2) const { return !(*this==p2); }
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
protected:
|
|
Packit |
8f70b4 |
xstring_c vproto;
|
|
Packit |
8f70b4 |
xstring_c hostname;
|
|
Packit |
8f70b4 |
xstring_c portname;
|
|
Packit |
8f70b4 |
xstring_c user;
|
|
Packit |
8f70b4 |
xstring_c pass;
|
|
Packit |
8f70b4 |
bool pass_open;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *default_cwd;
|
|
Packit |
8f70b4 |
Path home;
|
|
Packit |
8f70b4 |
Path cwd;
|
|
Packit |
8f70b4 |
Ref<Path> new_cwd;
|
|
Packit |
8f70b4 |
xstring file;
|
|
Packit |
8f70b4 |
xstring file_url;
|
|
Packit |
8f70b4 |
xstring file1;
|
|
Packit |
8f70b4 |
int mode;
|
|
Packit |
8f70b4 |
off_t pos;
|
|
Packit |
8f70b4 |
off_t real_pos;
|
|
Packit |
8f70b4 |
off_t limit;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileTimestamp *opt_date;
|
|
Packit |
8f70b4 |
off_t *opt_size;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileSet *fileset_for_info;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
Timer reconnect_timer;
|
|
Packit |
8f70b4 |
int retries;
|
|
Packit |
8f70b4 |
int max_retries;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool mkdir_p;
|
|
Packit |
8f70b4 |
bool rename_f;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int saved_errno;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void ExpandTildeInCWD();
|
|
Packit |
8f70b4 |
const char *ExpandTildeStatic(const char *s) const;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
xstring real_cwd;
|
|
Packit |
8f70b4 |
void set_real_cwd(const char *c)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
real_cwd.set(c);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void set_home(const char *h);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
off_t entity_size; // size of file to be sent
|
|
Packit |
8f70b4 |
time_t entity_date; // date of file to be sent
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
xstring_c closure;
|
|
Packit |
8f70b4 |
const char *res_prefix;
|
|
Packit |
8f70b4 |
const char *ResPrefix() const { return res_prefix?res_prefix:GetProto(); }
|
|
Packit |
8f70b4 |
const char *ResClosure() const { return closure?closure.get():GetHostName(); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int chmod_mode;
|
|
Packit |
8f70b4 |
bool ascii;
|
|
Packit |
8f70b4 |
bool norest_manual;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int priority; // higher priority can take over other session.
|
|
Packit |
8f70b4 |
int last_priority;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool Error() { return error_code!=OK; }
|
|
Packit |
8f70b4 |
void ClearError();
|
|
Packit |
8f70b4 |
void SetError(int code,const char *mess=0);
|
|
Packit |
8f70b4 |
void Fatal(const char *mess);
|
|
Packit |
8f70b4 |
xstring error;
|
|
Packit |
8f70b4 |
int error_code;
|
|
Packit |
8f70b4 |
xstring_c location;
|
|
Packit |
8f70b4 |
xstring_c suggested_filename;
|
|
Packit |
8f70b4 |
void SetSuggestedFileName(const char *fn);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
xstring_c entity_content_type;
|
|
Packit |
8f70b4 |
xstring_c entity_charset;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
xstring_c last_disconnect_cause;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
xlist<FileAccess> all_fa_node;
|
|
Packit |
8f70b4 |
static xlist_head<FileAccess> all_fa;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileAccess *FirstSameSite() const { return NextSameSite(0); }
|
|
Packit |
8f70b4 |
FileAccess *NextSameSite(FileAccess *) const;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
StringSet *MkdirMakeSet() const; // splits the path for mkdir -p
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int device_prefix_len(const char *path) const;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual ~FileAccess();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
virtual const char *GetProto() const = 0; // http, ftp, file etc
|
|
Packit |
8f70b4 |
bool SameProtoAs(const FileAccess *fa) const { return !strcmp(GetProto(),fa->GetProto()); }
|
|
Packit |
8f70b4 |
virtual FileAccess *Clone() const = 0;
|
|
Packit |
8f70b4 |
virtual const char *ProtocolSubstitution(const char *host) { return 0; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *GetVisualProto() const { return vproto?vproto.get():GetProto(); }
|
|
Packit |
8f70b4 |
void SetVisualProto(const char *p) { vproto.set(p); }
|
|
Packit |
8f70b4 |
const char *GetHome() const { return home; }
|
|
Packit |
8f70b4 |
const char *GetHostName() const { return hostname; }
|
|
Packit |
8f70b4 |
const char *GetUser() const { return user; }
|
|
Packit |
8f70b4 |
const char *GetPassword() const { return pass; }
|
|
Packit |
8f70b4 |
const char *GetPort() const { return portname; }
|
|
Packit |
8f70b4 |
const xstring& GetConnectURL(int flags=0) const;
|
|
Packit |
8f70b4 |
const xstring& GetFileURL(const char *file,int flags=0) const;
|
|
Packit |
8f70b4 |
enum { NO_PATH=1,WITH_PASSWORD=2,NO_PASSWORD=4,NO_USER=8 };
|
|
Packit |
8f70b4 |
const char *GetLastDisconnectCause() const { return last_disconnect_cause; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Connect(const char *h,const char *p);
|
|
Packit |
8f70b4 |
void ConnectVerify();
|
|
Packit |
8f70b4 |
void PathVerify(const Path &);
|
|
Packit |
8f70b4 |
virtual void Login(const char *u,const char *p);
|
|
Packit |
8f70b4 |
void AnonymousLogin() { Login(0,0); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// reset location-related state on Connect/Login/AnonymousLogin
|
|
Packit |
8f70b4 |
virtual void ResetLocationData();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual void Open(const char *file,int mode,off_t pos=0);
|
|
Packit |
8f70b4 |
void Open2(const char *f1,const char *f2,open_mode m);
|
|
Packit |
8f70b4 |
void SetFileURL(const char *u);
|
|
Packit |
8f70b4 |
void SetLimit(off_t lim) { limit=lim; }
|
|
Packit |
8f70b4 |
void SetSize(off_t s) { entity_size=s; }
|
|
Packit |
8f70b4 |
void SetDate(time_t d) { entity_date=d; }
|
|
Packit |
8f70b4 |
void WantDate(FileTimestamp *d) { opt_date=d; }
|
|
Packit |
8f70b4 |
void WantSize(off_t *s) { opt_size=s; }
|
|
Packit |
8f70b4 |
void AsciiTransfer() { ascii=true; }
|
|
Packit |
8f70b4 |
virtual void Close();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Rename(const char *rfile,const char *to,bool clobber=false);
|
|
Packit |
8f70b4 |
void Link(const char *f1,const char *f2) { Open2(f1,f2,LINK); }
|
|
Packit |
8f70b4 |
void Symlink(const char *f1,const char *f2) { Open2(f1,f2,SYMLINK); }
|
|
Packit |
8f70b4 |
void Mkdir(const char *rfile,bool allpath=false);
|
|
Packit |
8f70b4 |
void Chdir(const char *dir,bool verify=true);
|
|
Packit |
8f70b4 |
void ChdirAccept() { cwd=*new_cwd; }
|
|
Packit |
8f70b4 |
void SetCwd(const Path &new_cwd) { cwd=new_cwd; }
|
|
Packit |
8f70b4 |
void Remove(const char *rfile) { Open(rfile,REMOVE); }
|
|
Packit |
8f70b4 |
void RemoveDir(const char *dir) { Open(dir,REMOVE_DIR); }
|
|
Packit |
8f70b4 |
void Chmod(const char *file,int m);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void GetInfoArray(FileSet *info);
|
|
Packit |
8f70b4 |
int InfoArrayPercentDone() { return fileset_for_info->curr_pct(); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual const char *CurrentStatus();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual int Read(Buffer *buf,int size) = 0;
|
|
Packit |
8f70b4 |
virtual int Write(const void *buf,int size) = 0;
|
|
Packit |
8f70b4 |
virtual int Buffered();
|
|
Packit |
8f70b4 |
virtual int StoreStatus() = 0;
|
|
Packit |
8f70b4 |
virtual bool IOReady();
|
|
Packit |
8f70b4 |
off_t GetPos() const { return pos; }
|
|
Packit |
8f70b4 |
off_t GetRealPos() const { return real_pos<0?pos:real_pos; }
|
|
Packit |
8f70b4 |
void SeekReal() { pos=GetRealPos(); }
|
|
Packit |
8f70b4 |
void RereadManual() { norest_manual=true; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const Path& GetCwd() const { return cwd; }
|
|
Packit |
8f70b4 |
const Path& GetNewCwd() const { return *new_cwd; }
|
|
Packit |
8f70b4 |
const char *GetFile() const { return file; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual int Do() = 0;
|
|
Packit |
8f70b4 |
virtual int Done() = 0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual bool SameLocationAs(const FileAccess *fa) const;
|
|
Packit |
8f70b4 |
virtual bool SameSiteAs(const FileAccess *fa) const;
|
|
Packit |
8f70b4 |
bool IsBetterThan(const FileAccess *fa) const;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Init();
|
|
Packit |
8f70b4 |
FileAccess() : all_fa_node(this) { Init(); }
|
|
Packit |
8f70b4 |
FileAccess(const FileAccess *);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void DontSleep() { reconnect_timer.Stop(); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool IsClosed() { return mode==CLOSED; }
|
|
Packit |
8f70b4 |
bool IsOpen() { return !IsClosed(); }
|
|
Packit |
8f70b4 |
int OpenMode() { return mode; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual int IsConnected() const; // level of connection (0 - not connected).
|
|
Packit |
8f70b4 |
void Disconnect(const char *dc=0) { last_disconnect_cause.set(dc); DisconnectLL(); }
|
|
Packit |
8f70b4 |
virtual void DisconnectLL() {}
|
|
Packit |
8f70b4 |
virtual void UseCache(bool);
|
|
Packit |
8f70b4 |
virtual bool NeedSizeDateBeforehand();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int GetErrorCode() { return error_code; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
enum status
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
IN_PROGRESS=1, // is returned only by *Status() or Done()
|
|
Packit |
8f70b4 |
OK=0,
|
|
Packit |
8f70b4 |
SEE_ERRNO=-100,
|
|
Packit |
8f70b4 |
LOOKUP_ERROR,
|
|
Packit |
8f70b4 |
NOT_OPEN,
|
|
Packit |
8f70b4 |
NO_FILE,
|
|
Packit |
8f70b4 |
NO_HOST,
|
|
Packit |
8f70b4 |
FILE_MOVED,
|
|
Packit |
8f70b4 |
FATAL,
|
|
Packit |
8f70b4 |
STORE_FAILED,
|
|
Packit |
8f70b4 |
LOGIN_FAILED,
|
|
Packit |
8f70b4 |
DO_AGAIN,
|
|
Packit |
8f70b4 |
NOT_SUPP
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual const char *StrError(int err);
|
|
Packit |
8f70b4 |
virtual void Cleanup();
|
|
Packit |
8f70b4 |
virtual void CleanupThis();
|
|
Packit |
8f70b4 |
void CleanupAll();
|
|
Packit |
8f70b4 |
// ^^ close idle connections, etc.
|
|
Packit |
8f70b4 |
virtual ListInfo *MakeListInfo(const char *path=0);
|
|
Packit |
8f70b4 |
virtual Glob *MakeGlob(const char *pattern);
|
|
Packit |
8f70b4 |
virtual DirList *MakeDirList(ArgV *a);
|
|
Packit |
8f70b4 |
virtual FileSet *ParseLongList(const char *buf,int len,int *err=0) const { return 0; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static bool NotSerious(int err) { return temporary_network_error(err); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *GetNewLocation() { return location; }
|
|
Packit |
8f70b4 |
const char *GetSuggestedFileName() { return suggested_filename; }
|
|
Packit |
8f70b4 |
const char *GetEntityContentType() { return entity_content_type; }
|
|
Packit |
8f70b4 |
const char *GetEntityCharset() { return entity_charset; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Reconfig(const char *);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
typedef FileAccess *SessionCreator();
|
|
Packit |
8f70b4 |
class Protocol
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
static xmap_p<Protocol> proto_by_name;
|
|
Packit |
8f70b4 |
const char *proto;
|
|
Packit |
8f70b4 |
SessionCreator *New;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static Protocol *FindProto(const char *proto);
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
static FileAccess *NewSession(const char *proto);
|
|
Packit |
8f70b4 |
Protocol(const char *proto,SessionCreator *creator);
|
|
Packit |
8f70b4 |
static void ClassCleanup() { proto_by_name.empty(); }
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static void Register(const char *proto,SessionCreator *creator)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
(void)new Protocol(proto,creator);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static FileAccess *New(const char *proto,const char *host=0,const char *port=0);
|
|
Packit |
8f70b4 |
static FileAccess *New(const class ParsedURL *u,bool dummy=true);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void SetPasswordGlobal(const char *p);
|
|
Packit |
8f70b4 |
void InsecurePassword(bool i)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
pass_open=i;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void SetPriority(int p)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(p==priority)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
priority=p;
|
|
Packit |
8f70b4 |
current->Timeout(0);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
int GetPriority() const { return priority; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// not pretty (FIXME)
|
|
Packit |
8f70b4 |
int GetRetries() const { return retries; }
|
|
Packit |
8f70b4 |
void SetRetries(int r) { retries=r; }
|
|
Packit |
8f70b4 |
int GetMaxRetries() const { return max_retries; }
|
|
Packit |
8f70b4 |
time_t GetTryTime() const { return reconnect_timer.GetStartTime(); }
|
|
Packit |
8f70b4 |
void SetTryTime(time_t t);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *GetLogContext() { return hostname; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static void ClassInit();
|
|
Packit |
8f70b4 |
static void ClassCleanup();
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// shortcut
|
|
Packit |
8f70b4 |
#define FA FileAccess
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// cache of used sessions
|
|
Packit |
8f70b4 |
class SessionPool
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
enum { pool_size=64 };
|
|
Packit |
8f70b4 |
static FileAccess *pool[pool_size];
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
static void Reuse(FileAccess *);
|
|
Packit |
8f70b4 |
static void Print(FILE *f);
|
|
Packit |
8f70b4 |
static FileAccess *GetSession(int n);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// start with n==0, then increase n; returns 0 when no more
|
|
Packit |
8f70b4 |
static FileAccess *Walk(int *n,const char *proto);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static void ClearAll();
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
class FileAccessRef : public SMTaskRef<FileAccess>
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileAccessRef(const FileAccessRef&); // disable cloning
|
|
Packit |
8f70b4 |
void operator=(const FileAccessRef&); // and assignment
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void reuse() { if(ptr) { ptr->DecRefCount(); SessionPool::Reuse(ptr); ptr=0; } }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
FileAccessRef() {}
|
|
Packit |
8f70b4 |
FileAccessRef(FileAccess *p) : SMTaskRef<FileAccess>(p) {}
|
|
Packit |
8f70b4 |
~FileAccessRef() { reuse(); }
|
|
Packit |
8f70b4 |
const FileAccessRef& operator=(FileAccess *p);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
template<class T> const SMTaskRef<T>& Cast() const
|
|
Packit |
8f70b4 |
{ void(static_cast<T*>(this->ptr)); return *(const SMTaskRef<T>*)this; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static const FileAccessRef null;
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// constant ref (ref clone)
|
|
Packit |
8f70b4 |
class FileAccessRefC
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
void close() { if(*ref) (*ref)->Close(); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
protected:
|
|
Packit |
8f70b4 |
const FileAccessRef *ref;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
FileAccessRefC(const FileAccessRef& p) { ref=&p; }
|
|
Packit |
8f70b4 |
const FileAccessRef& operator=(const FileAccessRef& p) { close(); ref=&p; return p; }
|
|
Packit |
8f70b4 |
operator const FileAccess*() const { return *ref; }
|
|
Packit |
8f70b4 |
FileAccess *operator->() const { return ref->operator->(); }
|
|
Packit |
8f70b4 |
operator const FileAccessRef&() { return *ref; }
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// static reference
|
|
Packit |
8f70b4 |
class FileAccessRefS : public FileAccessRef
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileAccessRefS(const FileAccessRefS&); // disable cloning
|
|
Packit |
8f70b4 |
void operator=(const FileAccessRefS&); // and assignment
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
FileAccessRefS() {}
|
|
Packit |
8f70b4 |
FileAccessRefS(FileAccess *p) { ptr=p; }
|
|
Packit |
8f70b4 |
~FileAccessRefS() { ptr=0; }
|
|
Packit |
8f70b4 |
const FileAccessRefS& operator=(FileAccess *p) { ptr=p; return *this; }
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
class FileAccessOperation : public SMTask
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
protected:
|
|
Packit |
8f70b4 |
FileAccessRefS session;
|
|
Packit |
8f70b4 |
bool done;
|
|
Packit |
8f70b4 |
xstring error_text;
|
|
Packit |
8f70b4 |
void SetError(const char *);
|
|
Packit |
8f70b4 |
void SetErrorCached(const char *);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool use_cache;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void PrepareToDie() { if(session) session->Close(); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
FileAccessOperation(FileAccess *s) : session(s), done(false), use_cache(true) {}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual int Do() = 0;
|
|
Packit |
8f70b4 |
bool Done() { return done; }
|
|
Packit |
8f70b4 |
bool Error() { return error_text!=0; }
|
|
Packit |
8f70b4 |
const char *ErrorText() { return error_text; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual const char *Status() = 0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void UseCache(bool y=true) { use_cache=y; }
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include "PatternSet.h"
|
|
Packit |
8f70b4 |
class ListInfo : public FileAccessOperation
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
protected:
|
|
Packit |
8f70b4 |
FileAccess::Path saved_cwd;
|
|
Packit |
8f70b4 |
Ref<FileSet> result;
|
|
Packit |
8f70b4 |
Ref<FileSet> excluded;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *exclude_prefix;
|
|
Packit |
8f70b4 |
const PatternSet *exclude;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
unsigned need;
|
|
Packit |
8f70b4 |
bool follow_symlinks;
|
|
Packit |
8f70b4 |
bool try_recursive;
|
|
Packit |
8f70b4 |
bool is_recursive;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void PrepareToDie();
|
|
Packit |
8f70b4 |
~ListInfo();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
ListInfo(FileAccess *session,const char *path);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void SetExclude(const char *p,const PatternSet *e) { exclude_prefix=p; exclude=e; excluded=new FileSet(); }
|
|
Packit |
8f70b4 |
void TryRecursive(bool y=true) { try_recursive=y; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// caller has to delete the resulting FileSet itself.
|
|
Packit |
8f70b4 |
FileSet *GetResult() { return result.borrow(); }
|
|
Packit |
8f70b4 |
FileSet *GetExcluded() { return excluded.borrow(); }
|
|
Packit |
8f70b4 |
bool IsRecursive() const { return is_recursive; }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Need(unsigned mask) { need|=mask; }
|
|
Packit |
8f70b4 |
void NoNeed(unsigned mask) { need&=~mask; }
|
|
Packit |
8f70b4 |
void FollowSymlinks() { follow_symlinks=true; }
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include "buffer.h"
|
|
Packit |
8f70b4 |
class LsOptions
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
bool append_type:1;
|
|
Packit |
8f70b4 |
bool multi_column:1;
|
|
Packit |
8f70b4 |
bool show_all:1;
|
|
Packit |
8f70b4 |
LsOptions()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
append_type=false;
|
|
Packit |
8f70b4 |
multi_column=false;
|
|
Packit |
8f70b4 |
show_all=false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
class DirList : public FileAccessOperation
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
protected:
|
|
Packit |
8f70b4 |
Ref<Buffer> buf;
|
|
Packit |
8f70b4 |
Ref<ArgV> args;
|
|
Packit |
8f70b4 |
bool color;
|
|
Packit |
8f70b4 |
~DirList();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
DirList(FileAccess *s,ArgV *a);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
virtual int Do() = 0;
|
|
Packit |
8f70b4 |
virtual const char *Status() = 0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int Size() { return buf->Size(); }
|
|
Packit |
8f70b4 |
bool Eof() { return buf->Eof(); }
|
|
Packit |
8f70b4 |
void Get(const char **b,int *size) { buf->Get(b,size); }
|
|
Packit |
8f70b4 |
void Skip(int len) { buf->Skip(len); }
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void UseColor(bool c=true) { color=c; }
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
class UploadState
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
time_t try_time;
|
|
Packit |
8f70b4 |
off_t pos_watermark;
|
|
Packit |
8f70b4 |
int retries;
|
|
Packit |
8f70b4 |
public:
|
|
Packit |
8f70b4 |
UploadState() : try_time(NO_DATE), pos_watermark(0),retries(-1) {}
|
|
Packit |
8f70b4 |
void Clear() {
|
|
Packit |
8f70b4 |
try_time=NO_DATE;
|
|
Packit |
8f70b4 |
pos_watermark=0;
|
|
Packit |
8f70b4 |
retries=-1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Save(const FileAccess *session) {
|
|
Packit |
8f70b4 |
try_time=session->GetTryTime();
|
|
Packit |
8f70b4 |
retries=session->GetRetries();
|
|
Packit |
8f70b4 |
off_t pos=session->GetRealPos();
|
|
Packit |
8f70b4 |
int max_retries=session->GetMaxRetries();
|
|
Packit |
8f70b4 |
if(max_retries>0 && retries>=max_retries)
|
|
Packit |
8f70b4 |
pos=0;
|
|
Packit |
8f70b4 |
if(pos_watermark
|
|
Packit |
8f70b4 |
pos_watermark=pos;
|
|
Packit |
8f70b4 |
retries=-1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Restore(const FileAccessRef& session) {
|
|
Packit |
8f70b4 |
if(try_time!=NO_DATE)
|
|
Packit |
8f70b4 |
session->SetTryTime(try_time);
|
|
Packit |
8f70b4 |
if(retries>=0)
|
|
Packit |
8f70b4 |
session->SetRetries(retries+1);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
};
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#endif /* FILEACCESS_H */
|