static int sync_rm(csiebox_server *server, int conn_fd, csiebox_protocol_rm *rm)/*{{{*/ { char client_path[PATH_MAX]; char target_path[PATH_MAX]; if (recv_message(conn_fd, client_path, PATH_MAX)) { sprintf(target_path, "%s%s", get_user_homedir(server, server->client[conn_fd]), make_path(client_path)); struct stat fstatus; memset(&fstatus, 0, sizeof(fstatus)); lstat(target_path, &fstatus); if (S_ISDIR(fstatus.st_mode)) rmdir(target_path); else unlink(target_path); fprintf(stderr, "removed : %s\n", target_path); } // resend message back to client csiebox_protocol_header header; memset(&header, 0, sizeof(header)); header.res.magic = CSIEBOX_PROTOCOL_MAGIC_RES; header.res.op = CSIEBOX_PROTOCOL_OP_RM; header.res.status = CSIEBOX_PROTOCOL_STATUS_OK; if (!send_message(conn_fd, &header, sizeof(header))) { fprintf(stderr, "send back message error\n"); return 0; } return 1; }/*}}}*/
static void rm_file(csiebox_server* server, int conn_fd, csiebox_protocol_rm* rm) { csiebox_client_info* info = server->client[conn_fd]; char* homedir = get_user_homedir(server, info); char req_path[PATH_MAX], buf[PATH_MAX]; memset(req_path, 0, PATH_MAX); memset(buf, 0, PATH_MAX); recv_message(conn_fd, buf, rm->message.body.pathlen); sprintf(req_path, "%s%s", homedir, buf); free(homedir); fprintf(stderr, "rm (%zd, %s)\n", strlen(req_path), req_path); struct stat stat; memset(&stat, 0, sizeof(stat)); lstat(req_path, &stat); if ((stat.st_mode & S_IFMT) == S_IFDIR) { rmdir(req_path); } else { unlink(req_path); } csiebox_protocol_header header; memset(&header, 0, sizeof(header)); header.res.magic = CSIEBOX_PROTOCOL_MAGIC_RES; header.res.op = CSIEBOX_PROTOCOL_OP_RM; header.res.datalen = 0; header.res.client_id = conn_fd; header.res.status = CSIEBOX_PROTOCOL_STATUS_OK; send_message(conn_fd, &header, sizeof(header)); }
static int sync_file(csiebox_server *server, int conn_fd, csiebox_protocol_file *file)/*{{{*/ { // receive path char full_path[PATH_MAX]; recv_message(conn_fd, full_path, PATH_MAX); char target_path[PATH_MAX]; sprintf(target_path, "%s%s", get_user_homedir(server, server->client[conn_fd]), make_path(full_path)); fprintf(stderr, "sync file : target path : %s\n", target_path); // receive data struct stat fstatus; memset(&fstatus, 0, sizeof(fstatus)); int open_success = lstat(target_path, &fstatus); if (S_ISREG(fstatus.st_mode)){ int fd = open(target_path, O_WRONLY | O_CREAT | O_TRUNC); if (fd < 0) fprintf(stderr, "sync file : open fail\n"); while(1){ uint8_t buffer[1025]; memset(buffer, 0, 1025); recv_message(conn_fd, buffer, 1024); write(fd, buffer, strlen(buffer)); if (strlen(buffer) < 1024) break; } fsync(fd); close(fd); fprintf(stderr, "sync file : write success\n"); } // symbolic link if (open_success == -1 || S_ISLNK(fstatus.st_mode)) { uint8_t actual_path[PATH_MAX]; memset(actual_path, 0, PATH_MAX); recv_message(conn_fd, actual_path, PATH_MAX); if (symlink(actual_path, target_path) == 0) { fprintf(stderr, "sync file : symbolic link create/modify success\n"); } } // resend message back to client for time csiebox_protocol_header header; memset(&header, 0, sizeof(header)); header.res.magic = CSIEBOX_PROTOCOL_MAGIC_RES; header.res.op = CSIEBOX_PROTOCOL_OP_SYNC_FILE; header.res.status = CSIEBOX_PROTOCOL_STATUS_OK; send_message(conn_fd, &header, sizeof(header)); fprintf(stderr, "sync file : success\n"); // utime struct utimbuf meta_time; memset(&meta_time, 0, sizeof(meta_time)); recv_message(conn_fd, &meta_time, sizeof(meta_time)); utime(target_path, &meta_time); fprintf(stderr, "sync file : utime\n"); return 1; }/*}}}*/
static int sync_hardlink(csiebox_server *server, int conn_fd, csiebox_protocol_hardlink *hardlink)/*{{{*/ { char client_src_path[PATH_MAX]; char client_target_path[PATH_MAX]; if (!recv_message(conn_fd, client_src_path, PATH_MAX) || !recv_message(conn_fd, client_target_path, PATH_MAX)) { fprintf(stderr, "receive path error\n"); return 0; } // sync hardlink fprintf(stderr, "sync hardlink : receive path :\n\t%s\n\t%s\n", client_src_path, client_target_path); char src_path[PATH_MAX], target_path[PATH_MAX]; sprintf(src_path, "%s%s", get_user_homedir(server, server->client[conn_fd]), make_path(client_src_path)); sprintf(target_path, "%s%s", get_user_homedir(server, server->client[conn_fd]), make_path(client_target_path)); remove(target_path); fprintf(stderr, "sync hardlink : remove : %s\n", target_path); link(src_path, target_path); // send back message for time csiebox_protocol_header header; memset(&header, 0, sizeof(header)); header.res.magic = CSIEBOX_PROTOCOL_MAGIC_RES; header.res.op = CSIEBOX_PROTOCOL_OP_SYNC_HARDLINK; header.res.status = CSIEBOX_PROTOCOL_STATUS_OK; send_message(conn_fd, &header, sizeof(header)); fprintf(stderr, "sync hardlink : success\n"); // utime struct utimbuf meta_time; memset(&meta_time, 0, sizeof(meta_time)); recv_message(conn_fd, &meta_time, sizeof(meta_time)); utime(src_path, &meta_time); fprintf(stderr, "sync hardlink : utime\n"); return 1; }/*}}}*/
/*============================================ * expand_special_fname_chars -- Replace ~ with home *==========================================*/ BOOLEAN expand_special_fname_chars (STRING buffer, INT buflen, INT utf8) { char * sep=0; if (buffer[0]=='~') { if (is_dir_sep(buffer[1])) { STRING home = get_home(); if (home && home[0]) { STRING tmp; if ((INT)strlen(home) + 1 + (INT)strlen(buffer) > buflen) { return FALSE; } tmp = strsave(buffer); buffer[0] = 0; llstrapps(buffer, buflen, utf8, home); llstrapps(buffer, buflen, utf8, tmp+1); strfree(&tmp); return TRUE; } } /* check for ~name/... and resolve the ~name */ if ((sep = strchr(buffer,LLCHRDIRSEPARATOR))) { STRING username = strsave(buffer+1); STRING homedir; username[sep-buffer+1] = 0; homedir = get_user_homedir(username); strfree(&username); if (homedir) { STRING tmp=0; if ((INT)strlen(homedir) + 1 + (INT)strlen(sep+1) > buflen) { return FALSE; } tmp = strsave(sep+1); buffer[0] = 0; llstrapps(buffer, buflen, utf8, homedir); llstrapps(buffer, buflen, utf8, tmp+(sep-buffer+1)); strfree(&tmp); return TRUE; } } } return TRUE; }
//handle the login request from client static void login( csiebox_server* server, int conn_fd, csiebox_protocol_login* login) { int succ = 1; csiebox_client_info* info = (csiebox_client_info*)malloc(sizeof(csiebox_client_info)); memset(info, 0, sizeof(csiebox_client_info)); if (!get_account_info(server, login->message.body.user, &(info->account))) { fprintf(stderr, "cannot find account\n"); succ = 0; } if (succ && memcmp(login->message.body.passwd_hash, info->account.passwd_hash, MD5_DIGEST_LENGTH) != 0) { fprintf(stderr, "passwd miss match\n"); succ = 0; } csiebox_protocol_header header; memset(&header, 0, sizeof(header)); header.res.magic = CSIEBOX_PROTOCOL_MAGIC_RES; header.res.op = CSIEBOX_PROTOCOL_OP_LOGIN; header.res.datalen = 0; if (succ) { if (server->client[conn_fd]) { free(server->client[conn_fd]); } info->conn_fd = conn_fd; server->client[conn_fd] = info; header.res.status = CSIEBOX_PROTOCOL_STATUS_OK; header.res.client_id = info->conn_fd; char* homedir = get_user_homedir(server, info); mkdir(homedir, DIR_S_FLAG); printf("%s\n",homedir); free(homedir); } else { header.res.status = CSIEBOX_PROTOCOL_STATUS_FAIL; free(info); } send_message(conn_fd, &header, sizeof(header)); }
static int sync_meta(csiebox_server *server, int conn_fd, csiebox_protocol_meta *meta)/*{{{*/ { char full_path[PATH_MAX]; recv_message(conn_fd, full_path, sizeof(full_path)); // make a short path char *client_path = make_path(full_path); char *cur_dir = get_user_homedir(server, server->client[conn_fd]); if (chdir(cur_dir) == -1) { fprintf(stderr, "change to user directory error\n"); return 0; } // start to traverse int file_check = 0; char *object = strtok(client_path, "/"); while(object != NULL){ strcat(cur_dir, "/"); strcat(cur_dir, object); struct stat object_stat; memset(&object_stat, 0, sizeof(object_stat)); int open_success = lstat(cur_dir, &object_stat); // if file not exist if (open_success == -1){ if (S_ISDIR(meta->message.body.stat.st_mode)) { mkdir(cur_dir, meta->message.body.stat.st_mode); fprintf(stderr, "sync meta : create dir\n"); // dir utime struct utimbuf meta_time; memset(&meta_time, 0, sizeof(meta_time)); meta_time.actime = meta->message.body.stat.st_atime; meta_time.modtime = meta->message.body.stat.st_mtime; utime(cur_dir, &meta_time); fprintf(stderr, "create dir\n"); } if (S_ISREG(meta->message.body.stat.st_mode)) { int fd = creat(cur_dir, meta->message.body.stat.st_mode); // file utime struct utimbuf meta_time; memset(&meta_time, 0, sizeof(meta_time)); meta_time.actime = meta->message.body.stat.st_atime; meta_time.modtime = meta->message.body.stat.st_mtime; utime(cur_dir, &meta_time); fprintf(stderr, "sync meta : create file\n"); close(fd); file_check = 1; } if (S_ISLNK(meta->message.body.stat.st_mode)) { fprintf(stderr, "sync meta : is symbolic link\n"); file_check = 1; } object = strtok(NULL, "/"); } // file exist else { // is directory if (S_ISDIR(object_stat.st_mode)){ if (chdir(cur_dir) == -1) { fprintf(stderr, "chdir error\n"); return 0; } } else { // is file // file chmod chmod(cur_dir, meta->message.body.stat.st_mode); chown(cur_dir, meta->message.body.stat.st_uid, meta->message.body.stat.st_gid); // check if is same uint8_t content_hash[MD5_DIGEST_LENGTH]; memset(content_hash, 0, sizeof(content_hash)); md5_file(cur_dir, content_hash); if (memcmp(content_hash, meta->message.body.hash, MD5_DIGEST_LENGTH) != 0) file_check = 1; // file utime struct utimbuf meta_time; memset(&meta_time, 0, sizeof(meta_time)); meta_time.actime = meta->message.body.stat.st_atime; meta_time.modtime = meta->message.body.stat.st_mtime; utime(cur_dir, &meta_time); } object = strtok(NULL, "/"); // dir chmod if (object == NULL) { chmod(cur_dir, meta->message.body.stat.st_mode); chown(cur_dir, meta->message.body.stat.st_uid, meta->message.body.stat.st_gid); struct utimbuf meta_time; // dir utime memset(&meta_time, 0, sizeof(meta_time)); meta_time.actime = meta->message.body.stat.st_atime; meta_time.modtime = meta->message.body.stat.st_mtime; utime(cur_dir, &meta_time); } } } // send back message csiebox_protocol_header header; memset(&header, 0, sizeof(header)); header.res.magic = CSIEBOX_PROTOCOL_MAGIC_RES; header.res.op = CSIEBOX_PROTOCOL_OP_SYNC_META; header.res.status = (file_check == 1)? CSIEBOX_PROTOCOL_STATUS_MORE : CSIEBOX_PROTOCOL_STATUS_OK; header.res.datalen = 0; send_message(conn_fd, &header, sizeof(header)); fprintf(stderr, "sync meta : success\n"); return 1; }/*}}}*/
// flock static void sync_file(csiebox_server* server, int conn_fd, csiebox_protocol_meta* meta) { csiebox_client_info* info = server->client[conn_fd]; char* homedir = get_user_homedir(server, info); printf("homedir = %s\n", homedir); char buf[PATH_MAX], req_path[PATH_MAX]; memset(buf, 0, PATH_MAX); memset(req_path, 0, PATH_MAX); recv_message(conn_fd, buf, meta->message.body.pathlen); sprintf(req_path, "%s%s", homedir, buf); free(homedir); fprintf(stderr, "req_path: %s\n", req_path); struct stat stat; memset(&stat, 0, sizeof(struct stat)); int need_data = 0, change = 0; if (lstat(req_path, &stat) < 0) { need_data = 1; change = 1; } else { if(stat.st_mode != meta->message.body.stat.st_mode) { chmod(req_path, meta->message.body.stat.st_mode); } if(stat.st_atime != meta->message.body.stat.st_atime || stat.st_mtime != meta->message.body.stat.st_mtime){ struct utimbuf* buf = (struct utimbuf*)malloc(sizeof(struct utimbuf)); buf->actime = meta->message.body.stat.st_atime; buf->modtime = meta->message.body.stat.st_mtime; if(utime(req_path, buf)!=0){ printf("time fail\n"); } } uint8_t hash[MD5_DIGEST_LENGTH]; memset(hash, 0, MD5_DIGEST_LENGTH); if ((stat.st_mode & S_IFMT) == S_IFDIR) { } else { md5_file(req_path, hash); } if (memcmp(hash, meta->message.body.hash, MD5_DIGEST_LENGTH) != 0) { need_data = 1; } } csiebox_protocol_header header; memset(&header, 0, sizeof(header)); header.res.magic = CSIEBOX_PROTOCOL_MAGIC_RES; header.res.op = CSIEBOX_PROTOCOL_OP_SYNC_META; header.res.datalen = 0; header.res.client_id = conn_fd; if (need_data) { header.res.status = CSIEBOX_PROTOCOL_STATUS_MORE; } else { header.res.status = CSIEBOX_PROTOCOL_STATUS_OK; } send_message(conn_fd, &header, sizeof(header)); if (need_data) { csiebox_protocol_file file; memset(&file, 0, sizeof(file)); // receive upload request recv_message(conn_fd, &file, sizeof(file)); fprintf(stderr, "sync file: %zd\n", file.message.body.datalen); if ((meta->message.body.stat.st_mode & S_IFMT) == S_IFDIR) { fprintf(stderr, "dir\n"); mkdir(req_path, DIR_S_FLAG); } else { fprintf(stderr, "regular file\n"); int fd = open(req_path, O_CREAT | O_WRONLY | O_TRUNC, REG_S_FLAG); // request flock csiebox_protocol_header block; int request; while (flock(fd, LOCK_NB | LOCK_EX) != 0) { fprintf(stderr, "data locked, blocking...\n"); block.res.status = CSIEBOX_PROTOCOL_STATUS_BLOCKED; recv_message(conn_fd, &request, sizeof(int)); send_message(conn_fd, &block, sizeof(block)); } recv_message(conn_fd, &request, sizeof(int)); block.res.status = CSIEBOX_PROTOCOL_STATUS_OK; send_message(conn_fd, &block, sizeof(block)); // start receiving data size_t total = 0, readlen = 0; char buf[4096]; memset(buf, 0, 4096); while (file.message.body.datalen > total) { if (file.message.body.datalen - total < 4096) { readlen = file.message.body.datalen - total; } else { readlen = 4096; } if (!recv_message(conn_fd, buf, readlen)) { fprintf(stderr, "file broken\n"); break; } total += readlen; if (fd > 0) { write(fd, buf, readlen); } } if (fd > 0) { // unlock flock(fd, LOCK_UN); close(fd); } } if (change) { chmod(req_path, meta->message.body.stat.st_mode); struct utimbuf* buf = (struct utimbuf*)malloc(sizeof(struct utimbuf)); buf->actime = meta->message.body.stat.st_atime; buf->modtime = meta->message.body.stat.st_mtime; utime(req_path, buf); } header.res.op = CSIEBOX_PROTOCOL_OP_SYNC_FILE; header.res.status = CSIEBOX_PROTOCOL_STATUS_OK; send_message(conn_fd, &header, sizeof(header)); } }
static char *expand_configuration_value(char *unexpanded_value) { static char *homedir; static int homedir_len; char *ptr = unexpanded_value; int resultlen; char *result, *resultindex; char *var_name; char buf; if (unexpanded_value == NULL) return NULL; if ((homedir = get_user_homedir()) == NULL) homedir = empty_string; homedir_len = strlen(homedir); TRACE_LOG("Value to expand: \"%s\".\n", unexpanded_value); resultlen = 0; while (*ptr != 0) { if (*ptr == '$') { ptr++; if (*ptr == '(') { ptr++; var_name = ptr; while ( (*ptr != 0) && (*ptr != ')') ) ptr++; if (*ptr != ')') return NULL; buf = *ptr; *ptr = 0; if (strcmp(var_name, "HOME") == 0) { resultlen += strlen(homedir); } else { *ptr = buf; return NULL; } *ptr = buf; ptr++; } else return NULL; } else { ptr++; resultlen++; } } TRACE_LOG("result len: %d.\n", resultlen); result = fizmo_malloc(resultlen + 1); resultindex = result; ptr = unexpanded_value; while (*ptr != 0) { if (*ptr == '$') { ptr++; if (*ptr == '(') { ptr++; var_name = ptr; while ( (*ptr != 0) && (*ptr != ')') ) ptr++; if (*ptr != ')') { free(result); return NULL; } buf = *ptr; *ptr = 0; if (strcmp(var_name, "HOME") == 0) { strcpy(resultindex, homedir); resultindex += homedir_len; } else { *ptr = buf; // Can't ever reach this point due to loop 1. } *ptr = buf; ptr++; } } else { *resultindex = *ptr; ptr++; resultindex++; } } *resultindex = 0; TRACE_LOG("result expanded value: %s / %p.\n", result, result); return result; }