move folder-related code from psynclib to pfolder

This commit is contained in:
Levi Neely 2025-04-18 15:23:50 +02:00
parent 1dd703142d
commit 6540e14732
No known key found for this signature in database
GPG Key ID: AD3B685AA7814409
6 changed files with 209 additions and 239 deletions

View File

@ -42,6 +42,8 @@
#include "plibs.h"
#include "plist.h"
#include "pnetlibs.h"
#include "ppathstatus.h"
#include "prun.h"
#include "psys.h"
#include "ppath.h"
#include "pfile.h"
@ -919,3 +921,146 @@ psync_folder_list_t *pfolder_sync_folders(char *syncTypes) {
return ret;
}
psync_syncid_t pfolder_add_sync(const char *localpath, psync_folderid_t folderid, psync_synctype_t synctype) {
psync_sql_res *res;
char *syncmp;
psync_uint_row row;
psync_str_row srow;
uint64_t perms;
struct stat st;
psync_syncid_t ret;
int unsigned mbedtls_md;
pdbg_logf(D_NOTICE, "Add sync by folder id localpath: [%s]", localpath);
if (pdbg_unlikely(synctype < PSYNC_SYNCTYPE_MIN ||
synctype > PSYNC_SYNCTYPE_MAX))
return_isyncid(PERROR_INVALID_SYNCTYPE);
if (pdbg_unlikely(stat(localpath, &st)) ||
pdbg_unlikely(!pfile_stat_isfolder(&st)))
return_isyncid(PERROR_LOCAL_FOLDER_NOT_FOUND);
if (synctype & PSYNC_DOWNLOAD_ONLY)
mbedtls_md = 7;
else
mbedtls_md = 5;
if (pdbg_unlikely(!pfile_stat_mode_ok(&st, mbedtls_md)))
return_isyncid(PERROR_LOCAL_FOLDER_ACC_DENIED);
syncmp = psync_fs_getmountpoint();
if (syncmp) {
size_t len = strlen(syncmp);
if (!memcmp(syncmp, localpath, len) &&
(localpath[len] == 0 || localpath[len] == '/' ||
localpath[len] == '\\')) {
free(syncmp);
return_isyncid(PERROR_LOCAL_IS_ON_PDRIVE);
}
free(syncmp);
}
res = psql_query("SELECT localpath FROM syncfolder");
if (pdbg_unlikely(!res))
return_isyncid(PERROR_DATABASE_ERROR);
while ((srow = psql_fetch_str(res)))
if (psyncer_str_has_prefix(srow[0], localpath)) {
psql_free(res);
return_isyncid(PERROR_PARENT_OR_SUBFOLDER_ALREADY_SYNCING);
} else if (!strcmp(srow[0], localpath)) {
psql_free(res);
return_isyncid(PERROR_FOLDER_ALREADY_SYNCING);
}
psql_free(res);
if (folderid) {
res = psql_query("SELECT permissions FROM folder WHERE id=?");
if (pdbg_unlikely(!res))
return_isyncid(PERROR_DATABASE_ERROR);
psql_bind_uint(res, 1, folderid);
row = psql_fetch_int(res);
if (pdbg_unlikely(!row)) {
psql_free(res);
return_isyncid(PERROR_REMOTE_FOLDER_NOT_FOUND);
}
perms = row[0];
psql_free(res);
} else
perms = PSYNC_PERM_ALL;
if (pdbg_unlikely((synctype & PSYNC_DOWNLOAD_ONLY &&
(perms & PSYNC_PERM_READ) != PSYNC_PERM_READ) ||
(synctype & PSYNC_UPLOAD_ONLY &&
(perms & PSYNC_PERM_WRITE) != PSYNC_PERM_WRITE)))
return_isyncid(PERROR_REMOTE_FOLDER_ACC_DENIED);
res = psql_prepare(
"INSERT OR IGNORE INTO syncfolder (folderid, localpath, synctype, flags, "
"inode, deviceid) VALUES (?, ?, ?, 0, ?, ?)");
if (pdbg_unlikely(!res))
return_isyncid(PERROR_DATABASE_ERROR);
psql_bind_uint(res, 1, folderid);
psql_bind_str(res, 2, localpath);
psql_bind_uint(res, 3, synctype);
psql_bind_uint(res, 4, pfile_stat_inode(&st));
psql_bind_uint(res, 5, pfile_stat_device(&st));
psql_run(res);
if (pdbg_likely(psql_affected()))
ret = psql_insertid();
else
ret = PSYNC_INVALID_SYNCID;
psql_free(res);
if (ret == PSYNC_INVALID_SYNCID)
return_isyncid(PERROR_FOLDER_ALREADY_SYNCING);
psql_sync();
ppathstatus_reload_syncs();
psyncer_create(ret);
return ret;
}
psync_syncid_t pfolder_add_sync_path(const char *localpath, const char *remotepath, psync_synctype_t synctype) {
psync_folderid_t folderid = pfolder_id(remotepath);
if (pdbg_likely(folderid != PSYNC_INVALID_FOLDERID))
return pfolder_add_sync(localpath, folderid, synctype);
else
return PSYNC_INVALID_SYNCID;
}
int pfolder_add_sync_path_delay(const char *localpath,
const char *remotepath,
psync_synctype_t synctype) {
psync_sql_res *res;
struct stat st;
int unsigned mbedtls_md;
if (pdbg_unlikely(synctype < PSYNC_SYNCTYPE_MIN ||
synctype > PSYNC_SYNCTYPE_MAX)) {
psync_error = PERROR_INVALID_SYNCTYPE;
return -1;
}
if (pdbg_unlikely(stat(localpath, &st)) ||
pdbg_unlikely(!pfile_stat_isfolder(&st))) {
psync_error = PERROR_LOCAL_FOLDER_NOT_FOUND;
return -1;
}
if (synctype & PSYNC_DOWNLOAD_ONLY)
mbedtls_md = 7;
else
mbedtls_md = 5;
if (pdbg_unlikely(!pfile_stat_mode_ok(&st, mbedtls_md))) {
psync_error = PERROR_LOCAL_FOLDER_ACC_DENIED;
return -1;
}
res = psql_prepare("INSERT INTO syncfolderdelayed (localpath, "
"remotepath, synctype) VALUES (?, ?, ?)");
psql_bind_str(res, 1, localpath);
psql_bind_str(res, 2, remotepath);
psql_bind_uint(res, 3, synctype);
psql_run_free(res);
psql_sync();
if (pstatus_get(PSTATUS_TYPE_ONLINE) == PSTATUS_ONLINE_ONLINE)
prun_thread("check delayed syncs", psyncer_check_delayed);
return 0;
}
pfolder_list_t *pfolder_remote_folders_path(const char *remotepath, psync_listtype_t listtype) {
psync_folderid_t folderid = pfolder_id(remotepath);
if (folderid != PSYNC_INVALID_FOLDERID)
return pfolder_remote_folders(folderid, listtype);
else
return NULL;
}

View File

@ -52,6 +52,19 @@
#define PSYNC_FOLDER_FLAG_BACKUP_ROOT 32
#define PSYNC_FOLDER_FLAG_BACKUP 64
#define PSYNC_DOWNLOAD_ONLY 1
#define PSYNC_UPLOAD_ONLY 2
#define PSYNC_FULL 3
#define PSYNC_BACKUPS 7
#define PSYNC_STR_DOWNLOAD_ONLY "1"
#define PSYNC_STR_UPLOAD_ONLY "2"
#define PSYNC_STR_FULL "3"
#define PSYNC_STR_ALLSYNCS "1,2,3"
#define PSYNC_STR_BACKUPS "7"
#define PSYNC_SYNCTYPE_MIN 1
#define PSYNC_SYNCTYPE_MAX 7
// limitation: path length of 255, plus null terminator.
#define PSYNC_MAX_PATH_LENGTH 256
@ -140,9 +153,40 @@ char *pfolder_lpath_lfile(psync_fileid_t localfileid, size_t *retlen);
pfolder_list_t *pfolder_remote_folders(psync_folderid_t folderid, psync_listtype_t listtype);
pfolder_list_t *pfolder_local_folders(const char *path, psync_listtype_t listtype) PSYNC_NONNULL(1);
pentry_t *pfolder_stat(const char *remotepath);
// Gets a list of local syncs, based on their type. Type empty string means all.
// Accepts comma separated list of types example: 1,2,3
psync_folder_list_t *pfolder_sync_folders(char *syncTypes);
psync_folderid_t pfolder_db_wait(psync_folderid_t folderid);
/* Use the following functions to list local or remote folders.
* For local folders fileid and folderid will be set to a value that
* should in general uniquely identify the entry (e.g. inode number).
* Remote paths use slashes (/) and start with one.
* In case of success the returned folder list is to be freed with a
* single call to free(). In case of error NULL is returned. Parameter
* listtype should be one of PLIST_FILES, PLIST_FOLDERS or PLIST_ALL.
*
* Folders do not contain "." or ".." entries.
*
* All files/folders are listed regardless if they are to be ignored
* based on 'ignorepatterns' setting. If needed, pass the names to
* psync_is_name_to_ignore that returns 1 for files that are to be
* ignored and 0 for others.
*
* Remote root folder has 0 folderid.
*/
// Adds a sync folder to the database. localpath is the path on the
// local machine where pcloudcc is running. remotepath is the path in
// pcloud remote storage (it must already exist). synctype may be
// PSYNC_FULL, PSYNC_DOWNLOAD_ONLY, or PSYNC_UPLOAD_ONLY.
psync_syncid_t pfolder_add_sync_path(const char *localpath, const char *remotepath, psync_synctype_t synctype);
psync_syncid_t pfolder_add_sync(const char *localpath, psync_folderid_t folderid, psync_synctype_t synctype);
int pfolder_add_sync_path_delay(const char *localpath, const char *remotepath, psync_synctype_t synctype);
pfolder_list_t *pfolder_remote_folders_path(const char *remotepath, psync_listtype_t listtype);
// "syncer" API (impl. psync.c)
void psyncer_check_delayed();
void psyncer_create(psync_syncid_t syncid);
@ -158,4 +202,6 @@ void psyncer_init();
int psyncer_str_has_prefix(const char *str1, const char *str2);
int psyncer_str_starts_with(const char *str1, const char *str2);
#endif

View File

@ -109,12 +109,6 @@ static inline int psync_status_is_offline() {
return pstatus_get(PSTATUS_TYPE_ONLINE) == PSTATUS_ONLINE_OFFLINE;
}
#define return_isyncid(err) \
do { \
psync_error = err; \
return PSYNC_INVALID_SYNCID; \
} while (0)
uint32_t psync_get_last_error() { return psync_error; }
void psync_set_database_path(const char *databasepath) {
@ -644,144 +638,6 @@ void psync_tfa_set_code(const char *code, int trusted, int is_recovery) {
pstatus_set(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
}
psync_syncid_t psync_add_sync_by_path(const char *localpath,
const char *remotepath,
psync_synctype_t synctype) {
psync_folderid_t folderid = pfolder_id(remotepath);
if (pdbg_likely(folderid != PSYNC_INVALID_FOLDERID))
return psync_add_sync_by_folderid(localpath, folderid, synctype);
else
return PSYNC_INVALID_SYNCID;
}
psync_syncid_t psync_add_sync_by_folderid(const char *localpath,
psync_folderid_t folderid,
psync_synctype_t synctype) {
psync_sql_res *res;
char *syncmp;
psync_uint_row row;
psync_str_row srow;
uint64_t perms;
struct stat st;
psync_syncid_t ret;
int unsigned mbedtls_md;
pdbg_logf(D_NOTICE, "Add sync by folder id localpath: [%s]", localpath);
if (pdbg_unlikely(synctype < PSYNC_SYNCTYPE_MIN ||
synctype > PSYNC_SYNCTYPE_MAX))
return_isyncid(PERROR_INVALID_SYNCTYPE);
if (pdbg_unlikely(stat(localpath, &st)) ||
pdbg_unlikely(!pfile_stat_isfolder(&st)))
return_isyncid(PERROR_LOCAL_FOLDER_NOT_FOUND);
if (synctype & PSYNC_DOWNLOAD_ONLY)
mbedtls_md = 7;
else
mbedtls_md = 5;
if (pdbg_unlikely(!pfile_stat_mode_ok(&st, mbedtls_md)))
return_isyncid(PERROR_LOCAL_FOLDER_ACC_DENIED);
syncmp = psync_fs_getmountpoint();
if (syncmp) {
size_t len = strlen(syncmp);
if (!memcmp(syncmp, localpath, len) &&
(localpath[len] == 0 || localpath[len] == '/' ||
localpath[len] == '\\')) {
free(syncmp);
return_isyncid(PERROR_LOCAL_IS_ON_PDRIVE);
}
free(syncmp);
}
res = psql_query("SELECT localpath FROM syncfolder");
if (pdbg_unlikely(!res))
return_isyncid(PERROR_DATABASE_ERROR);
while ((srow = psql_fetch_str(res)))
if (psyncer_str_has_prefix(srow[0], localpath)) {
psql_free(res);
return_isyncid(PERROR_PARENT_OR_SUBFOLDER_ALREADY_SYNCING);
} else if (!strcmp(srow[0], localpath)) {
psql_free(res);
return_isyncid(PERROR_FOLDER_ALREADY_SYNCING);
}
psql_free(res);
if (folderid) {
res = psql_query("SELECT permissions FROM folder WHERE id=?");
if (pdbg_unlikely(!res))
return_isyncid(PERROR_DATABASE_ERROR);
psql_bind_uint(res, 1, folderid);
row = psql_fetch_int(res);
if (pdbg_unlikely(!row)) {
psql_free(res);
return_isyncid(PERROR_REMOTE_FOLDER_NOT_FOUND);
}
perms = row[0];
psql_free(res);
} else
perms = PSYNC_PERM_ALL;
if (pdbg_unlikely((synctype & PSYNC_DOWNLOAD_ONLY &&
(perms & PSYNC_PERM_READ) != PSYNC_PERM_READ) ||
(synctype & PSYNC_UPLOAD_ONLY &&
(perms & PSYNC_PERM_WRITE) != PSYNC_PERM_WRITE)))
return_isyncid(PERROR_REMOTE_FOLDER_ACC_DENIED);
res = psql_prepare(
"INSERT OR IGNORE INTO syncfolder (folderid, localpath, synctype, flags, "
"inode, deviceid) VALUES (?, ?, ?, 0, ?, ?)");
if (pdbg_unlikely(!res))
return_isyncid(PERROR_DATABASE_ERROR);
psql_bind_uint(res, 1, folderid);
psql_bind_str(res, 2, localpath);
psql_bind_uint(res, 3, synctype);
psql_bind_uint(res, 4, pfile_stat_inode(&st));
psql_bind_uint(res, 5, pfile_stat_device(&st));
psql_run(res);
if (pdbg_likely(psql_affected()))
ret = psql_insertid();
else
ret = PSYNC_INVALID_SYNCID;
psql_free(res);
if (ret == PSYNC_INVALID_SYNCID)
return_isyncid(PERROR_FOLDER_ALREADY_SYNCING);
psql_sync();
ppathstatus_reload_syncs();
psyncer_create(ret);
return ret;
}
int psync_add_sync_by_path_delayed(const char *localpath,
const char *remotepath,
psync_synctype_t synctype) {
psync_sql_res *res;
struct stat st;
int unsigned mbedtls_md;
if (pdbg_unlikely(synctype < PSYNC_SYNCTYPE_MIN ||
synctype > PSYNC_SYNCTYPE_MAX)) {
psync_error = PERROR_INVALID_SYNCTYPE;
return -1;
}
if (pdbg_unlikely(stat(localpath, &st)) ||
pdbg_unlikely(!pfile_stat_isfolder(&st))) {
psync_error = PERROR_LOCAL_FOLDER_NOT_FOUND;
return -1;
}
if (synctype & PSYNC_DOWNLOAD_ONLY)
mbedtls_md = 7;
else
mbedtls_md = 5;
if (pdbg_unlikely(!pfile_stat_mode_ok(&st, mbedtls_md))) {
psync_error = PERROR_LOCAL_FOLDER_ACC_DENIED;
return -1;
}
res = psql_prepare("INSERT INTO syncfolderdelayed (localpath, "
"remotepath, synctype) VALUES (?, ?, ?)");
psql_bind_str(res, 1, localpath);
psql_bind_str(res, 2, remotepath);
psql_bind_uint(res, 3, synctype);
psql_run_free(res);
psql_sync();
if (pstatus_get(PSTATUS_TYPE_ONLINE) == PSTATUS_ONLINE_ONLINE)
prun_thread("check delayed syncs", psyncer_check_delayed);
return 0;
}
int psync_change_synctype(psync_syncid_t syncid, psync_synctype_t synctype) {
psync_sql_res *res;
psync_variant_row row;
@ -934,10 +790,6 @@ int psync_delete_sync(psync_syncid_t syncid) {
}
}
psync_folder_list_t *psync_get_sync_list() {
return pfolder_sync_folders(PSYNC_STR_ALLSYNCS);
}
psuggested_folders_t *psync_get_sync_suggestions() {
char *home;
psuggested_folders_t *ret;
@ -952,26 +804,6 @@ psuggested_folders_t *psync_get_sync_suggestions() {
}
}
pfolder_list_t *psync_list_local_folder_by_path(const char *localpath,
psync_listtype_t listtype) {
return pfolder_local_folders(localpath, listtype);
}
pfolder_list_t *psync_list_remote_folder_by_path(const char *remotepath,
psync_listtype_t listtype) {
psync_folderid_t folderid = pfolder_id(remotepath);
if (folderid != PSYNC_INVALID_FOLDERID)
return pfolder_remote_folders(folderid, listtype);
else
return NULL;
}
pfolder_list_t *
psync_list_remote_folder_by_folderid(psync_folderid_t folderid,
psync_listtype_t listtype) {
return pfolder_remote_folders(folderid, listtype);
}
pentry_t *psync_stat_path(const char *remotepath) {
return pfolder_stat(remotepath);
}
@ -2468,12 +2300,6 @@ int psync_is_folder_syncable(char *localPath, char **errMsg) {
return 0;
}
psync_folder_list_t *psync_get_syncs_bytype(const char *syncType) {
pdbg_logf(D_NOTICE, "Get syncs type: [%s]", syncType);
return pfolder_sync_folders((char *)syncType);
}
psync_folderid_t create_bup_mach_folder(char **msgErr) {
binresult *rootFolIdObj;
binresult *retData;
@ -2583,7 +2409,7 @@ int psync_create_backup(char *path, char **errMsg) {
folId = (binresult *)papi_find_result2(retData, FOLDER_ID, PARAM_NUM);
syncFId = psync_add_sync_by_folderid(path, folId->num, PSYNC_BACKUPS);
syncFId = pfolder_add_sync(path, folId->num, PSYNC_BACKUPS);
free(retData);

View File

@ -176,22 +176,6 @@ typedef struct {
#define PNOTIFICATION_ACTION_GO_TO_URL 2
#define PNOTIFICATION_ACTION_SHARE_REQUEST 3
// Sync constants
#define PSYNC_DOWNLOAD_ONLY 1
#define PSYNC_UPLOAD_ONLY 2
#define PSYNC_FULL 3
#define PSYNC_BACKUPS 7
#define PSYNC_STR_DOWNLOAD_ONLY "1"
#define PSYNC_STR_UPLOAD_ONLY "2"
#define PSYNC_STR_FULL "3"
#define PSYNC_STR_ALLSYNCS "1,2,3"
#define PSYNC_STR_BACKUPS "7"
#define PSYNC_SYNCTYPE_MIN 1
#define PSYNC_SYNCTYPE_MAX 7
// Sync constants end
#define PERROR_LOCAL_FOLDER_NOT_FOUND 1
#define PERROR_REMOTE_FOLDER_NOT_FOUND 2
#define PERROR_DATABASE_OPEN 3
@ -715,28 +699,14 @@ void psync_tfa_set_code(const char *code, int trusted, int is_recovery);
*
*/
psync_syncid_t psync_add_sync_by_path(const char *localpath,
const char *remotepath,
psync_synctype_t synctype);
psync_syncid_t psync_add_sync_by_folderid(const char *localpath,
psync_folderid_t folderid,
psync_synctype_t synctype);
int psync_add_sync_by_path_delayed(const char *localpath,
const char *remotepath,
psync_synctype_t synctype);
int psync_change_synctype(psync_syncid_t syncid, psync_synctype_t synctype);
int psync_delete_sync(psync_syncid_t syncid);
psync_folder_list_t *psync_get_sync_list();
psuggested_folders_t *psync_get_sync_suggestions();
// Backups
int psync_is_folder_syncable(char *localPath, char **errMsg);
// Gets a list of local syncs, based on their type. Type empty string means all.
// Accepts comma separated list of types example: 1,2,3
psync_folder_list_t *psync_get_syncs_bytype(const char *syncType);
// Create a backup for the local folder defined by path parameter.
int psync_create_backup(char *path, char **err);
@ -770,30 +740,6 @@ void psync_async_ui_callback(void *ptr);
// Backups
/* Use the following functions to list local or remote folders.
* For local folders fileid and folderid will be set to a value that
* should in general uniquely identify the entry (e.g. inode number).
* Remote paths use slashes (/) and start with one.
* In case of success the returned folder list is to be freed with a
* single call to free(). In case of error NULL is returned. Parameter
* listtype should be one of PLIST_FILES, PLIST_FOLDERS or PLIST_ALL.
*
* Folders do not contain "." or ".." entries.
*
* All files/folders are listed regardless if they are to be ignored
* based on 'ignorepatterns' setting. If needed, pass the names to
* psync_is_name_to_ignore that returns 1 for files that are to be
* ignored and 0 for others.
*
* Remote root folder has 0 folderid.
*/
pfolder_list_t *psync_list_local_folder_by_path(const char *localpath,
psync_listtype_t listtype);
pfolder_list_t *psync_list_remote_folder_by_path(const char *remotepath,
psync_listtype_t listtype);
pfolder_list_t *psync_list_remote_folder_by_folderid(psync_folderid_t folderid,
psync_listtype_t listtype);
pentry_t *psync_stat_path(const char *remotepath);
psync_folderid_t psync_get_fsfolderid_by_path(const char *path,
uint32_t *pflags,

View File

@ -18,6 +18,12 @@ extern "C" {
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
#define return_isyncid(err) \
do { \
psync_error = err; \
return PSYNC_INVALID_SYNCID; \
} while (0)
extern const char base64_table[];
void putil_wipe(void *mem, size_t sz);

View File

@ -37,13 +37,14 @@
#include <time.h>
#include <unistd.h>
#include "pcryptofolder.h"
#include "prpc.h"
#include "psynclib.h"
#include "pshm.h"
#include "pdevice.h"
#include "pcommands.h"
#include "putil.h"
#include "pclsync/pcryptofolder.h"
#include "pclsync/pfoldersync.h"
#include "pclsync/prpc.h"
#include "pclsync/psynclib.h"
#include "pclsync/pshm.h"
#include "pclsync/pdevice.h"
#include "pclsync/pcommands.h"
#include "pclsync/putil.h"
#include "pclsync_lib.h"
@ -390,7 +391,7 @@ int clib::pclsync_lib::add_sync_folder(const char *combined_path) {
std::string localpath = combined.substr(0, delimiter_pos);
std::string remotepath = combined.substr(delimiter_pos + 1);
psync_syncid_t syncid = psync_add_sync_by_path(localpath.c_str(), remotepath.c_str(), PSYNC_FULL);
psync_syncid_t syncid = pfolder_add_sync_path(localpath.c_str(), remotepath.c_str(), PSYNC_FULL);
pthread_mutex_lock(&mtx);
if (syncid == PSYNC_INVALID_SYNCID) {
@ -419,7 +420,7 @@ int clib::pclsync_lib::list_sync_folders(const char *unused) {
psync_folder_list_t *folders;
size_t folderssz;
folders = psync_get_sync_list();
folders = pfolder_sync_folders((char *)PSYNC_STR_ALLSYNCS);
if (!folders) {
return -1;
}
@ -510,4 +511,4 @@ void clib::pclsync_lib::wipe(std::string& s) {
size_t sz = s.size();
putil_wipe(mem, sz);
s.clear();
}
}