sig
  type ftp
  type response
  type directoryResponse
  type listingResponse
  type status =
      RestartMarkerReply
    | ServiceReadySoon
    | DataConnectionAlreadyOpened
    | OpeningDataConnection
    | Ok
    | PointlessCommand
    | SystemStatus
    | DirectoryStatus
    | FileStatus
    | HelpMessage
    | SystemType
    | ServiceReady
    | ClosingConnection
    | DataConnectionOpened
    | ClosingDataConnection
    | EnteringPassiveMode
    | LoggedIn
    | FileActionOk
    | DirectoryOk
    | NeedPassword
    | NeedAccountToLogIn
    | NeedInformation
    | ServiceUnavailable
    | DataConnectionUnavailable
    | TransferAborted
    | FileActionAborted
    | LocalError
    | InsufficientStorageSpace
    | CommandUnknown
    | ParametersUnknown
    | CommandNotImplemented
    | BadCommandSequence
    | ParameterNotImplemented
    | NotLoggedIn
    | NeedAccountToStore
    | FileUnavailable
    | PageTypeUnknown
    | NotEnoughMemory
    | FilenameNotAllowed
    | InvalidResponse
    | ConnectionFailed
    | ConnectionClosed
    | InvalidFile
  type transferMode = Binary | Ascii | Ebcdic
  external create : unit -> SFFtp.ftp = "caml_sfFtp_create"
  external destroy : SFFtp.ftp -> unit = "caml_sfFtp_destroy"
  external connect :
    SFFtp.ftp ->
    server:SFIpAddress.t ->
    ?port:int -> ?timeout:SFTime.t -> unit -> SFFtp.response
    = "caml_sfFtp_connect"
  external loginAnonymous : SFFtp.ftp -> SFFtp.response
    = "caml_sfFtp_loginAnonymous"
  external login :
    SFFtp.ftp -> userName:string -> password:string -> SFFtp.response
    = "caml_sfFtp_login"
  external disconnect : SFFtp.ftp -> SFFtp.response = "caml_sfFtp_disconnect"
  external keepAlive : SFFtp.ftp -> SFFtp.response = "caml_sfFtp_keepAlive"
  external changeDirectory : SFFtp.ftp -> directory:string -> SFFtp.response
    = "caml_sfFtp_changeDirectory"
  external parentDirectory : SFFtp.ftp -> SFFtp.response
    = "caml_sfFtp_parentDirectory"
  external createDirectory : SFFtp.ftp -> name:string -> SFFtp.response
    = "caml_sfFtp_createDirectory"
  external deleteDirectory : SFFtp.ftp -> name:string -> SFFtp.response
    = "caml_sfFtp_deleteDirectory"
  external renameFile :
    SFFtp.ftp -> file:string -> newName:string -> SFFtp.response
    = "caml_sfFtp_renameFile"
  external deleteFile : SFFtp.ftp -> name:string -> SFFtp.response
    = "caml_sfFtp_deleteFile"
  external upload :
    SFFtp.ftp ->
    localFile:string ->
    destPath:string -> mode:SFFtp.transferMode -> SFFtp.response
    = "caml_sfFtp_upload"
  external download :
    SFFtp.ftp ->
    distantFile:string ->
    destPath:string -> mode:SFFtp.transferMode -> SFFtp.response
    = "caml_sfFtp_download"
  module Response :
    sig
      external destroy : SFFtp.response -> unit
        = "caml_sfFtpResponse_destroy"
      external isOk : SFFtp.response -> bool = "caml_sfFtpResponse_isOk"
      external getStatus : SFFtp.response -> SFFtp.status
        = "caml_sfFtpResponse_getStatus"
      external getMessage : SFFtp.response -> string
        = "caml_sfFtpResponse_getMessage"
    end
  external getDirectoryListing :
    SFFtp.ftp -> directory:string -> SFFtp.listingResponse
    = "caml_sfFtp_getDirectoryListing"
  module ListingResponse :
    sig
      external destroy : SFFtp.listingResponse -> unit
        = "caml_sfFtpListingResponse_destroy"
      external isOk : SFFtp.listingResponse -> bool
        = "caml_sfFtpListingResponse_isOk"
      external getStatus : SFFtp.listingResponse -> SFFtp.status
        = "caml_sfFtpListingResponse_getStatus"
      external getMessage : SFFtp.listingResponse -> string
        = "caml_sfFtpListingResponse_getMessage"
      external getListing : SFFtp.listingResponse -> string array
        = "caml_sfFtpListingResponse_getListing"
    end
  external getWorkingDirectory : SFFtp.ftp -> SFFtp.directoryResponse
    = "caml_sfFtp_getWorkingDirectory"
  module DirectoryResponse :
    sig
      external destroy : SFFtp.directoryResponse -> unit
        = "caml_sfFtpDirectoryResponse_destroy"
      external isOk : SFFtp.directoryResponse -> bool
        = "caml_sfFtpDirectoryResponse_isOk"
      external getStatus : SFFtp.directoryResponse -> SFFtp.status
        = "caml_sfFtpDirectoryResponse_getStatus"
      external getMessage : SFFtp.directoryResponse -> string
        = "caml_sfFtpDirectoryResponse_getMessage"
      external getDirectory : SFFtp.directoryResponse -> string
        = "caml_sfFtpDirectoryResponse_getDirectory"
    end
  external sendCommand :
    SFFtp.ftp -> command:string -> parameter:string -> SFFtp.response
    = "caml_sfFtp_sendCommand"
end