Files
FastSync/src/shared/utils.c
T
TapTap 4a1e666365 refactor: merge File/FileReceive, add optional metadata transfer with -M flag
- Remove FileReceive struct; use File everywhere with nullable FileMetadata*
- Remove struct stat from File; file size lives in Data->size (data_create_reserve)
- Add FileMetadata struct (mode, uid, gid, mtime) sent conditionally over wire
- Add -M / --preserve flag to client
- Restore permissions, ownership, timestamps on disk write
- Wire format uses per-file present flag for metadata (zero overhead when off)
2026-07-05 20:21:46 +02:00

99 lines
2.7 KiB
C

#include "utils.h"
#include "libgen.h"
#include "sys/stat.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
void mkdir_r(char *path) {
char *path_duplicate = malloc(strlen(path) + 1);
strcpy(path_duplicate, path);
char *path_current = (char *)malloc((strlen(path) + 2) * sizeof(char));
char *path_current_position = path_current;
if (path[0] == '/') {
strcpy(path_current, "/");
path_current_position += 1;
} else {
path_current[0] = '\0';
}
const char *delimiter = "/";
char *part = strtok(path_duplicate, delimiter);
while (part != NULL) {
strcpy(path_current_position, part);
path_current_position += strlen(part) * sizeof(char);
strcpy(path_current_position, "/");
path_current_position += sizeof(char);
struct stat st;
if (stat(path_current, &st) != 0) {
if (mkdir(path_current, 0755) != 0) {
perror("Could not create directory");
exit(EXIT_FAILURE);
}
}
part = strtok(NULL, delimiter);
}
free(path_duplicate);
free(path_current);
}
char *str_dup(char *string) {
if (string == NULL)
return NULL;
char *new_string = (char *)malloc(strlen(string) + 1);
strcpy(new_string, string);
return new_string;
}
void to_disk(char *path, void *data, unsigned long long data_size) {
char *directory = str_dup(path);
char *dir_to_free = directory;
directory = dirname(directory);
mkdir_r(directory);
FILE *file_pointer = fopen(path, "wb");
if (file_pointer == NULL) {
perror("Could not open File");
exit(EXIT_FAILURE);
}
fwrite(data, 1, data_size, file_pointer);
fclose(file_pointer);
free(dir_to_free);
}
void file_restore_metadata(const char *path, FileMetadata *metadata) {
if (metadata == NULL)
return;
chmod(path, metadata->mode & 07777);
chown(path, metadata->uid, metadata->gid);
struct timespec times[2];
times[0].tv_sec = 0;
times[0].tv_nsec = UTIME_OMIT;
times[1].tv_sec = metadata->mtime_sec;
times[1].tv_nsec = metadata->mtime_nsec;
utimensat(AT_FDCWD, path, times, 0);
}
char *path_cat(char *path1, char *path2) {
if (path1 == NULL || *path1 == '\0')
return str_dup(path2);
if (path2 == NULL || *path2 == '\0')
return str_dup(path1);
int path1_len = strlen(path1);
int path2_len = strlen(path2);
char *path2_pointer = path2;
if (path1[path1_len - 1] == '/')
path1_len -= 1;
if (path2[0] == '/') {
path2_pointer += 1;
path2_len -= 1;
}
char *new_path = malloc(path1_len + path2_len + 2);
memcpy(new_path, path1, path1_len);
new_path[path1_len] = '/';
memcpy(new_path + path1_len + 1, path2_pointer, path2_len);
new_path[path1_len + path2_len + 1] = '\0';
return new_path;
}