pcloudcc-lneely/pclsync/pfs_helpers.c

149 lines
5.1 KiB
C

/*
* pfs_helpers.c — pure row→stat converters and overlay helpers.
*
* Dependencies: pfstasks_tree.c (for find_* functions), pfscrypto.h (for
* pfs_crpt_plain_size on encrypted files), plibs.h (psync_get_number macro).
* No psql calls, no FUSE, no network.
*/
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include "pdbg.h"
#include "pfscrypto.h"
#include "pfs_helpers.h"
#include "plibs.h" /* psync_get_number */
#include "ptimer.h" /* ptimer_time */
/* ------------------------------------------------------------------ */
/* Globals — initialised here; overwritten by pfs.c at mount time */
/* ------------------------------------------------------------------ */
uid_t pfs_stat_uid = 0;
gid_t pfs_stat_gid = 0;
/* ------------------------------------------------------------------ */
/* Row → stat converters */
/* ------------------------------------------------------------------ */
void pfs_row_to_folder_stat(psync_variant_row row, struct stat *stbuf) {
psync_folderid_t folderid;
uint64_t mtime;
psync_fstask_folder_t *folder;
folderid = (psync_folderid_t)psync_get_number(row[0]);
mtime = psync_get_number(row[3]);
folder = pfs_task_get_folder_tasks_rdlocked(folderid);
if (folder && folder->mtime)
mtime = folder->mtime;
memset(stbuf, 0, sizeof(*stbuf));
stbuf->st_ino = PFS_FOLDERID_TO_INODE(folderid);
stbuf->st_ctime = (time_t)mtime;
stbuf->st_mtime = (time_t)mtime;
stbuf->st_atime = (time_t)mtime;
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = (nlink_t)(psync_get_number(row[4]) + 2);
stbuf->st_size = PFS_FS_BLOCK_SIZE;
stbuf->st_blocks = 1;
stbuf->st_blksize = PFS_FS_BLOCK_SIZE;
stbuf->st_uid = pfs_stat_uid;
stbuf->st_gid = pfs_stat_gid;
}
void pfs_row_to_file_stat(psync_variant_row row, struct stat *stbuf,
uint32_t flags) {
uint64_t size = psync_get_number(row[1]);
psync_fileid_t fileid = (psync_fileid_t)psync_get_number(row[4]);
if (flags & PSYNC_FOLDER_FLAG_ENCRYPTED)
size = pfs_crpt_plain_size(size);
memset(stbuf, 0, sizeof(*stbuf));
stbuf->st_ino = PFS_FILEID_TO_INODE(fileid);
stbuf->st_ctime = (time_t)psync_get_number(row[3]);
stbuf->st_mtime = stbuf->st_ctime;
stbuf->st_atime = stbuf->st_ctime;
stbuf->st_mode = S_IFREG | 0644;
stbuf->st_nlink = 1;
stbuf->st_size = (off_t)size;
stbuf->st_blocks = (blkcnt_t)((size + 511) / 512);
stbuf->st_blksize = PFS_FS_BLOCK_SIZE;
stbuf->st_uid = pfs_stat_uid;
stbuf->st_gid = pfs_stat_gid;
}
void pfs_mkdir_to_folder_stat(psync_fstask_mkdir_t *mk, struct stat *stbuf) {
uint64_t mtime;
psync_fstask_folder_t *folder;
folder = pfs_task_get_folder_tasks_rdlocked(mk->folderid);
mtime = (folder && folder->mtime) ? folder->mtime : (uint64_t)mk->mtime;
memset(stbuf, 0, sizeof(*stbuf));
stbuf->st_ino = (mk->folderid >= 0)
? PFS_FOLDERID_TO_INODE(mk->folderid)
: PFS_TASKID_TO_INODE(-mk->folderid);
stbuf->st_ctime = (time_t)mtime;
stbuf->st_mtime = (time_t)mtime;
stbuf->st_atime = (time_t)mtime;
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = (nlink_t)(mk->subdircnt + 2);
stbuf->st_size = PFS_FS_BLOCK_SIZE;
stbuf->st_blocks = 1;
stbuf->st_blksize = PFS_FS_BLOCK_SIZE;
stbuf->st_uid = pfs_stat_uid;
stbuf->st_gid = pfs_stat_gid;
}
/* ------------------------------------------------------------------ */
/* Task overlay */
/* ------------------------------------------------------------------ */
int pfs_apply_task_overlay(struct stat *stbuf,
psync_fstask_folder_t *folder,
const char *name, uint32_t flags) {
if (!folder)
return 0;
/* Pending mkdir: show the directory */
psync_fstask_mkdir_t *mk = pfs_task_find_mkdir(folder, name, 0);
if (mk) {
if (mk->flags & PSYNC_FOLDER_FLAG_INVISIBLE)
return -1;
pfs_mkdir_to_folder_stat(mk, stbuf);
return 1;
}
/* Pending rmdir: hide the directory */
if (pfs_task_find_rmdir(folder, name, 0))
return -1;
/* Pending unlink: hide the file */
if (pfs_task_find_unlink(folder, name, 0))
return -1;
/* Pending creat with fileid==0 (new local file, no SQL needed):
* return a minimal stat for the new file. */
psync_fstask_creat_t *cr = pfs_task_find_creat(folder, name, 0);
if (cr && cr->fileid == 0) {
time_t now = ptimer_time();
memset(stbuf, 0, sizeof(*stbuf));
stbuf->st_ctime = now;
stbuf->st_mtime = now;
stbuf->st_atime = now;
stbuf->st_mode = S_IFREG | 0644;
stbuf->st_nlink = 1;
stbuf->st_size = 0;
stbuf->st_blocks = 0;
stbuf->st_blksize = PFS_FS_BLOCK_SIZE;
stbuf->st_uid = pfs_stat_uid;
stbuf->st_gid = pfs_stat_gid;
return 2;
}
return 0;
}