2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/select.h>
31 #define TRACE_TAG TRACE_SYNC
33 #include "file_sync_service.h"
35 #define SYNC_TIMEOUT 10
37 struct sync_permit_rule
41 int mode; // 0:push, 1: pull, 2: push&push
44 struct sync_permit_rule sdk_sync_permit_rule[] = {
45 // /* 0 */ {"rds", "^((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/info/\\.sdk_delta\\.info$", 1},
46 /* 1 */ {"unitest", "^((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data/[a-zA-Z0-9_\\-]{1,50}\\.xml$", 1},
47 /* 2 */ {"codecoverage", "^((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data/+([a-zA-Z0-9_/\\.])*+[a-zA-Z0-9_\\-\\.]{1,50}\\.gcda$", 1},
48 /* end */ {NULL, NULL, 0}
51 /* The typical default value for the umask is S_IWGRP | S_IWOTH (octal 022).
52 * Before use the DIR_PERMISSION, the process umask value should be set 0 using umask().
54 #define DIR_PERMISSION 0777
56 static int mkdirs(char *name)
61 if(name[0] != '/') return -1;
68 ret = sdb_mkdir(name, DIR_PERMISSION);
70 if((ret < 0) && (errno != EEXIST)) {
71 D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
80 static int do_stat(int s, const char *path)
85 msg.stat.id = ID_STAT;
92 D("failed to stat %s due to: %s\n", path, strerror(errno));
94 msg.stat.mode = htoll(st.st_mode);
95 msg.stat.size = htoll(st.st_size);
96 msg.stat.time = htoll(st.st_mtime);
99 return writex(s, &msg.stat, sizeof(msg.stat));
102 static int do_list(int s, const char *path)
110 char tmp[1024 + 256 + 1];
114 memcpy(tmp, path, len);
116 fname = tmp + len + 1;
118 msg.dent.id = ID_DENT;
122 D("failed to open dir due to: %s\n", strerror(errno));
126 while((de = readdir(d))) {
127 int len = strlen(de->d_name);
129 /* not supposed to be possible, but
130 if it does happen, let's not buffer overrun */
135 strcpy(fname, de->d_name);
136 if(lstat(tmp, &st) == 0) {
137 msg.dent.mode = htoll(st.st_mode);
138 msg.dent.size = htoll(st.st_size);
139 msg.dent.time = htoll(st.st_mtime);
140 msg.dent.namelen = htoll(len);
142 if(writex(s, &msg.dent, sizeof(msg.dent)) ||
143 writex(s, de->d_name, len)) {
153 msg.dent.id = ID_DONE;
157 msg.dent.namelen = 0;
158 return writex(s, &msg.dent, sizeof(msg.dent));
161 static int fail_message(int s, const char *reason)
164 int len = strlen(reason);
166 D("sync: failure: %s\n", reason);
168 msg.data.id = ID_FAIL;
169 msg.data.size = htoll(len);
170 if(writex(s, &msg.data, sizeof(msg.data)) ||
171 writex(s, reason, len)) {
178 static int fail_errno(int s)
180 return fail_message(s, strerror(errno));
183 static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
186 unsigned int timestamp = 0;
189 fd = sdb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
190 if(fd < 0 && errno == ENOENT) {
192 fd = sdb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
194 if(fd < 0 && errno == EEXIST) {
195 fd = sdb_open_mode(path, O_WRONLY, mode);
205 if(readx(s, &msg.data, sizeof(msg.data))) {
208 if(msg.data.id != ID_DATA) {
209 if(msg.data.id == ID_DONE) {
210 timestamp = ltohl(msg.data.size);
213 fail_message(s, "invalid data message");
216 len = ltohl(msg.data.size);
217 if(len > SYNC_DATA_MAX) {
218 fail_message(s, "oversize data message");
221 if(readx(s, buffer, len)) {
222 D("read failed due to unknown reason\n");
229 if(writex(fd, buffer, len)) {
230 int saved_errno = errno;
235 if(fail_errno(s)) return -1;
242 u.actime = timestamp;
243 u.modtime = timestamp;
246 msg.status.id = ID_OKAY;
247 msg.status.msglen = 0;
248 if(writex(s, &msg.status, sizeof(msg.status)))
250 // flush file system buffers due to N_SE-22305
253 D("sync error: %d!!!\n", fd);
266 static int handle_send_link(int s, char *path, char *buffer)
272 if(readx(s, &msg.data, sizeof(msg.data)))
275 if(msg.data.id != ID_DATA) {
276 fail_message(s, "invalid data message: expected ID_DATA");
280 len = ltohl(msg.data.size);
281 if(len > SYNC_DATA_MAX) {
282 fail_message(s, "oversize data message");
285 if(readx(s, buffer, len))
288 ret = symlink(buffer, path);
289 if(ret && errno == ENOENT) {
291 ret = symlink(buffer, path);
298 if(readx(s, &msg.data, sizeof(msg.data)))
301 if(msg.data.id == ID_DONE) {
302 msg.status.id = ID_OKAY;
303 msg.status.msglen = 0;
304 if(writex(s, &msg.status, sizeof(msg.status)))
307 fail_message(s, "invalid data message: expected ID_DONE");
313 #endif /* HAVE_SYMLINKS */
315 static int do_send(int s, char *path, char *buffer)
321 tmp = strrchr(path,',');
325 mode = strtoul(tmp + 1, NULL, 0);
326 #ifndef HAVE_SYMLINKS
329 is_link = S_ISLNK(mode);
331 // extracts file permission from stat.mode. (ex 100644 & 0777 = 644);
332 mode &= 0777; // combination of (S_IRWXU | S_IRWXG | S_IRWXO)
335 mode = 0644; // set default permission value in most of unix system.
339 // sdb does not allow to check that file exists or not. After deleting old file and creating new file again unconditionally.
345 ret = handle_send_link(s, path, buffer);
350 /* copy user permission bits to "group" and "other" permissions.
351 * ex) 0644 file will be created copied 0666 file.
352 * the following 2 lines should be commented if sdb process has been set to umask 0.
355 //mode |= ((mode >> 3) & 0070);
356 //mode |= ((mode >> 3) & 0007);
357 ret = handle_send_file(s, path, mode, buffer);
363 static int do_recv(int s, const char *path, char *buffer)
368 fd = sdb_open(path, O_RDONLY);
370 if(fail_errno(s)) return -1;
374 msg.data.id = ID_DATA;
376 r = sdb_read(fd, buffer, SYNC_DATA_MAX);
379 if(errno == EINTR) continue;
384 msg.data.size = htoll(r);
385 if(writex(s, &msg.data, sizeof(msg.data)) ||
386 writex(s, buffer, r)) {
394 msg.data.id = ID_DONE;
396 if(writex(s, &msg.data, sizeof(msg.data))) {
402 static int verify_sync_rule(const char* path) {
408 for (i=0; sdk_sync_permit_rule[i].regx != NULL; i++) {
409 ret = regcomp(®ex, sdk_sync_permit_rule[i].regx, REG_EXTENDED);
413 // execute regular expression
414 ret = regexec(®ex, path, 0, NULL, 0);
417 D("found matched rule(%s) from %s path\n", sdk_sync_permit_rule[i].name, path);
419 } else if( ret == REG_NOMATCH ){
422 regerror(ret, ®ex, buf, sizeof(buf));
423 D("regex match failed(%s): %s\n",sdk_sync_permit_rule[i].name, buf);
430 void file_sync_service(int fd, void *cookie)
436 struct timeval timeout;
438 char *buffer = malloc(SYNC_DATA_MAX);
439 if(buffer == 0) goto fail;
441 FD_ZERO(&set); /* clear the set */
442 FD_SET(fd, &set); /* add our file descriptor to the set */
444 timeout.tv_sec = SYNC_TIMEOUT;
448 D("sync: waiting for command for %d sec\n", SYNC_TIMEOUT);
450 rv = select(fd + 1, &set, NULL, NULL, &timeout);
452 D("sync file descriptor select failed\n");
453 } else if (rv == 0) {
454 D("sync file descriptor timeout: (took %d sec over)\n", SYNC_TIMEOUT);
455 fail_message(fd, "sync timeout");
459 if(readx(fd, &msg.req, sizeof(msg.req))) {
460 fail_message(fd, "command read failure");
463 namelen = ltohl(msg.req.namelen);
465 fail_message(fd, "invalid namelen");
468 if(readx(fd, name, namelen)) {
469 fail_message(fd, "filename read failure");
475 D("sync: '%s' '%s'\n", (char*) &msg.req, name);
477 if (should_drop_privileges() && !verify_sync_rule(name)) {
478 set_developer_privileges();
483 if(do_stat(fd, name)) goto fail;
486 if(do_list(fd, name)) goto fail;
489 if(do_send(fd, name, buffer)) goto fail;
492 if(do_recv(fd, name, buffer)) goto fail;
497 fail_message(fd, "unknown command");
503 if(buffer != 0) free(buffer);