@namespace("keybase.1") protocol SimpleFS { import idl "common.avdl"; import idl "kbfs_common.avdl"; /* File manipulation interface Caller provides OpID to one of these methods to begin an operation: simpleFSList simpleFSListRecursive simpleFSListRecursiveToDepth simpleFSCopy simpleFSOpen simpleFSMove simpleFSRemove simpleFSGetRevisions then calls one of the following until status is no longer pending or operation is cancelled: simpleFSReadList (after list, listRecursive, or listRecursiveToDepth) simpleFSGetRevisions (after getRevisions) simpleFSRead (after open) simpleFSWrite (after open) simpleFSCheck (after copy, move or remove) Caller can optionally block by calling wait() Operation must be closed by calling close */ // Random GUID provided by caller fixed OpID(16); @typedef("int64") @lint("ignore") record KBFSRevision {} enum KBFSArchivedType { REVISION_0, TIME_1, TIME_STRING_2, REL_TIME_STRING_3 } variant KBFSArchivedParam switch (KBFSArchivedType KBFSArchivedType) { case REVISION: KBFSRevision; case TIME: Time; case TIME_STRING: string; case REL_TIME_STRING: string; } record KBFSArchivedPath { string path; KBFSArchivedParam archivedParam; union{ null, TLFIdentifyBehavior } identifyBehavior; } record KBFSPath { string path; union{ null, TLFIdentifyBehavior } identifyBehavior; } enum PathType { LOCAL_0, KBFS_1, KBFS_ARCHIVED_2 } variant Path switch (PathType PathType) { case LOCAL: string; case KBFS: KBFSPath; case KBFS_ARCHIVED: KBFSArchivedPath; } enum DirentType { FILE_0, DIR_1, SYM_2, EXEC_3 } enum PrefetchStatus { NOT_STARTED_0, IN_PROGRESS_1, COMPLETE_2 } record PrefetchProgress { Time start; Time endEstimate; int64 bytesTotal; int64 bytesFetched; } record Dirent { Time time; int size; // size of file or count of dir entries (TBD - may be expensive/unnecessary) string name; DirentType direntType; // The last writer of this directory entry. NOTE: this is NOT // cryptographically verified; users with write access to the TLF could // in theory spoof the last writer if they modify their client. User lastWriterUnverified; boolean writable; PrefetchStatus prefetchStatus; PrefetchProgress prefetchProgress; string symlinkTarget; } record DirentWithRevision { Dirent entry; KBFSRevision revision; } enum RevisionSpanType { DEFAULT_0, // scattered revisions across different time intervals LAST_FIVE_1 // the five most recent revisions } @typedef("int") record ErrorNum {} enum OpenFlags { READ_0, // exclusive of other flags REPLACE_1, // overwrite EXISTING_2, // fail if not present already WRITE_4, // read is implied if not write, executable, or directory APPEND_8, DIRECTORY_16 } @typedef("int") record Progress {} record SimpleFSListResult { array entries; Progress progress; } record FileContent { bytes data; // Zero bytes when read is complete Progress progress; // Amount of data copied so far during this and previous reads } // (TBD: should this be percentage?) enum AsyncOps { LIST_0, LIST_RECURSIVE_1, READ_2, WRITE_3, COPY_4, MOVE_5, REMOVE_6, LIST_RECURSIVE_TO_DEPTH_7, GET_REVISIONS_8 } enum ListFilter { NO_FILTER_0, FILTER_ALL_HIDDEN_1, FILTER_SYSTEM_HIDDEN_2 } record ListArgs { OpID opID; Path path; ListFilter filter; } record ListToDepthArgs { OpID opID; Path path; ListFilter filter; int depth; } record RemoveArgs { OpID opID; Path path; boolean recursive; } record ReadArgs { OpID opID; Path path; long offset; int size; } record WriteArgs { OpID opID; Path path; long offset; } record CopyArgs { OpID opID; Path src; Path dest; } record MoveArgs { OpID opID; Path src; Path dest; } record GetRevisionsArgs { OpID opID; Path path; RevisionSpanType spanType; } variant OpDescription switch (AsyncOps asyncOp) { case LIST: ListArgs; case LIST_RECURSIVE: ListArgs; case LIST_RECURSIVE_TO_DEPTH: ListToDepthArgs; case READ: ReadArgs; case WRITE: WriteArgs; case COPY: CopyArgs; case MOVE: MoveArgs; case REMOVE: RemoveArgs; case GET_REVISIONS: GetRevisionsArgs; } record GetRevisionsResult { array revisions; Progress progress; } record OpProgress { Time start; Time endEstimate; AsyncOps opType; int64 bytesTotal; int64 bytesRead; int64 bytesWritten; int64 filesTotal; int64 filesRead; int64 filesWritten; } /** Begin list of items in directory at path. Retrieve results with readList(). Can be a single file to get flags/status. If `refreshSubscription` is true and the path is a KBFS path, simpleFS will begin sending `FSPathUpdated` notifications for the for the corresponding TLF, until another call refreshes the subscription on a different TLF. */ void simpleFSList(OpID opID, Path path, ListFilter filter, boolean refreshSubscription); /** Begin recursive list of items in directory at path. If `refreshSubscription` is true and the path is a KBFS path, simpleFS will begin sending `FSPathUpdated` notifications for the for the corresponding TLF, until another call refreshes the subscription on a different TLF. */ void simpleFSListRecursive(OpID opID, Path path, ListFilter filter, boolean refreshSubscription); /** Begin recursive list of items in directory at path up to a given depth */ void simpleFSListRecursiveToDepth(OpID opID, Path path, ListFilter filter, boolean refreshSubscription, int depth); /** Get list of Paths in progress. Can indicate status of pending to get more entries. */ SimpleFSListResult simpleFSReadList(OpID opID); /** Begin copy of file or directory */ void simpleFSCopy(OpID opID, Path src, Path dest); /** Make a symlink of file or directory */ void simpleFSSymlink(string target, Path link); /** Begin recursive copy of directory */ void simpleFSCopyRecursive(OpID opID, Path src, Path dest); /** Begin move of file or directory, from/to KBFS only */ void simpleFSMove(OpID opID, Path src, Path dest); /** Rename file or directory, KBFS side only */ void simpleFSRename(Path src, Path dest); /** Create/open a file and leave it open or create a directory Files must be closed afterwards. */ void simpleFSOpen(OpID opID, Path dest, OpenFlags flags); /** Set/clear file bits - only executable for now */ void simpleFSSetStat(Path dest, DirentType flag); /** Read (possibly partial) contents of open file, up to the amount specified by size. Repeat until zero bytes are returned or error. If size is zero, read an arbitrary amount. */ FileContent simpleFSRead(OpID opID, long offset, int size); /** Append content to opened file. May be repeated until OpID is closed. */ void simpleFSWrite(OpID opID, long offset, bytes content); /** Remove file or directory from filesystem */ void simpleFSRemove(OpID opID, Path path, boolean recursive); /** Get info about file */ Dirent simpleFSStat(Path path, boolean refreshSubscription); /** Get revision info for a directory entry */ void simpleFSGetRevisions(OpID opID, Path path, RevisionSpanType spanType); /** Get list of revisions in progress. Can indicate status of pending to get more revisions. */ GetRevisionsResult simpleFSReadRevisions(OpID opID); /** Convenience helper for generating new random value */ OpID simpleFSMakeOpid(); /** Close OpID, cancels any pending operation. Must be called after list/copy/remove */ void simpleFSClose(OpID opID); /** Cancels a running operation, like copy. */ void simpleFSCancel(OpID opID); /** Check progress of pending operation */ OpProgress simpleFSCheck(OpID opID); /** Get all the outstanding operations */ array simpleFSGetOps(); /** Blocking wait for the pending operation to finish */ void simpleFSWait(OpID opID); /** Instructs KBFS to dump debugging info into its logs. */ void simpleFSDumpDebuggingInfo(); // Clear the conflict state of a TLF. This turns a locally "branched" TLF // into: // 1) a TLF that's as seen on all other devices, i.e. the server view, // under the normal TLF path; // 2) a TLF that's locally branched, under a path with a TLF suffix. // // After this, user is expected to make changes in 1), usually by coping // needed data from 2) into 1). // // Note that it's possible to have multiple 2) for the same 1). void simpleFSClearConflictState(Path path); // Mark the finish of resolving conflict. This deletes the locally branched // version of the TLF. Path must be a local view TLF path with conflict // suffix. void simpleFSFinishResolvingConflict(Path path); /** Force a TLF into a stuck conflict state (for testing). */ void simpleFSForceStuckConflict(Path path); /** Get sync status. */ FSSyncStatus simpleFSSyncStatus(ListFilter filter); /** simpleFSUserEditHistory returns edit histories of TLFs that the logged-in user can access. Each returned history is corresponds to a unique writer-TLF pair. They are in descending order by the modification time (as recorded by the server) of the most recent edit in each history. */ array simpleFSUserEditHistory(); /** simpleFSFolderEditHistory returns the edit history for the TLF described by `path`, for the most recent writers of that TLF. The writers are in descending order by the modification time (as recorded by the server) of their most recent edit. */ FSFolderEditHistory simpleFSFolderEditHistory(Path path); /** simpleFSListFavorites gets the current favorites, ignored folders, and new folders from the KBFS cache. */ FavoritesResult simpleFSListFavorites(); record SimpleFSQuotaUsage { int64 usageBytes; int64 archiveBytes; int64 limitBytes; int64 gitUsageBytes; int64 gitArchiveBytes; int64 gitLimitBytes; } /** simpleFSGetUserQuotaUsage returns the quota usage for the logged-in user. Any usage includes local journal usage as well. */ SimpleFSQuotaUsage simpleFSGetUserQuotaUsage(); /** simpleFSGetTeamQuotaUsage returns the quota usage for the given team, if the logged-in user has access to that team. Any usage includes local journal usage as well. */ SimpleFSQuotaUsage simpleFSGetTeamQuotaUsage(TeamName teamName); /** simpleFSReset completely resets the KBFS folder referenced in `path`. It should only be called after explicit user confirmation. */ void simpleFSReset(Path path, string tlfID); enum FolderSyncMode { DISABLED_0, ENABLED_1, PARTIAL_2 } record FolderSyncConfig { FolderSyncMode mode; // paths is only used when the mode is PARTIAL array paths; } record FolderSyncConfigAndStatus { FolderSyncConfig config; FolderSyncStatus status; } record FolderSyncConfigAndStatusWithFolder { Folder folder; FolderSyncConfig config; FolderSyncStatus status; } record SyncConfigAndStatusRes { array folders; FolderSyncStatus overallStatus; } // simpleFSFolderSyncConfigAndStatus returns the current sync config for the // folder specified in `path` (e.g., whether syncing is enabled for // that folder). FolderSyncConfigAndStatus simpleFSFolderSyncConfigAndStatus(Path path); // simpleFSSetFolderSyncConfig sets the sync config for the folder // specified in `path`. void simpleFSSetFolderSyncConfig(Path path, FolderSyncConfig config); // simpleFSSyncConfigAndStatus returns the sync config and status // for all syncing folders, as well as an overall status for the whole // device. SyncConfigAndStatusRes simpleFSSyncConfigAndStatus(union{ null, TLFIdentifyBehavior } identifyBehavior); // simpleFSGetFolder is used get TLF metadata for a specific path. It's more // expensive than getting favorites,but works with both any tlf path -- it // doesn't have to be canonical. This allows GUI to query on any TLF path // without having to worrying about canonicalization, or whether a TLF is // already in the favorites or not. record FolderWithFavFlags { Folder folder; boolean isFavorite; boolean isIgnored; boolean isNew; } FolderWithFavFlags simpleFSGetFolder(KBFSPath path); enum KbfsOnlineStatus { OFFLINE_0, TRYING_1, ONLINE_2 } KbfsOnlineStatus simpleFSGetOnlineStatus(); // This is called when GUI learns about a OS level network status change, and // causes mdserver_remote to check reachability with a Dial. Then it either // forces a reconnect, or fast forwards any pending reconnect, depending on // if the Dial succeeds. void simpleFSCheckReachability(); // simpleFSSetDebugLevel sets the vdebug log level. Useful level strings // are defined in libkb/vdebug.go. Any unknown strings will have no effect // on the level (but won't cause an error). void simpleFSSetDebugLevel(string level); record FSSettings { int64 spaceAvailableNotificationThreshold; @lint("ignore") boolean sfmiBannerDismissed; } // simpleFSSettings retrieves the settings for this client. FSSettings simpleFSSettings(); void simpleFSSetNotificationThreshold(int64 threshold); @lint("ignore") void simpleFSSetSfmiBannerDismissed(boolean dismissed); // simpleFSObfuscatePath returns an obfuscated path for the given KBFS path. string simpleFSObfuscatePath(Path path); // simpleFSDeobfuscatePath returns a set of plaintext paths for the given // obfuscated KBFS path. array simpleFSDeobfuscatePath(Path path); record SimpleFSStats { ProcessRuntimeStats processStats; array blockCacheDbStats; array syncCacheDbStats; array runtimeDbStats; } SimpleFSStats simpleFSGetStats(); enum SubscriptionTopic { FAVORITES_0, JOURNAL_STATUS_1, ONLINE_STATUS_2, DOWNLOAD_STATUS_3, FILES_TAB_BADGE_4, OVERALL_SYNC_STATUS_5, SETTINGS_6 } enum PathSubscriptionTopic { CHILDREN_0, STAT_1 } // Caller needs to make sure subscriptionID is unique. Notifications are // delivered through notify_fs. void simpleFSSubscribePath(union{ null, TLFIdentifyBehavior } identifyBehavior, string subscriptionID, string kbfsPath, PathSubscriptionTopic topic, int deduplicateIntervalSecond); void simpleFSSubscribeNonPath(union{ null, TLFIdentifyBehavior } identifyBehavior, string subscriptionID, SubscriptionTopic topic, int deduplicateIntervalSecond); void simpleFSUnsubscribe(union{ null, TLFIdentifyBehavior } identifyBehavior, string subscriptionID); record DownloadInfo { string downloadID; KBFSPath path; string filename; Time startTime; boolean isRegularDownload; } record DownloadState { string downloadID; double progress; Time endEstimate; // localPath is the path to the downloaded file when the download manager // is done with it. This would be a path inside the cache dir for // non-regular downloads, and a path in the Downloads folder if it's a // regular download. string localPath; string error; boolean done; boolean canceled; } record DownloadStatus { array regularDownloadIDs; // the ones showing up in the GUI footer array states; // all downloads including non-regular ones } // returns download ID. isRegularDownload causes moving to the Downloads // folder. This is used by GUI for normal downloads where download entries // appear in the footer. Save on mobile and share to other apps use // isRegularDownload=false, and the download manager doesn't do anything // special after they're done. GUI handles calling the right APIs to save or // share the file. string simpleFSStartDownload(KBFSPath path, boolean isRegularDownload); DownloadInfo simpleFSGetDownloadInfo(string downloadID); DownloadStatus simpleFSGetDownloadStatus(); // Canceling a download multiple times is fine, but canceling a dismissed // download will error. void simpleFSCancelDownload(string downloadID); // Remove a download from the download manager. If the download is still // running, this cancels it as well. Caller should make sure of calling this // when it doesn't care about a download anymore. This includes both regular // and non-regular downloads. void simpleFSDismissDownload(string downloadID); void simpleFSConfigureDownload(string cacheDirOverride, string downloadDirOverride); // FilesTabBadge is the badge we show on the Files tab, to indicate // attention-seeking status across entire KBFS. enum FilesTabBadge { NONE_0, // No badge. // We are stuck in conflict resolution in a TLF. This causes GUI to show a // red upload icon on the Files tab. NOTE that this should have higher // priority than other upload status. UPLOADING_STUCK_1, // We have stuff in the journal for a TLF, but we are currently offline. // This causes GUI to show a gray uplaod icon on the Files tab. AWAITING_UPLOAD_2, // We have stuff in the journal for a TLF, and we're uploading. This causes // GUI to show a blue upload icon on the Files tab. UPLOADING_3 } FilesTabBadge simpleFSGetFilesTabBadge(); enum GUIViewType { DEFAULT_0, TEXT_1, IMAGE_2, AUDIO_3, VIDEO_4, PDF_5 } record GUIFileContext { GUIViewType viewType; string contentType; string url; } GUIFileContext simpleFSGetGUIFileContext(KBFSPath path); void simpleFSUserIn(string clientID); void simpleFSUserOut(string clientID); record SimpleFSSearchHit { string path; } record SimpleFSSearchResults { array hits; int nextResult; // -1 if no more results } SimpleFSSearchResults simpleFSSearch(string query, int numResults, int startingFrom); }