1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 #ifndef SEAF_FILE_MGR_H
4 #define SEAF_FILE_MGR_H
5 
6 #include <glib.h>
7 
8 #include "seafile-object.h"
9 
10 #include "obj-store.h"
11 
12 #include "cdc/cdc.h"
13 #include "../common/seafile-crypt.h"
14 
15 #define CURRENT_DIR_OBJ_VERSION 1
16 #define CURRENT_SEAFILE_OBJ_VERSION 1
17 
18 typedef struct _SeafFSManager SeafFSManager;
19 typedef struct _SeafFSObject SeafFSObject;
20 typedef struct _Seafile Seafile;
21 typedef struct _SeafDir SeafDir;
22 typedef struct _SeafDirent SeafDirent;
23 
24 typedef enum {
25     SEAF_METADATA_TYPE_INVALID,
26     SEAF_METADATA_TYPE_FILE,
27     SEAF_METADATA_TYPE_LINK,
28     SEAF_METADATA_TYPE_DIR,
29 } SeafMetadataType;
30 
31 /* Common to seafile and seafdir objects. */
32 struct _SeafFSObject {
33     int type;
34 };
35 
36 struct _Seafile {
37     SeafFSObject object;
38     int         version;
39     char        file_id[41];
40     guint64     file_size;
41     guint32     n_blocks;
42     char        **blk_sha1s;
43     int         ref_count;
44 };
45 
46 typedef struct SearchResult {
47     char *path;
48     gint64 size;
49     gint64 mtime;
50     gboolean is_dir;
51 } SearchResult;
52 
53 void
54 seafile_ref (Seafile *seafile);
55 
56 void
57 seafile_unref (Seafile *seafile);
58 
59 int
60 seafile_save (SeafFSManager *fs_mgr,
61               const char *repo_id,
62               int version,
63               Seafile *file);
64 
65 #define SEAF_DIR_NAME_LEN 256
66 
67 struct _SeafDirent {
68     int        version;
69     guint32    mode;
70     char       id[41];
71     guint32    name_len;
72     char       *name;
73 
74     /* attributes for version > 0 */
75     gint64     mtime;
76     char       *modifier;       /* for files only */
77     gint64     size;            /* for files only */
78 };
79 
80 struct _SeafDir {
81     SeafFSObject object;
82     int    version;
83     char   dir_id[41];
84     GList *entries;
85 
86     /* data in on-disk format. */
87     void  *ondisk;
88     int    ondisk_size;
89 };
90 
91 SeafDir *
92 seaf_dir_new (const char *id, GList *entries, int version);
93 
94 void
95 seaf_dir_free (SeafDir *dir);
96 
97 SeafDir *
98 seaf_dir_from_data (const char *dir_id, uint8_t *data, int len,
99                     gboolean is_json);
100 
101 void *
102 seaf_dir_to_data (SeafDir *dir, int *len);
103 
104 int
105 seaf_dir_save (SeafFSManager *fs_mgr,
106                const char *repo_id,
107                int version,
108                SeafDir *dir);
109 
110 SeafDirent *
111 seaf_dirent_new (int version, const char *sha1, int mode, const char *name,
112                  gint64 mtime, const char *modifier, gint64 size);
113 
114 void
115 seaf_dirent_free (SeafDirent *dent);
116 
117 SeafDirent *
118 seaf_dirent_dup (SeafDirent *dent);
119 
120 int
121 seaf_metadata_type_from_data (const char *obj_id,
122                               uint8_t *data, int len, gboolean is_json);
123 
124 /* Parse an fs object without knowing its type. */
125 SeafFSObject *
126 seaf_fs_object_from_data (const char *obj_id,
127                           uint8_t *data, int len,
128                           gboolean is_json);
129 
130 void
131 seaf_fs_object_free (SeafFSObject *obj);
132 
133 typedef struct {
134     /* TODO: GHashTable may be inefficient when we have large number of IDs. */
135     GHashTable  *block_hash;
136     GPtrArray   *block_ids;
137     uint32_t     n_blocks;
138     uint32_t     n_valid_blocks;
139 } BlockList;
140 
141 BlockList *
142 block_list_new ();
143 
144 void
145 block_list_free (BlockList *bl);
146 
147 void
148 block_list_insert (BlockList *bl, const char *block_id);
149 
150 /* Return a blocklist containing block ids which are in @bl1 but
151  * not in @bl2.
152  */
153 BlockList *
154 block_list_difference (BlockList *bl1, BlockList *bl2);
155 
156 struct _SeafileSession;
157 
158 typedef struct _SeafFSManagerPriv SeafFSManagerPriv;
159 
160 struct _SeafFSManager {
161     struct _SeafileSession *seaf;
162 
163     struct SeafObjStore *obj_store;
164 
165     SeafFSManagerPriv *priv;
166 };
167 
168 SeafFSManager *
169 seaf_fs_manager_new (struct _SeafileSession *seaf,
170                      const char *seaf_dir);
171 
172 int
173 seaf_fs_manager_init (SeafFSManager *mgr);
174 
175 #ifndef SEAFILE_SERVER
176 
177 int
178 seaf_fs_manager_checkout_file (SeafFSManager *mgr,
179                                const char *repo_id,
180                                int version,
181                                const char *file_id,
182                                const char *file_path,
183                                guint32 mode,
184                                guint64 mtime,
185                                struct SeafileCrypt *crypt,
186                                const char *in_repo_path,
187                                const char *conflict_head_id,
188                                gboolean force_conflict,
189                                gboolean *conflicted,
190                                const char *email);
191 
192 #endif  /* not SEAFILE_SERVER */
193 
194 /**
195  * Check in blocks and create seafile/symlink object.
196  * Returns sha1 id for the seafile/symlink object in @sha1 parameter.
197  */
198 int
199 seaf_fs_manager_index_file_blocks (SeafFSManager *mgr,
200                                    const char *repo_id,
201                                    int version,
202                                    GList *paths,
203                                    GList *blockids,
204                                    unsigned char sha1[],
205                                    gint64 file_size);
206 
207 int
208 seaf_fs_manager_index_raw_blocks (SeafFSManager *mgr,
209                                   const char *repo_id,
210                                   int version,
211                                   GList *paths,
212                                   GList *blockids);
213 
214 int
215 seaf_fs_manager_index_existed_file_blocks (SeafFSManager *mgr,
216                                            const char *repo_id,
217                                            int version,
218                                            GList *blockids,
219                                            unsigned char sha1[],
220                                            gint64 file_size);
221 int
222 seaf_fs_manager_index_blocks (SeafFSManager *mgr,
223                               const char *repo_id,
224                               int version,
225                               const char *file_path,
226                               unsigned char sha1[],
227                               gint64 *size,
228                               SeafileCrypt *crypt,
229                               gboolean write_data,
230                               gboolean use_cdc,
231                               gint64 *indexed);
232 
233 Seafile *
234 seaf_fs_manager_get_seafile (SeafFSManager *mgr,
235                              const char *repo_id,
236                              int version,
237                              const char *file_id);
238 
239 SeafDir *
240 seaf_fs_manager_get_seafdir (SeafFSManager *mgr,
241                              const char *repo_id,
242                              int version,
243                              const char *dir_id);
244 
245 /* Make sure entries in the returned dir is sorted in descending order.
246  */
247 SeafDir *
248 seaf_fs_manager_get_seafdir_sorted (SeafFSManager *mgr,
249                                     const char *repo_id,
250                                     int version,
251                                     const char *dir_id);
252 
253 SeafDir *
254 seaf_fs_manager_get_seafdir_sorted_by_path (SeafFSManager *mgr,
255                                             const char *repo_id,
256                                             int version,
257                                             const char *root_id,
258                                             const char *path);
259 
260 int
261 seaf_fs_manager_populate_blocklist (SeafFSManager *mgr,
262                                     const char *repo_id,
263                                     int version,
264                                     const char *root_id,
265                                     BlockList *bl);
266 
267 /*
268  * For dir object, set *stop to TRUE to stop traversing the subtree.
269  */
270 typedef gboolean (*TraverseFSTreeCallback) (SeafFSManager *mgr,
271                                             const char *repo_id,
272                                             int version,
273                                             const char *obj_id,
274                                             int type,
275                                             void *user_data,
276                                             gboolean *stop);
277 
278 int
279 seaf_fs_manager_traverse_tree (SeafFSManager *mgr,
280                                const char *repo_id,
281                                int version,
282                                const char *root_id,
283                                TraverseFSTreeCallback callback,
284                                void *user_data,
285                                gboolean skip_errors);
286 
287 typedef gboolean (*TraverseFSPathCallback) (SeafFSManager *mgr,
288                                             const char *path,
289                                             SeafDirent *dent,
290                                             void *user_data,
291                                             gboolean *stop);
292 
293 int
294 seaf_fs_manager_traverse_path (SeafFSManager *mgr,
295                                const char *repo_id,
296                                int version,
297                                const char *root_id,
298                                const char *dir_path,
299                                TraverseFSPathCallback callback,
300                                void *user_data);
301 
302 gboolean
303 seaf_fs_manager_object_exists (SeafFSManager *mgr,
304                                const char *repo_id,
305                                int version,
306                                const char *id);
307 
308 void
309 seaf_fs_manager_delete_object (SeafFSManager *mgr,
310                                const char *repo_id,
311                                int version,
312                                const char *id);
313 
314 gint64
315 seaf_fs_manager_get_file_size (SeafFSManager *mgr,
316                                const char *repo_id,
317                                int version,
318                                const char *file_id);
319 
320 gint64
321 seaf_fs_manager_get_fs_size (SeafFSManager *mgr,
322                              const char *repo_id,
323                              int version,
324                              const char *root_id);
325 
326 #ifndef SEAFILE_SERVER
327 int
328 seafile_write_chunk (const char *repo_id,
329                      int version,
330                      CDCDescriptor *chunk,
331                      SeafileCrypt *crypt,
332                      uint8_t *checksum,
333                      gboolean write_data);
334 int
335 seafile_check_write_chunk (CDCDescriptor *chunk,
336                            uint8_t *sha1,
337                            gboolean write_data);
338 #endif /* SEAFILE_SERVER */
339 
340 uint32_t
341 calculate_chunk_size (uint64_t total_size);
342 
343 int
344 seaf_fs_manager_count_fs_files (SeafFSManager *mgr,
345                                 const char *repo_id,
346                                 int version,
347                                 const char *root_id);
348 
349 SeafDir *
350 seaf_fs_manager_get_seafdir_by_path(SeafFSManager *mgr,
351                                     const char *repo_id,
352                                     int version,
353                                     const char *root_id,
354                                     const char *path,
355                                     GError **error);
356 char *
357 seaf_fs_manager_get_seafile_id_by_path (SeafFSManager *mgr,
358                                         const char *repo_id,
359                                         int version,
360                                         const char *root_id,
361                                         const char *path,
362                                         GError **error);
363 
364 char *
365 seaf_fs_manager_path_to_obj_id (SeafFSManager *mgr,
366                                 const char *repo_id,
367                                 int version,
368                                 const char *root_id,
369                                 const char *path,
370                                 guint32 *mode,
371                                 GError **error);
372 
373 char *
374 seaf_fs_manager_get_seafdir_id_by_path (SeafFSManager *mgr,
375                                         const char *repo_id,
376                                         int version,
377                                         const char *root_id,
378                                         const char *path,
379                                         GError **error);
380 
381 SeafDirent *
382 seaf_fs_manager_get_dirent_by_path (SeafFSManager *mgr,
383                                     const char *repo_id,
384                                     int version,
385                                     const char *root_id,
386                                     const char *path,
387                                     GError **error);
388 
389 /* Check object integrity. */
390 
391 gboolean
392 seaf_fs_manager_verify_seafdir (SeafFSManager *mgr,
393                                 const char *repo_id,
394                                 int version,
395                                 const char *dir_id,
396                                 gboolean verify_id,
397                                 gboolean *io_error);
398 
399 gboolean
400 seaf_fs_manager_verify_seafile (SeafFSManager *mgr,
401                                 const char *repo_id,
402                                 int version,
403                                 const char *file_id,
404                                 gboolean verify_id,
405                                 gboolean *io_error);
406 
407 gboolean
408 seaf_fs_manager_verify_object (SeafFSManager *mgr,
409                                const char *repo_id,
410                                int version,
411                                const char *obj_id,
412                                gboolean verify_id,
413                                gboolean *io_error);
414 
415 int
416 dir_version_from_repo_version (int repo_version);
417 
418 int
419 seafile_version_from_repo_version (int repo_version);
420 
421 struct _CDCFileDescriptor;
422 void
423 seaf_fs_manager_calculate_seafile_id_json (int repo_version,
424                                            struct _CDCFileDescriptor *cdc,
425                                            guint8 *file_id_sha1);
426 
427 int
428 seaf_fs_manager_remove_store (SeafFSManager *mgr,
429                               const char *store_id);
430 
431 GObject *
432 seaf_fs_manager_get_file_count_info_by_path (SeafFSManager *mgr,
433                                              const char *repo_id,
434                                              int version,
435                                              const char *root_id,
436                                              const char *path,
437                                              GError **error);
438 
439 GList *
440 seaf_fs_manager_search_files (SeafFSManager *mgr,
441                               const char *repo_id,
442                               const char *str);
443 
444 #endif
445