Blame src/FileAccess.h

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 */