1 /******************************************************************************
2 Copyright 2006 Palmsource, Inc (an ACCESS company).
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *****************************************************************************/
22 * @brief file system on top of a SQL database library
25 *****************************************************************************/
27 /* the file system is stored in a SQLite table, with the following columns
30 full key path type inode uid gid mode acl attributes atime mtime ctime size block_size
31 (text) (text) (integer) (integer) (integer) (integer) (text) (text) (integer) ...
33 the key path must start with "/" and is case sensitive
35 the type can be one of these: "int", "double", "string", "dir", "sym link" and "blob"
38 for Blobs we will divide them into 8k pieces, each occupying an BLOB object in database indexed by a block number
43 CREATE TABLE meta_data(key text, type text, inode integer, uid integer, gid integer, mode integer, acl text, attribute text,
44 atime integer, mtime integer, ctime integer, size integer, block_size integer, primary key (key), unique(key)) ;
46 CREATE TABLE value_data (key text, block_no integer, data_block blob, unique(key, block_no));
48 create index meta_index on meta_data (key);
49 create index value_index on value_data (key, block_no);
54 /* currently permission control due to the current directory not implemented */
65 #include <sys/types.h>
70 #include <attr/xattr.h>
71 #include <sys/capability.h>
75 // baik - for sqlfs profiling
79 #define PROFILE_START\
82 struct timeval time1;\
83 struct timeval time2;\
84 struct timeval restime;\
85 gettimeofday(&time1, NULL);
88 gettimeofday(&time2, NULL);\
89 timersub(&time2, &time1, &restime);\
90 g_sec = g_sec+restime.tv_sec;\
91 g_usec = g_usec+restime.tv_usec;\
92 g_total_sec = g_total_sec+ restime.tv_sec;\
93 g_total_usec = g_total_usec + restime.tv_usec;\
94 printf("%s = %d %d %d(%d) \n",__FUNCTION__,g_sec,g_usec,g_total_usec,g_usec*100/g_total_usec);
96 #define PROFILE_POINT(ARG)\
98 struct timeval profile_point_enter_time;\
99 gettimeofday(&kkk_enter_time,NULL);\
100 printf("%s- %d %d\n",ARG,profile_point_enter_time.tv_sec,kkk_enter_time.tv_usec);\
105 #define PREPARE_STMT\
106 stmt = get_sqlfs(sqlfs)->stmts[INDEX];\
110 if (sqlite3_expired(stmt))\
112 sqlite3_finalize(stmt);\
116 else r = ~SQLITE_OK;\
119 #define DONE_PREPARE if (r == SQLITE_OK) get_sqlfs(sqlfs)->stmts[INDEX] = stmt; else get_sqlfs(sqlfs)->stmts[INDEX] = 0;
121 #define SQLITE3_PREPARE(a, b, c, d, e)\
123 r = sqlite3_prepare((a), (b), (c), (d), (e));\
128 #define SQLFS_FAST_TUNNING
129 #define FAST_ATTRIBUTE_SEARCH
134 #ifdef FAST_ATTRIBUTE_SEARCH
135 char *g_prev_attribute_path=NULL;
136 key_attr g_prev_attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
139 #ifdef SQLFS_FAST_TUNNING
140 // baik - minimize get / set block size
141 static const int BLOCK_SIZE = 1 * 1024;
143 static const int BLOCK_SIZE = 128 * 1024;
146 static pthread_key_t sql_key;
148 static char default_db_file[PATH_MAX] = { 0 };
151 static int max_inode = 0;
153 static void * sqlfs_t_init(const char *);
154 static void sqlfs_t_finalize(void *arg);
156 static void delay(int ms)
158 struct timeval timeout;
159 timeout.tv_sec = ms / 1000 ;
160 timeout.tv_usec = 1000 * ( ms % 1000 );
162 select(0, 0, 0, 0, &timeout);
165 static __inline__ int sql_step(sqlite3_stmt *stmt)
168 for (i = 0; i < (1 * 1000 / 100); i++)
170 r = sqlite3_step(stmt);
171 if (r != SQLITE_BUSY)
180 static __inline__ sqlfs_t *get_sqlfs(sqlfs_t *p)
187 sqlfs = (sqlfs_t *) (pthread_getspecific(sql_key));
191 sqlfs = (sqlfs_t*) sqlfs_t_init(default_db_file);
192 pthread_setspecific(sql_key, sqlfs);
195 static __inline__ int get_new_inode(void)
200 static __inline__ void remove_tail_slash(char *str)
202 char *s = str + strlen(str) - 1;
212 static __inline__ char *make_str_copy(const char *str, size_t n)
216 return strndup(str,n);
219 static void show_msg(FILE *f, char *fmt, ...)
225 vfprintf(f, fmt, ap);
231 void clean_attr(key_attr *attr)
237 memset(attr, 0, sizeof(*attr));
241 void clean_value(key_value *value)
245 memset(value, 0, sizeof(*value));
248 /*static pthread_mutex_t transaction_lock = PTHREAD_MUTEX_INITIALIZER;
250 #define TRANS_LOCK //pthread_mutex_lock(&transaction_lock);
251 #define TRANS_UNLOCK //pthread_mutex_unlock(&transaction_lock);
257 static int begin_transaction(sqlfs_t *sqlfs)
261 const char *cmd = "begin exclusive;";
264 const char *cmd = "begin;";
273 if (get_sqlfs(sqlfs)->transaction_level == 0)
275 /*assert(sqlite3_get_autocommit(get_sqlfs(sqlfs)->db) != 0);*/
277 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
278 for (i = 0; i < 10; i++)
280 r = sqlite3_step(stmt);
281 if (r != SQLITE_BUSY)
286 if (r == SQLITE_DONE)
288 if (r == SQLITE_BUSY)
291 show_msg(stderr, "database is busy!\n");
292 return r; /* busy, return back */
294 get_sqlfs(sqlfs)->in_transaction = 1;
296 get_sqlfs(sqlfs)->transaction_level++;
305 static int commit_transaction(sqlfs_t *sqlfs, int r0)
311 static const char *cmd1 = "commit;", *cmd2 = "rollback;";
314 sqlite3_stmt *stmt, *stmt1, *stmt2;
317 // baik - ??제 transaction ??에???Prepare ??주는 것이 좋다.
318 #ifndef SQLFS_FAST_TUNNING
319 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
326 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
338 /*assert(get_sqlfs(sqlfs)->transaction_level > 0);*/
340 /*assert(get_sqlfs(sqlfs)->transaction_level >= 0);*/
341 if ((get_sqlfs(sqlfs)->transaction_level - 1 == 0) && (get_sqlfs(sqlfs)->in_transaction))
343 #ifdef SQLFS_FAST_TUNNING
344 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
351 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
359 for (i = 0; i < 10; i++)
361 r = sqlite3_step(stmt);
362 if (r != SQLITE_BUSY)
367 if (r == SQLITE_DONE)
369 if (r == SQLITE_BUSY)
372 show_msg(stderr, "database is busy!\n");
373 return r; /* busy, return back */
375 //**assert(sqlite3_get_autocommit(get_sqlfs(sqlfs)->db) != 0);*/
376 get_sqlfs(sqlfs)->in_transaction = 0;
378 get_sqlfs(sqlfs)->transaction_level--;
380 /*if (get_sqlfs(sqlfs)->transaction_level == 0)
381 assert(get_sqlfs(sqlfs)->in_transaction == 0);*/
389 static int break_transaction(sqlfs_t *sqlfs, int r0)
395 static const char *cmd1 = "commit;", *cmd2 = "rollback;";
398 sqlite3_stmt *stmt, *stmt1, *stmt2;
401 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
408 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
419 if (get_sqlfs(sqlfs)->in_transaction)
421 for (i = 0; i < 10; i++)
423 r = sqlite3_step(stmt);
424 if (r != SQLITE_BUSY)
429 if (r == SQLITE_DONE)
431 if (r == SQLITE_BUSY)
434 show_msg(stderr, "database is busy!\n");
435 return r; /* busy, return back */
437 //**assert(sqlite3_get_autocommit(get_sqlfs(sqlfs)->db) != 0);*/
438 get_sqlfs(sqlfs)->in_transaction = 0;
452 #if 0 // baik - set 1 for profile
454 #ifdef SQLFS_FAST_TUNNING
455 #define BEGIN PROFILE_START
456 #define COMPLETE(r) PROFILE_END
460 begin_transaction(get_sqlfs(sqlfs));
462 commit_transaction(get_sqlfs(sqlfs), (r));\
468 #ifdef SQLFS_FAST_TUNNING
469 // baik - Transaction ??걸기 ??해??는 반드??setxattr ?????용??서 걸어????다.
473 #define BEGIN begin_transaction(get_sqlfs(sqlfs));
474 #define COMPLETE(r) commit_transaction(get_sqlfs(sqlfs), (r));
486 static __inline__ int get_current_max_inode(sqlfs_t *sqlfs)
490 static const char *cmd = "select max(inode) from meta_data;";
493 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
498 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
506 if (r != SQLITE_DONE)
507 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
511 result = sqlite3_column_int(stmt, 0);
522 static int key_exists(sqlfs_t *sqlfs, const char *key, size_t *size)
526 static const char *cmd = "select size from meta_data where key = :key;";
528 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
531 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
536 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
540 if (r != SQLITE_DONE)
541 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
542 if (r == SQLITE_BUSY)
549 *size = sqlite3_column_int64(stmt, 0);
562 static int key_is_dir(sqlfs_t *sqlfs, const char *key)
565 const char *tail, *t;
566 static const char *cmd = "select type from meta_data where key = :key;";
568 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
571 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
575 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
579 if (r != SQLITE_DONE)
580 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
581 if (r == SQLITE_BUSY)
587 t = sqlite3_column_text(stmt, 0);
589 if (t && !strcmp(TYPE_DIR, t))
603 static int key_accessed(sqlfs_t *sqlfs, const char *key)
605 #ifndef SQLFS_FAST_TUNNING
608 static const char *cmd = "update meta_data set atime = :atime where key = :key;";
613 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
616 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
620 r = sqlite3_bind_int64(stmt, 1, now);
621 r = sqlite3_bind_text(stmt, 2, key, -1, SQLITE_STATIC);
622 r = sqlite3_step(stmt);
623 if (r != SQLITE_DONE)
625 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
628 else if (r == SQLITE_BUSY)
635 //baik - key_accessed ??에??access ??보?????데??트 ???? ??는??
644 static int key_modified(sqlfs_t *sqlfs, const char *key)
649 static const char *cmd = "update meta_data set atime = :atime, mtime = :mtime, ctime = :ctime where key = :key;";
652 #ifdef FAST_ATTRIBUTE_SEARCH
653 if(g_prev_attribute_path!=NULL)
654 if(strcmp(g_prev_attribute_path,key)==0)
656 free(g_prev_attribute_path);
657 g_prev_attribute_path = NULL;
662 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
665 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
669 sqlite3_bind_int64(stmt, 1, now);
670 sqlite3_bind_int64(stmt, 2, now);
671 sqlite3_bind_int64(stmt, 3, now);
672 sqlite3_bind_text(stmt, 4, key, -1, SQLITE_STATIC);
674 if (r != SQLITE_DONE)
676 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
691 static int remove_key(sqlfs_t *sqlfs, const char *key)
696 static const char *cmd1 = "delete from meta_data where key = :key;";
697 static const char *cmd2 = "delete from value_data where key = :key;" ;
698 static const char *cmd3 = "delete from xattr_data where key = :key;" ;
700 #ifdef FAST_ATTRIBUTE_SEARCH
701 if(g_prev_attribute_path!=NULL)
702 if(strcmp(g_prev_attribute_path,key)==0)
704 free(g_prev_attribute_path);
705 g_prev_attribute_path = NULL;
710 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
713 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
717 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
719 if (r != SQLITE_DONE)
721 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
735 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
738 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
742 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
744 if (r != SQLITE_DONE)
746 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
759 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd3, -1, &stmt, &tail);
762 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
766 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
768 if (r != SQLITE_DONE)
770 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
789 static int remove_key_subtree(sqlfs_t *sqlfs, const char *key)
794 char pattern[PATH_MAX];
795 static const char *cmd1 = "delete from meta_data where key glob :pattern;";
796 static const char *cmd2 = "delete from value_data where key glob :pattern;" ;
799 #ifdef FAST_ATTRIBUTE_SEARCH
800 if(g_prev_attribute_path!=NULL)
802 free(g_prev_attribute_path);
803 g_prev_attribute_path = NULL;
807 lpath = strndup(key,strlen(key));
808 assert(lpath != NULL);
809 remove_tail_slash(lpath);
810 sprintf(pattern, "%s/*", lpath);
813 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
816 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
820 sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_STATIC);
822 if (r != SQLITE_DONE)
824 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
838 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
841 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
845 sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_STATIC);
847 if (r != SQLITE_DONE)
849 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
860 r = remove_key(sqlfs, key);
871 static int remove_key_subtree_with_exclusion(sqlfs_t *sqlfs, const char *key, const char *exclusion_pattern)
876 char pattern[PATH_MAX];
877 char n_pattern[PATH_MAX];
878 static const char *cmd1 = "delete from meta_data where (key glob :pattern) and not (key glob :n_pattern) ;";
879 static const char *cmd2 = "delete from value_data where (key glob :pattern) and not (key glob :n_pattern) ;" ;
880 static const char *cmd3 = "select key from meta_data where (key glob :n_pattern) ;" ;
883 #ifdef FAST_ATTRIBUTE_SEARCH
884 if(g_prev_attribute_path!=NULL)
886 free(g_prev_attribute_path);
887 g_prev_attribute_path = NULL;
891 lpath = strndup(key,strlen(key));
892 assert(lpath != NULL);
893 remove_tail_slash(lpath);
894 snprintf(pattern, sizeof(pattern), "%s/*", lpath);
896 snprintf(n_pattern, sizeof(n_pattern), "%s/%s", lpath, exclusion_pattern);
899 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
902 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
906 sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_STATIC);
907 sqlite3_bind_text(stmt, 2, n_pattern, -1, SQLITE_STATIC);
909 if (r != SQLITE_DONE)
911 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
924 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
927 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
931 sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_STATIC);
933 if (r != SQLITE_DONE)
935 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
950 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd3, -1, &stmt, &tail);
953 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
957 sqlite3_bind_text(stmt, 1, n_pattern, -1, SQLITE_STATIC);
961 if (r == SQLITE_BUSY)
964 if (r != SQLITE_DONE)
965 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
973 if (r == SQLITE_NOTFOUND)
974 r = remove_key(sqlfs, key);
975 else if (r == SQLITE_BUSY)
989 static int rename_key(sqlfs_t *sqlfs, const char *old, const char *new)
994 static const char *cmd1 = "update meta_data set key = :new where key = :old; ";
995 static const char *cmd2 = "update value_data set key = :new where key = :old; ";
996 static const char *cmd3 = "update xattr_data set key = :new where key = :old; ";
998 #ifdef FAST_ATTRIBUTE_SEARCH
999 if(g_prev_attribute_path!=NULL)
1000 if(strcmp(g_prev_attribute_path,old)==0)
1002 free(g_prev_attribute_path);
1003 g_prev_attribute_path = NULL;
1008 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
1011 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1015 sqlite3_bind_text(stmt, 1, new, -1, SQLITE_STATIC);
1016 sqlite3_bind_text(stmt, 2, old, -1, SQLITE_STATIC);
1018 if (r != SQLITE_DONE)
1020 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1026 sqlite3_reset(stmt);
1036 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
1039 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1043 sqlite3_bind_text(stmt, 1, new, -1, SQLITE_STATIC);
1044 sqlite3_bind_text(stmt, 2, old, -1, SQLITE_STATIC);
1046 if (r != SQLITE_DONE)
1048 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1054 sqlite3_reset(stmt);
1063 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd3, -1, &stmt, &tail);
1066 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1070 sqlite3_bind_text(stmt, 1, new, -1, SQLITE_STATIC);
1071 sqlite3_bind_text(stmt, 2, old, -1, SQLITE_STATIC);
1073 if (r != SQLITE_DONE)
1075 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1081 sqlite3_reset(stmt);
1093 static int get_dir_children_num(sqlfs_t *sqlfs, const char *path)
1095 int i, r, count = 0;
1099 static const char *cmd = "select key from meta_data where key glob :pattern; ";
1104 if ((i = key_is_dir(sqlfs, path)), (i == 0))
1112 lpath = strndup(path,strlen(path));
1113 assert(lpath != NULL);
1114 remove_tail_slash(lpath);
1115 snprintf(tmp, sizeof(tmp), "%s/*", lpath);
1116 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
1119 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1123 sqlite3_bind_text(stmt, 1, tmp, -1, SQLITE_STATIC);
1128 if (r == SQLITE_ROW)
1130 t = sqlite3_column_text(stmt, 0);
1131 t2 = t + strlen(tmp) - 1;
1132 if (strchr(t2, '/'))
1133 continue; /* grand child, etc. */
1137 else if (r == SQLITE_DONE)
1143 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1151 if (r == SQLITE_BUSY)
1156 static int set_attr(sqlfs_t *sqlfs, const char *key, const key_attr *attr);
1159 static int ensure_existence(sqlfs_t *sqlfs, const char *key, const char *type)
1162 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1163 if (key_exists(sqlfs, key, 0) == 0)
1165 attr.path = strndup(key,strlen(key));
1166 assert(attr.path != NULL);
1167 attr.type = strndup(type,strlen(type));
1168 assert(attr.type != NULL);
1169 attr.mode = get_sqlfs(sqlfs)->default_mode; /* to use default */
1172 attr.uid = fuse_get_context()->uid;
1173 attr.gid = fuse_get_context()->gid;
1174 /* printf("[%s:%d]attr.uid = %d, attr.gid=%d\n", __FILE__, __LINE__, attr.uid, attr.gid); */
1176 attr.uid = geteuid();
1177 attr.gid = getegid();
1180 attr.uid = get_sqlfs(sqlfs)->uid;
1181 attr.gid = get_sqlfs(sqlfs)->gid;
1184 attr.inode = get_new_inode();
1185 r = set_attr(sqlfs, key, &attr);
1200 static int ensure_parent_existence(sqlfs_t *sqlfs, const char *key)
1205 char *parent = calloc(strlen(key) + 2, sizeof(char));
1210 strcpy(parent, key);
1211 remove_tail_slash(parent);
1212 t = strrchr(parent, '/');
1225 ensure_existence(sqlfs, parent, TYPE_DIR);
1231 static int get_parent_path(const char *path, char buf[PATH_MAX])
1235 if ((path[0] == '/') && (path[1] == 0))
1237 /* the root directory, which has no parent */
1238 return SQLITE_NOTFOUND;
1242 remove_tail_slash(buf);
1243 s = strrchr(buf, '/');
1246 return SQLITE_NOTFOUND; /* no parent? */
1260 static int get_permission_data(sqlfs_t *sqlfs, const char *key, gid_t *gid, uid_t *uid, mode_t *mode)
1267 static const char *cmd = "select mode, uid, gid from meta_data where key = :key; ";
1270 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
1273 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1276 r = sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1279 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1283 if (r != SQLITE_ROW)
1285 if (r != SQLITE_DONE)
1286 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1287 else if (r == SQLITE_BUSY)
1290 r = SQLITE_NOTFOUND;
1294 *mode = (mode_t) (sqlite3_column_int(stmt, 0));
1295 *uid = (uid_t) (sqlite3_column_int(stmt, 1));
1296 *gid = (gid_t) (sqlite3_column_int(stmt, 2));
1300 sqlite3_reset(stmt);
1301 key_accessed(sqlfs, key);
1306 static int get_parent_permission_data(sqlfs_t *sqlfs, const char *key, gid_t *gid, uid_t *uid, mode_t *mode)
1308 char tmp[PATH_MAX], *s;
1310 r = get_parent_path(key, tmp);
1312 r = get_permission_data(sqlfs, tmp, gid, uid, mode);
1322 static int get_attr(sqlfs_t *sqlfs, const char *key, key_attr *attr)
1328 static const char *cmd = "select key, type, mode, uid, gid, atime, mtime, ctime, size, inode from meta_data where key = :key; ";
1332 // baik - ??반??으???file operation ?? open -> read -> close ????속????서???발생??다.
1333 // - ??라?? ??나??Attribute ???cache ??여????과????다.
1334 #ifdef FAST_ATTRIBUTE_SEARCH
1335 if(g_prev_attribute_path!=NULL)
1336 if(strcmp(g_prev_attribute_path,key)== 0)
1338 attr->path = make_str_copy(g_prev_attr.path,strlen(g_prev_attr.path));
1339 assert(attr->path != NULL);
1340 assert(!strcmp(key, attr->path));
1341 attr->type = make_str_copy(g_prev_attr.type,strlen(g_prev_attr.type));
1342 assert(attr->type != NULL);
1343 attr->mode =g_prev_attr.mode;
1344 attr->uid = g_prev_attr.uid;
1345 attr->gid = g_prev_attr.gid;
1346 attr->atime = g_prev_attr.atime;
1347 attr->mtime = g_prev_attr.mtime;
1348 attr->ctime = g_prev_attr.ctime;
1349 attr->size = g_prev_attr.size;
1350 attr->inode = g_prev_attr.inode;
1357 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
1360 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1363 r = sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1366 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1370 if (r != SQLITE_ROW)
1372 if (r != SQLITE_DONE)
1373 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1374 if (r == SQLITE_BUSY)
1377 r = SQLITE_NOTFOUND;
1381 attr->path = make_str_copy(sqlite3_column_text(stmt, 0),strlen(sqlite3_column_text(stmt, 0)));
1382 assert(attr->path != NULL);
1383 assert(!strcmp(key, attr->path));
1384 attr->type = make_str_copy(sqlite3_column_text(stmt, 1),strlen(sqlite3_column_text(stmt, 1)));
1385 assert(attr->type != NULL);
1386 attr->mode = (sqlite3_column_int(stmt, 2));
1387 attr->uid = (sqlite3_column_int(stmt, 3));
1388 attr->gid = (sqlite3_column_int(stmt, 4));
1389 attr->atime = (sqlite3_column_int(stmt, 5));
1390 attr->mtime = (sqlite3_column_int(stmt, 6));
1391 attr->ctime = (sqlite3_column_int(stmt, 7));
1392 attr->size = (sqlite3_column_int64(stmt, 8));
1393 attr->inode = (sqlite3_column_int(stmt, 9));
1397 #ifdef FAST_ATTRIBUTE_SEARCH
1398 clean_attr(&g_prev_attr);
1399 g_prev_attr.path = make_str_copy(attr->path,strlen(attr->path));
1400 assert(g_prev_attr.path != NULL);
1401 assert(!strcmp(key, attr->path));
1402 g_prev_attr.type = make_str_copy(attr->type,strlen(attr->type));
1403 assert(g_prev_attr.type != NULL);
1404 g_prev_attr.mode = attr->mode;
1405 g_prev_attr.uid = attr->uid;
1406 g_prev_attr.gid = attr->gid;
1407 g_prev_attr.atime = attr->atime;
1408 g_prev_attr.mtime = attr->mtime;
1409 g_prev_attr.ctime = attr->ctime;
1410 g_prev_attr.size = attr->size;
1411 g_prev_attr.inode = attr->inode;
1413 if(g_prev_attribute_path!=NULL)
1414 free(g_prev_attribute_path);
1415 g_prev_attribute_path = strndup(key,strlen(key));
1416 assert(g_prev_attribute_path != NULL);
1420 sqlite3_reset(stmt);
1421 key_accessed(sqlfs, key);
1430 static int set_attr(sqlfs_t *sqlfs, const char *key, const key_attr *attr)
1435 int mode = attr->mode;
1436 static const char *cmd1 = "insert or ignore into meta_data (key) VALUES ( :key ) ; ";
1437 static const char *cmd2 = "update meta_data set type = :type, mode = :mode, uid = :uid, gid = :gid,"
1438 "atime = :atime, mtime = :mtime, ctime = :ctime, size = :size, inode = :inode, block_size = :block_size where key = :key; ";
1442 #ifdef FAST_ATTRIBUTE_SEARCH
1443 if(g_prev_attribute_path!=NULL)
1444 if(strcmp(g_prev_attribute_path,key)==0)
1446 free(g_prev_attribute_path);
1447 g_prev_attribute_path = NULL;
1452 if (!strcmp(attr->type, TYPE_DIR))
1454 else if (!strcmp(attr->type, TYPE_SYM_LINK))
1459 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
1462 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1466 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1468 sqlite3_reset(stmt);
1475 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
1478 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1482 sqlite3_bind_text(stmt, 1, attr->type, -1, SQLITE_STATIC);
1483 sqlite3_bind_int(stmt, 2, mode);
1484 sqlite3_bind_int(stmt, 3, attr->uid);
1485 sqlite3_bind_int(stmt, 4, attr->gid);
1486 // baik - modified time ????기????데??트 ??다.
1487 #ifdef SQLFS_FAST_TUNNING
1489 sqlite3_bind_int(stmt, 5, now);
1490 sqlite3_bind_int(stmt, 6, now);
1491 sqlite3_bind_int(stmt, 7, now);
1493 sqlite3_bind_int(stmt, 5, attr->atime);
1494 sqlite3_bind_int(stmt, 6, attr->mtime);
1495 sqlite3_bind_int(stmt, 7, attr->ctime);
1497 sqlite3_bind_int64(stmt, 8, attr->size);
1498 sqlite3_bind_int(stmt, 9, attr->inode);
1499 sqlite3_bind_int(stmt, 10, BLOCK_SIZE);
1501 sqlite3_bind_text(stmt, 11, attr->path, -1, SQLITE_STATIC);
1505 if (r != SQLITE_DONE)
1507 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1512 sqlite3_reset(stmt);
1513 #ifndef SQLFS_FAST_TUNNING
1514 key_modified(sqlfs, key);
1516 /*ensure_parent_existence(sqlfs, key);*/
1527 static int key_set_type(sqlfs_t *sqlfs, const char *key, const char *type)
1529 int r = SQLITE_OK, i;
1531 static const char *cmd = "update meta_data set type = :type where key = :key; ";
1534 #ifdef FAST_ATTRIBUTE_SEARCH
1535 if(g_prev_attribute_path!=NULL)
1536 if(strcmp(g_prev_attribute_path,key)==0)
1538 free(g_prev_attribute_path);
1539 g_prev_attribute_path = NULL;
1544 i = ensure_existence(sqlfs, key, type);
1547 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
1550 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1554 sqlite3_bind_text(stmt, 1, type, -1, SQLITE_STATIC);
1555 sqlite3_bind_text(stmt, 2, key, -1, SQLITE_STATIC);
1557 if (r != SQLITE_DONE)
1559 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1561 sqlite3_reset(stmt);
1574 static int get_value_block(sqlfs_t *sqlfs, const char *key, char *data, int block_no, int *size)
1579 static const char *cmd = "select data_block from value_data where key = :key and block_no = :block_no;";
1580 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
1582 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
1585 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1588 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1589 sqlite3_bind_int(stmt, 2, block_no);
1591 if (r != SQLITE_ROW)
1593 if (r != SQLITE_DONE)
1594 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1600 *size = sqlite3_column_bytes(stmt, 0);
1601 memcpy(data, sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
1606 sqlite3_reset(stmt);
1616 static int set_value_block(sqlfs_t *sqlfs, const char *key, const char *data, int block_no, int size)
1622 static const char *cmd = "update value_data set data_block = :data_block where key = :key and block_no = :block_no;";
1623 static const char *cmd1 = "insert or ignore into value_data (key, block_no) VALUES ( :key, :block_no ) ; ";
1624 static const char *cmd2 = "delete from value_data where key = :key and block_no = :block_no;";
1631 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
1634 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1638 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1639 sqlite3_bind_int(stmt, 2, block_no);
1641 if (r != SQLITE_DONE)
1643 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1648 sqlite3_reset(stmt);
1658 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
1661 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1665 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1666 sqlite3_bind_int(stmt, 2, block_no);
1668 sqlite3_reset(stmt);
1670 if (r == SQLITE_BUSY)
1680 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
1683 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1687 sqlite3_bind_blob(stmt, 1, data, size, SQLITE_STATIC);
1688 sqlite3_bind_text(stmt, 2, key, -1, SQLITE_STATIC);
1689 sqlite3_bind_int(stmt, 3, block_no);
1693 if (r != SQLITE_DONE)
1695 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1700 sqlite3_reset(stmt);
1713 static int get_value(sqlfs_t *sqlfs, const char *key, key_value *value, size_t begin, size_t end)
1718 static const char *cmd = "select size from meta_data where key = :key; ";
1725 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
1728 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1732 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1734 if (r != SQLITE_ROW)
1736 if (r != SQLITE_DONE)
1737 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1742 size = sqlite3_column_int64(stmt, 0);
1747 if ((end == 0) || (end > size))
1754 value->data = malloc(value->size);
1755 assert(value->data);
1758 begin = (block_no = (begin / BLOCK_SIZE)) * BLOCK_SIZE;
1759 for ( ; begin < end; begin += BLOCK_SIZE, block_no++)
1762 r = get_value_block(sqlfs, key, value->data + begin - value->offset, block_no, NULL);
1768 r = SQLITE_NOTFOUND ;
1771 sqlite3_reset(stmt);
1772 key_accessed(sqlfs, key);
1782 static int set_value(sqlfs_t *sqlfs, const char *key, const key_value *value, size_t begin, size_t end)
1787 size_t begin2, end2, length;
1791 static const char *cmd1 = "insert or ignore into meta_data (key) VALUES ( :key ) ; ";
1793 // baik - time ????기????데??트 ??다.
1794 #ifdef SQLFS_FAST_TUNNING
1795 static const char *cmd2 = "update meta_data set atime = :atime, mtime = :mtime, ctime = :ctime, size = :size where key = :key ; ";
1797 static const char *cmd2 = "update meta_data set size = :size where key = :key ; ";
1801 #ifdef FAST_ATTRIBUTE_SEARCH
1802 if(g_prev_attribute_path!=NULL)
1803 if(strcmp(g_prev_attribute_path,key)==0)
1805 free(g_prev_attribute_path);
1806 g_prev_attribute_path = NULL;
1811 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
1814 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1818 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1820 sqlite3_reset(stmt);
1822 if (r == SQLITE_BUSY)
1824 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1835 tmp = calloc( BLOCK_SIZE, sizeof(char));
1839 begin2 = (block_no = (begin / BLOCK_SIZE)) * BLOCK_SIZE;
1841 if (end2 > begin2 + BLOCK_SIZE)
1842 end2 = begin2 + BLOCK_SIZE;
1845 size_t old_size = 0;
1846 r = get_value_block(sqlfs, key, tmp, block_no, &old_size);
1847 length = end2 - begin;
1848 memcpy(tmp + (begin - begin2), (value->data - value->offset) + begin, length);
1849 length = end2 - begin2;
1850 if (length < old_size)
1852 r = set_value_block(sqlfs, key, tmp, block_no, length);
1854 begin2 += BLOCK_SIZE;
1856 for ( ; begin2 < end / BLOCK_SIZE * BLOCK_SIZE; begin2 += BLOCK_SIZE, block_no++)
1859 r = set_value_block(sqlfs, key, (value->data - value->offset) + BLOCK_SIZE * block_no, block_no, BLOCK_SIZE);
1867 assert(begin2 % BLOCK_SIZE == 0);
1868 assert(end - begin2 < (size_t) BLOCK_SIZE);
1870 memset(tmp, 0, BLOCK_SIZE);
1871 r = get_value_block(sqlfs, key, tmp, block_no, &i);
1874 memcpy(tmp, (value->data - value->offset) + begin2, end - begin2 );
1875 if (i < (int)(end - begin2))
1876 i = (int)(end - begin2);
1878 r = set_value_block(sqlfs, key, tmp, block_no, i);
1883 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
1886 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1890 #ifdef SQLFS_FAST_TUNNING
1892 sqlite3_bind_int64(stmt, 1, now);
1893 sqlite3_bind_int64(stmt, 2, now);
1894 sqlite3_bind_int64(stmt, 3, now);
1895 sqlite3_bind_int64(stmt, 4, value->size);
1896 sqlite3_bind_text(stmt, 5, key, -1, SQLITE_STATIC);
1898 sqlite3_reset(stmt);
1899 if (r == SQLITE_DONE)
1902 sqlite3_bind_int64(stmt, 1, value->size);
1903 sqlite3_bind_text(stmt, 2, key, -1, SQLITE_STATIC);
1905 sqlite3_reset(stmt);
1906 if (r == SQLITE_DONE)
1908 key_modified(sqlfs, key);
1910 /*ensure_parent_existence(sqlfs, key);*/
1921 static int key_shorten_value(sqlfs_t *sqlfs, const char *key, size_t new_length)
1929 static const char *cmd1 = "delete from value_data where key = :key and block_no > :block_no; ";
1931 // baik - time ????기????데??트 ??다.
1932 #ifdef SQLFS_FAST_TUNNING
1933 static const char *cmd2 = "update meta_data set atime = :atime, mtime = :mtime, ctime = :ctime, size = :size where key = :key ; ";
1935 static const char *cmd2 = "update meta_data set size = :size where key = :key ; ";
1939 #ifdef FAST_ATTRIBUTE_SEARCH
1940 if(g_prev_attribute_path!=NULL)
1941 if(strcmp(g_prev_attribute_path,key)==0)
1943 free(g_prev_attribute_path);
1944 g_prev_attribute_path = NULL;
1949 if ((i = key_exists(sqlfs, key, &l)), (i == 0))
1952 show_msg(stderr, "Illegal truncateion on non-existence key %s\n", key);
1954 return SQLITE_ERROR;
1962 assert(l > new_length);
1963 block_no = new_length / BLOCK_SIZE;
1965 tmp = calloc(BLOCK_SIZE, sizeof(char));
1967 r = get_value_block(sqlfs, key, tmp, block_no, &i);
1968 assert(new_length % BLOCK_SIZE <= (unsigned int) i);
1969 r = set_value_block(sqlfs, key, tmp, block_no, new_length % BLOCK_SIZE);
1972 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1978 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd1, -1, &stmt, &tail);
1981 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1986 sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
1987 sqlite3_bind_int(stmt, 2, block_no);
1989 /*if (r != SQLITE_DONE)
1991 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
1994 /*ignore the result */
1995 if (r == SQLITE_BUSY)
1999 sqlite3_reset(stmt);
2009 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd2, -1, &stmt, &tail);
2012 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
2017 #ifdef SQLFS_FAST_TUNNING
2019 sqlite3_bind_int64(stmt, 1, now);
2020 sqlite3_bind_int64(stmt, 2, now);
2021 sqlite3_bind_int64(stmt, 3, now);
2022 sqlite3_bind_int64(stmt, 4, new_length);
2023 sqlite3_bind_text(stmt, 5, key, -1, SQLITE_STATIC);
2025 sqlite3_reset(stmt);
2026 if (r == SQLITE_DONE)
2030 sqlite3_bind_int64(stmt, 1, new_length);
2031 sqlite3_bind_text(stmt, 2, key, -1, SQLITE_STATIC);
2033 sqlite3_reset(stmt);
2034 if (r == SQLITE_DONE)
2036 key_modified(sqlfs, key);
2041 /*ensure_parent_existence(sqlfs, key);*/
2047 static int check_parent_access(sqlfs_t *sqlfs, const char *path)
2049 char ppath[PATH_MAX];
2054 r = get_parent_path(path, ppath);
2055 //fprintf(stderr, "%s #1 returns %d on %s\n", __func__, r, path);//???
2058 result = check_parent_access(sqlfs, ppath);
2059 //fprintf(stderr, "%s #2 returns %d on %s\n", __func__, result, path);//???
2061 result = (sqlfs_proc_access(sqlfs, (ppath), X_OK));
2062 //fprintf(stderr, "%s #3 returns %d on %s %s\n", __func__, result, path, ppath);//???
2064 /* else if no parent, we return 0 by default */
2067 //fprintf(stderr, "%s returns %d on %s\n", __func__, result, path);//???
2072 static int check_parent_write(sqlfs_t *sqlfs, const char *path)
2074 char ppath[PATH_MAX];
2079 r = get_parent_path(path, ppath);
2082 result = (sqlfs_proc_access(sqlfs, (ppath), W_OK | X_OK));
2083 //fprintf(stderr, "check directory write 1st %s %d uid %d gid %d\n", ppath, result, get_sqlfs(sqlfs)->uid, get_sqlfs(sqlfs)->gid);//???
2086 if (result == -ENOENT)
2088 result = check_parent_write(sqlfs, ppath);
2090 ensure_existence(sqlfs, ppath, TYPE_DIR);
2091 result = (sqlfs_proc_access(sqlfs, (ppath), W_OK | X_OK));
2096 //fprintf(stderr, "check directory write %s %d\n", ppath, result);//???
2100 #ifndef SQLFS_FAST_TUNNING
2101 #define CHECK_PARENT_PATH(p) result = check_parent_access(sqlfs, (p)); if (result != 0) { COMPLETE(1); return result; }
2103 #define CHECK_READ(p) result = (sqlfs_proc_access(sqlfs, (p), R_OK | F_OK)); if (result != 0) { COMPLETE(1); return result; }
2104 #define CHECK_WRITE(p) result = (sqlfs_proc_access(sqlfs, (p), W_OK | F_OK)); if (result != 0) { COMPLETE(1); return result; }
2106 #define CHECK_DIR_WRITE(p) result = (sqlfs_proc_access(sqlfs, (p), W_OK | F_OK | X_OK)); if (result != 0) { COMPLETE(1); return result; }
2107 #define CHECK_DIR_READ(p) result = (sqlfs_proc_access(sqlfs, (p), R_OK | F_OK | X_OK)); if (result != 0) {fprintf(stderr, "dir read failed %d\n", result); COMPLETE(1); return result; }
2109 #define CHECK_PARENT_READ(p) \
2110 { char ppath[PATH_MAX]; if (SQLITE_OK == get_parent_path((p), ppath)) { result = (sqlfs_proc_access(sqlfs, (ppath), R_OK | X_OK)); if (result != 0) { COMPLETE(1); return result; }}}
2111 #define CHECK_PARENT_WRITE(p) \
2112 { result = check_parent_write(sqlfs, (p)); if (result != 0) { COMPLETE(1); return result; }}
2114 #else /* Enable fast tuning */
2116 // baik - ??도?????해 access permission 체크????단 ???? ??는??
2118 #if 0 /* Block permission check */
2119 #define CHECK_PARENT_PATH(p) result = 0;
2121 #define CHECK_READ(p) result = 0;
2122 #define CHECK_WRITE(p) result = 0;
2124 #define CHECK_DIR_WRITE(p) result = 0;
2125 #define CHECK_DIR_READ(p) result = 0;
2127 #define CHECK_PARENT_READ(p) result = 0;
2128 #define CHECK_PARENT_WRITE(p) result = 0;
2131 /* Use basic permission checks */
2132 #define CHECK_PARENT_PATH(p) result = check_parent_access(sqlfs, (p)); if (result != 0) { COMPLETE(1); return result; }
2134 #define CHECK_READ(p) result = (sqlfs_proc_access(sqlfs, (p), R_OK | F_OK)); if (result != 0) { COMPLETE(1); return result; }
2135 #define CHECK_WRITE(p) result = (sqlfs_proc_access(sqlfs, (p), W_OK | F_OK)); if (result != 0) { COMPLETE(1); return result; }
2137 #define CHECK_DIR_WRITE(p) result = (sqlfs_proc_access(sqlfs, (p), W_OK | F_OK | X_OK)); if (result != 0) { COMPLETE(1); return result; }
2138 #define CHECK_DIR_READ(p) result = (sqlfs_proc_access(sqlfs, (p), R_OK | F_OK | X_OK)); if (result != 0) {fprintf(stderr, "dir read failed %d\n", result); COMPLETE(1); return result; }
2140 #define CHECK_PARENT_READ(p) \
2141 { char ppath[PATH_MAX]; if (SQLITE_OK == get_parent_path((p), ppath)) { result = (sqlfs_proc_access(sqlfs, (ppath), R_OK | X_OK)); if (result != 0) { COMPLETE(1); return result; }}}
2142 #define CHECK_PARENT_WRITE(p) \
2143 { result = check_parent_write(sqlfs, (p)); if (result != 0) { COMPLETE(1); return result; }}
2147 int sqlfs_proc_getattr(sqlfs_t *sqlfs, const char *path, struct stat *stbuf)
2149 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2153 CHECK_PARENT_PATH(path)
2156 r = get_attr(get_sqlfs(sqlfs), path, &attr);
2159 memset(stbuf, 0, sizeof(*stbuf));
2160 stbuf->st_mode = attr.mode;
2161 if (!strcmp(attr.type, TYPE_DIR))
2162 stbuf->st_mode |= S_IFDIR;
2163 else if (!strcmp(attr.type, TYPE_SYM_LINK))
2164 stbuf->st_mode |= S_IFLNK;
2166 stbuf->st_mode |= S_IFREG;
2167 stbuf->st_nlink = 1;
2168 stbuf->st_uid = (uid_t) attr.uid;
2169 stbuf->st_gid = (gid_t) attr.gid;
2170 stbuf->st_size = (off_t) attr.size;
2171 stbuf->st_blksize = 512;
2172 stbuf->st_blocks = attr.size / 512;
2173 stbuf->st_atime = attr.atime;
2174 stbuf->st_mtime = attr.mtime;
2175 stbuf->st_ctime = attr.ctime;
2176 stbuf->st_ino = attr.inode;
2190 /* Because of bug, this function is commented out.
2191 * uid_in_fgid() function is used instead of gid_in_supp_groups() */
2192 static int gid_in_supp_groups(gid_t gid)
2194 int n, num_groups = getgroups(0, 0);
2198 gid_t *gids = malloc(sizeof(gids[0]) * num_groups);
2199 n = getgroups(num_groups, gids);
2201 assert(n == num_groups);
2202 for (n = 0; n < num_groups; n++)
2218 static int uid_in_fgid(uid_t euid, gid_t fgid)
2220 /* euid: effective uid
2222 struct group* gr = getgrgid(fgid);
2227 if(!(gr->gr_mem)) return 0;
2228 char **gr_mem = gr->gr_mem;
2229 struct passwd *pwd = NULL;
2230 for(; *gr_mem; gr_mem++) {
2231 pwd = getpwnam(*gr_mem);
2233 if(euid == pwd->pw_uid)
2241 int sqlfs_proc_access(sqlfs_t *sqlfs, const char *path, int mask)
2244 int i, r = SQLITE_OK, result = 0;
2247 gid_t uid = fuse_get_context()->uid;
2248 uid_t gid = fuse_get_context()->gid;
2249 printf("[%s:%d]uid = %d, gid = %d\n", __FILE__, __LINE__, uid, gid);
2251 gid_t gid = getegid();
2252 uid_t uid = geteuid();
2255 gid_t gid = get_sqlfs(sqlfs)->gid;
2256 uid_t uid = get_sqlfs(sqlfs)->uid;
2264 if (uid == 0) /* root user so everything is granted */
2266 if ((i = key_exists(sqlfs, path, 0)), !i)
2272 //fprintf(stderr, "root access returns %d on %s\n", result, path);//???
2278 r = get_parent_permission_data(sqlfs, path, &fgid, &fuid, &fmode);
2281 if (uid == (uid_t) fuid)
2283 if ( !(S_IRUSR & S_IXUSR & fmode))
2289 // else if ((gid == (gid_t) fgid) || (gid_in_supp_groups(fgid)))
2290 else if ((gid == (gid_t) fgid) || (uid_in_fgid(uid, fgid)))
2292 if ( !(S_IRGRP & S_IXGRP & fmode))
2299 if ( !(S_IROTH & S_IXOTH & fmode))
2305 else if (r == SQLITE_NOTFOUND)
2312 r = get_permission_data(get_sqlfs(sqlfs), path, &fgid, &fuid, &fmode);
2313 //fprintf(stderr, "get permission returns %d\n", r);//???
2314 if ((r == SQLITE_OK) && (result == 0))
2316 if (uid == (uid_t) fuid)
2318 if (((mask & R_OK) && !(S_IRUSR & fmode)) ||
2319 ((mask & W_OK) && !(S_IWUSR & fmode)) ||
2320 ((mask & X_OK) && !(S_IXUSR & fmode)))
2326 // else if ((gid == (uid_t) fgid) || (gid_in_supp_groups(fgid)))
2327 else if ((gid == (uid_t) fgid) || (uid_in_fgid(uid, fgid)))
2329 if (((mask & R_OK) && !(S_IRGRP & fmode)) ||
2330 ((mask & W_OK) && !(S_IWGRP & fmode)) ||
2331 ((mask & X_OK) && !(S_IXGRP & fmode)))
2338 else if (((mask & R_OK) && !(S_IROTH & fmode)) ||
2339 ((mask & W_OK) && !(S_IWOTH & fmode)) ||
2340 ((mask & X_OK) && !(S_IXOTH & fmode)))
2348 else if (r == SQLITE_NOTFOUND)
2358 int sqlfs_proc_readlink(sqlfs_t *sqlfs, const char *path, char *buf, size_t size)
2360 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2361 key_value value = { 0, 0, 0 };
2364 CHECK_PARENT_PATH(path)
2366 r = get_attr(get_sqlfs(sqlfs), path, &attr);
2369 if (!strcmp(attr.type, TYPE_SYM_LINK))
2371 r = get_value(get_sqlfs(sqlfs), path, &value, 0, 0);
2374 if (value.size > size)
2375 { /* too short a buffer */
2377 "warning: readlink provided buffer too small\n");
2380 strncpy(buf, value.data, size);
2382 clean_value(&value);
2398 int sqlfs_proc_readdir(sqlfs_t *sqlfs, const char *path, void *buf, fuse_fill_dir_t filler,
2399 off_t offset, struct fuse_file_info *fi)
2401 int i, r, result = 0;
2404 static const char *cmd = "select key, mode from meta_data where key glob :pattern; ";
2409 CHECK_PARENT_PATH(path)
2410 CHECK_DIR_READ(path)
2412 if ((i = key_is_dir(get_sqlfs(sqlfs), path)), !i)
2423 lpath = strndup(path,strlen(path));
2424 assert(lpath != NULL);
2425 remove_tail_slash(lpath);
2426 filler(buf, ".", NULL, 0);
2427 filler(buf, "..", NULL, 0);
2428 snprintf(tmp, sizeof(tmp), "%s/*", lpath);
2430 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
2433 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
2439 sqlite3_bind_text(stmt, 1, tmp, -1, SQLITE_STATIC);
2444 if (r == SQLITE_ROW)
2446 t = sqlite3_column_text(stmt, 0);
2447 if (!strcmp(t, lpath))
2449 t2 = t + strlen(lpath) + 1;
2450 if (strchr(t2, '/'))
2451 continue; /* grand child, etc. */
2452 if (*t2 == 0) /* special case when dir the root directory */
2455 if (filler(buf, t2, NULL, 0))
2458 else if (r == SQLITE_DONE)
2462 else if (r == SQLITE_BUSY)
2466 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
2471 sqlite3_reset(stmt);
2478 int sqlfs_proc_mknod(sqlfs_t *sqlfs, const char *path, mode_t mode, dev_t rdev)
2480 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2482 if ((S_IFCHR & mode) || (S_IFBLK & mode))
2483 return -EACCES; /* not supported, not allowed */
2485 if (!((S_IFREG & mode) || (S_IFIFO & mode) || (S_IFSOCK & mode)))
2488 CHECK_PARENT_WRITE(path)
2490 r = get_attr(get_sqlfs(sqlfs), path, &attr);
2497 attr.path = strndup(path,strlen(path));
2498 assert(attr.path != NULL);
2499 attr.type = strndup(TYPE_BLOB, strlen(TYPE_BLOB));
2500 assert(attr.path != NULL);
2504 attr.uid = fuse_get_context()->uid;
2505 attr.gid = fuse_get_context()->gid;
2506 /* printf("[%s:%d]attr.uid = %d, attr.gid = %d\n", __FILE__, __LINE__, attr.uid, attr.gid); */
2508 attr.gid = getegid();
2509 attr.uid = geteuid();
2512 attr.gid = get_sqlfs(sqlfs)->gid;
2513 attr.uid = get_sqlfs(sqlfs)->uid;
2516 attr.inode = get_new_inode();
2517 r = set_attr(get_sqlfs(sqlfs), path, &attr);
2518 if (r == SQLITE_BUSY)
2520 else if (r != SQLITE_OK)
2530 int sqlfs_proc_mkdir(sqlfs_t *sqlfs, const char *path, mode_t mode)
2532 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2535 CHECK_PARENT_WRITE(path)
2537 r = get_attr(get_sqlfs(sqlfs), path, &attr);
2544 attr.path = strndup(path,strlen(path));
2545 assert(attr.path != NULL);
2546 attr.type = strndup(TYPE_DIR,strlen(TYPE_DIR));
2547 assert(attr.type != NULL);
2552 attr.uid = fuse_get_context()->uid;
2553 attr.gid = fuse_get_context()->gid;
2554 /* printf("[%s:%d]attr.uid = %d, attr.gid = %d\n", __FILE__, __LINE__, attr.uid, attr.gid); */
2556 attr.gid = getegid();
2557 attr.uid = geteuid();
2560 attr.gid = get_sqlfs(sqlfs)->gid;
2561 attr.uid = get_sqlfs(sqlfs)->uid;
2564 attr.inode = get_new_inode();
2565 r = set_attr(get_sqlfs(sqlfs), path, &attr);
2566 if (r == SQLITE_BUSY)
2568 else if (r != SQLITE_OK)
2577 int sqlfs_proc_unlink(sqlfs_t *sqlfs, const char *path)
2579 int i, r, result = 0;
2581 CHECK_PARENT_WRITE(path)
2583 if ((i = key_exists(get_sqlfs(sqlfs), path, 0)), (i == 0))
2588 if (key_is_dir(get_sqlfs(sqlfs), path))
2596 r = remove_key(get_sqlfs(sqlfs), path);
2597 if (r == SQLITE_BUSY)
2599 else if (r != SQLITE_OK)
2606 int sqlfs_proc_rmdir(sqlfs_t *sqlfs, const char *path)
2610 CHECK_PARENT_WRITE(path)
2612 if (get_dir_children_num(get_sqlfs(sqlfs), path) > 0)
2614 result = -ENOTEMPTY;
2618 r = remove_key(get_sqlfs(sqlfs), path);
2626 int sqlfs_proc_symlink(sqlfs_t *sqlfs, const char *path, const char *to)
2628 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2629 key_value value = { 0, 0, 0 };
2632 CHECK_PARENT_WRITE(to)
2634 r = get_attr(get_sqlfs(sqlfs), to, &attr);
2642 attr.path = strndup(to,strlen(to));
2643 assert(attr.path != NULL);
2644 attr.type = strndup(TYPE_SYM_LINK,strlen(TYPE_SYM_LINK));
2645 assert(attr.path != NULL);
2646 attr.mode = get_sqlfs(sqlfs)->default_mode; /* 0777 ?? */
2649 attr.uid = fuse_get_context()->uid;
2650 attr.gid = fuse_get_context()->gid;
2651 /* printf("[%s:%d]attr.uid = %d, attr.gid = %d\n", __FILE__, __LINE__, attr.uid, attr.gid); */
2653 attr.uid = geteuid();
2654 attr.gid = getegid();
2657 attr.uid = get_sqlfs(sqlfs)->uid;
2658 attr.gid = get_sqlfs(sqlfs)->gid;
2662 attr.inode = get_new_inode();
2663 r = set_attr(get_sqlfs(sqlfs), to, &attr);
2669 if (r == SQLITE_BUSY)
2674 value.data = strndup(path,strlen(path));
2675 assert(value.data != NULL);
2676 value.size = strlen(value.data) + 1;
2678 r = set_value(get_sqlfs(sqlfs), to, &value, 0, 0);
2684 clean_value(&value);
2690 int sqlfs_proc_rename(sqlfs_t *sqlfs, const char *from, const char *to)
2693 int i, r = SQLITE_OK, result = 0;
2695 CHECK_PARENT_WRITE(from)
2696 CHECK_PARENT_WRITE(to)
2698 if ((i = key_exists(get_sqlfs(sqlfs), from, 0)), !i)
2711 if (key_is_dir(get_sqlfs(sqlfs), to) == 1)
2713 if (get_dir_children_num(get_sqlfs(sqlfs), to) > 0)
2716 result = -ENOTEMPTY;
2718 if (!key_is_dir(get_sqlfs(sqlfs), from))
2724 if ((result == 0) && (key_is_dir(get_sqlfs(sqlfs), from) == 1))
2726 if (key_is_dir(get_sqlfs(sqlfs), to) == 0)
2733 if ((i = key_exists(get_sqlfs(sqlfs), to, 0)), (i == 1))
2735 r = remove_key(get_sqlfs(sqlfs), to);
2740 if (r == SQLITE_BUSY)
2751 r = rename_key(get_sqlfs(sqlfs), from, to);
2756 if (r == SQLITE_BUSY)
2767 int sqlfs_proc_link(sqlfs_t *sqlfs, const char *from, const char *to)
2768 { /* hard link not supported, not allowed */
2773 int sqlfs_proc_chmod(sqlfs_t *sqlfs, const char *path, mode_t mode)
2776 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
2779 CHECK_PARENT_PATH(path)
2781 r = get_attr(get_sqlfs(sqlfs), path, &attr);
2786 if (r == SQLITE_BUSY)
2792 if (((fuse_get_context()->uid) != 0) && ((fuse_get_context()->uid) != (uid_t) attr.uid))
2794 if ((geteuid() != 0) && (geteuid() != (uid_t) attr.uid))
2797 if ((get_sqlfs(sqlfs)->uid != 0) && (get_sqlfs(sqlfs)->uid != (uid_t) attr.uid))
2804 attr.mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
2807 r = set_attr(get_sqlfs(sqlfs), path, &attr);
2808 if (r == SQLITE_BUSY)
2810 else if (r != SQLITE_OK)
2821 int sqlfs_proc_chown(sqlfs_t *sqlfs, const char *path, uid_t uid, gid_t gid)
2824 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
2825 int group_change_only = 0;
2828 CHECK_PARENT_PATH(path)
2830 r = get_attr(get_sqlfs(sqlfs), path, &attr);
2835 if (r == SQLITE_BUSY)
2841 if (((fuse_get_context()->uid) == 0) || (((fuse_get_context()->uid) == attr.uid) && (uid == (uid_t) attr.uid)))
2843 if ((geteuid() == 0) || ((geteuid() == attr.uid) && (uid == (uid_t) attr.uid)))
2846 if ((get_sqlfs(sqlfs)->uid == 0) || ((get_sqlfs(sqlfs)->uid == (uid_t) attr.uid) && (uid == (uid_t) attr.uid)))
2856 r = set_attr(get_sqlfs(sqlfs), path, &attr);
2857 if (r == SQLITE_BUSY)
2859 else if (r != SQLITE_OK)
2874 int sqlfs_proc_truncate(sqlfs_t *sqlfs, const char *path, off_t size)
2878 key_value value = { 0, 0, 0 };
2881 CHECK_PARENT_PATH(path)
2884 // baik - get_value ???????요가 ??는 경우.
2885 #ifdef FAST_ATTRIBUTE_SEARCH
2886 if(g_prev_attribute_path!=NULL)
2887 if(strcmp(g_prev_attribute_path,path)==0)
2889 if(g_prev_attr.size > (size_t)size)
2891 value.size = g_prev_attr.size;
2892 goto truncate_shorten;
2897 r = get_value(get_sqlfs(sqlfs), path, &value, 0, 0);
2899 if (r == SQLITE_NOTFOUND)
2907 clean_value(&value);
2908 if (r == SQLITE_BUSY)
2913 if (value.size > (size_t) size)
2915 #ifdef FAST_ATTRIBUTE_SEARCH
2919 r = key_shorten_value(get_sqlfs(sqlfs), path, value.size);
2920 if (r == SQLITE_BUSY)
2922 else if (r != SQLITE_OK)
2925 else if (value.size < (size_t) size)
2927 data = realloc(value.data, size);
2934 memset(data + value.size, 0, size - value.size);
2940 r = set_value(get_sqlfs(sqlfs), path, &value, 0, 0);
2943 if (r == SQLITE_BUSY)
2945 else result = -EACCES;
2949 clean_value(&value);
2955 int sqlfs_proc_utime(sqlfs_t *sqlfs, const char *path, struct utimbuf *buf)
2959 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
2961 CHECK_PARENT_PATH(path)
2963 r = get_attr(get_sqlfs(sqlfs), path, &attr);
2968 if (r == SQLITE_BUSY)
2981 attr.atime = buf->actime;
2982 attr.mtime = buf->modtime;
2984 r = set_attr(get_sqlfs(sqlfs), path, &attr);
2987 if (r == SQLITE_BUSY)
2989 else result = -EACCES;
2998 int sqlfs_proc_create(sqlfs_t *sqlfs, const char *path, mode_t mode, struct fuse_file_info *fi)
3001 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3006 fi->flags |= O_CREAT | O_WRONLY | O_TRUNC;
3008 CHECK_PARENT_WRITE(path)
3010 r = get_attr(get_sqlfs(sqlfs), path, &attr);
3011 if (r == SQLITE_OK) /* already exists */
3013 if (fi->flags & (O_CREAT | O_EXCL))
3019 if (!strcmp(attr.type, TYPE_DIR) && (fi->flags & (O_WRONLY | O_RDWR)))
3026 if (r == SQLITE_BUSY)
3029 /* does not exist */
3030 if ((fi->flags & O_CREAT) == 0)
3037 attr.uid = fuse_get_context()->uid;
3038 attr.gid = fuse_get_context()->gid;
3039 /* printf("[%s:%d]attr.uid = %d, attr.gid = %d\n", __FILE__, __LINE__, attr.uid, attr.gid); */
3041 attr.uid = geteuid();
3042 attr.gid = getegid();
3045 attr.uid = get_sqlfs(sqlfs)->uid;
3046 attr.gid = get_sqlfs(sqlfs)->gid;
3052 attr.path = strndup(path,strlen(path));
3053 assert(attr.path != NULL);
3054 attr.inode = get_new_inode();
3056 if (attr.type == 0){
3057 attr.type = strndup(TYPE_BLOB,strlen(TYPE_BLOB));
3058 assert(attr.type != NULL);
3060 r = set_attr(get_sqlfs(sqlfs), path, &attr);
3061 if (r == SQLITE_BUSY)
3063 else if (r != SQLITE_OK)
3072 int sqlfs_proc_open(sqlfs_t *sqlfs, const char *path, struct fuse_file_info *fi)
3075 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3081 if ((fi->flags & O_CREAT) )
3083 CHECK_PARENT_WRITE(path)
3086 if (fi->flags & (O_WRONLY | O_RDWR))
3088 CHECK_PARENT_PATH(path)
3093 CHECK_PARENT_PATH(path)
3096 r = get_attr(get_sqlfs(sqlfs), path, &attr);
3097 if (r == SQLITE_OK) /* already exists */
3099 if (fi->flags & (O_CREAT | O_EXCL))
3105 if (!strcmp(attr.type, TYPE_DIR) && (fi->flags & (O_WRONLY | O_RDWR)))
3112 if (r == SQLITE_BUSY)
3115 /* does not exist */
3116 if ((fi->flags & O_CREAT) == 0)
3118 if ((result == 0) && (fi->flags & O_CREAT))
3120 attr.mode = get_sqlfs(sqlfs)->default_mode; /* to use some kind of default */
3123 attr.uid = fuse_get_context()->uid;
3124 attr.gid = fuse_get_context()->gid;
3125 /* printf("[%s:%d]attr.uid = %d, attr.gid = %d\n", __FILE__, __LINE__, attr.uid, attr.gid); */
3127 attr.uid = geteuid();
3128 attr.gid = getegid();
3131 attr.uid = get_sqlfs(sqlfs)->uid;
3132 attr.gid = get_sqlfs(sqlfs)->gid;
3137 attr.path = strndup(path,strlen(path));
3138 assert(attr.path != NULL);
3139 attr.inode = get_new_inode();
3141 if (attr.type == 0){
3142 attr.type = strndup(TYPE_BLOB,strlen(TYPE_BLOB));
3143 assert(attr.type != NULL);
3145 r = set_attr(get_sqlfs(sqlfs), path, &attr);
3146 if (r == SQLITE_BUSY)
3157 int sqlfs_proc_read(sqlfs_t *sqlfs, const char *path, char *buf, size_t size, off_t offset, struct
3160 int i, r, result = 0;
3161 int64_t length = size;
3162 key_value value = { 0, 0, 0 };
3165 CHECK_PARENT_PATH(path)
3168 // baik - libc 가 기본??으???open??에 getattr ?????해 처리??다. libc 가 ??처리??다.
3169 #ifndef SQLFS_FAST_TUNNING
3170 if (i = key_is_dir(get_sqlfs(sqlfs), path), (i == 1))
3183 if ((fi->flags & (O_RDONLY | O_RDWR)) == 0)
3186 r = get_value(get_sqlfs(sqlfs), path, &value, offset, offset + size);
3191 else if ((size_t) offset > value.size) /* nothing to read */
3195 if (length > (int64_t) value.size - offset)
3196 length = (int64_t) value.size - offset;
3201 memcpy(buf, ((char*)value.data) + offset, length);
3205 clean_value(&value);
3210 int sqlfs_proc_write(sqlfs_t *sqlfs, const char *path, const char *buf, size_t size, off_t offset,
3211 struct fuse_file_info *fi)
3213 int i, r, result = 0;
3215 size_t length = size, orig_size = 0;
3216 key_value value = { 0, 0, 0 };
3220 // baik - libc 가 기본??으???open??에 getattr ?????해 처리??다. libc 가 ??처리??다.
3221 #ifndef SQLFS_FAST_TUNNING
3222 if (i = key_is_dir(get_sqlfs(sqlfs), path), (i == 1))
3235 if ((fi->flags & (O_WRONLY | O_RDWR)) == 0)
3238 if ((i = key_exists(get_sqlfs(sqlfs), path, &orig_size) == 0), (i == 1))
3240 key_attr attr = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3241 CHECK_PARENT_WRITE(path)
3242 attr.path = strndup(path,strlen(path));
3243 assert(attr.path != NULL);
3244 attr.type = strndup(TYPE_BLOB,strlen(TYPE_BLOB));
3245 assert(attr.path != NULL);
3246 attr.mode = get_sqlfs(sqlfs)->default_mode; /* use default mode */
3249 attr.uid = fuse_get_context()->uid;
3250 attr.gid = fuse_get_context()->gid;
3251 /* printf("[%s:%d]attr.uid = %d, attr.gid = %d\n", __FILE__, __LINE__, attr.uid, attr.gid); */
3253 attr.uid = geteuid();
3254 attr.gid = getegid();
3257 attr.uid = get_sqlfs(sqlfs)->uid;
3258 attr.gid = get_sqlfs(sqlfs)->gid;
3261 attr.inode = get_new_inode();
3262 r = set_attr(get_sqlfs(sqlfs), path, &attr);
3266 clean_value(&value);
3274 CHECK_PARENT_PATH(path)
3281 value.data = calloc(orig_size, sizeof(char));
3282 value.size = orig_size;
3284 if (length > value.size - offset)
3286 data = realloc(value.data, offset + length);
3291 memset(data + value.size, 0, offset + length - value.size);
3293 value.size = offset + length;
3298 memcpy(value.data + offset, buf, length);
3303 if ((size_t) offset > orig_size)
3305 length += offset - orig_size;
3306 offset = orig_size; /* fill in the hole */
3308 r = set_value(get_sqlfs(sqlfs), path, &value, offset, offset + length);
3312 clean_value(&value);
3317 int sqlfs_proc_statfs(sqlfs_t *sqlfs, const char *path, struct statvfs *stbuf)
3319 /* file system information not supported as we have no idea how
3320 to map that to a SQLite file */
3324 int sqlfs_proc_release(sqlfs_t *sqlfs, const char *path, struct fuse_file_info *fi)
3330 int sqlfs_proc_fsync(sqlfs_t *sqlfs, const char *path, int isfdatasync, struct fuse_file_info *fi)
3332 sync(); /* just to sync everything */
3336 int g_full_db_transactioning = 0;
3337 pid_t g_transaction_pid = 0;
3339 typedef enum {XATTR_NS_USER=0, XATTR_NS_SECURITY, XATTR_NS_SYSTEM, XATTR_NS_TRUSTED, XATTR_NS_INVALID} xattr_ns_t;
3340 static const char *validNS[] = {"user", "security", "system", "trusted"}; //man 5 attr
3344 * @param name must be NULL-terminated
3346 static xattr_ns_t xattr_namespace(const char *name)
3348 const char *dot = strchr(name, '.');
3350 return XATTR_NS_INVALID;
3352 int len = dot - name;
3353 int numValidNS = sizeof(validNS)/sizeof(validNS[0]);
3355 for(i = 0; i < numValidNS; i++){
3356 if(strncmp(name, validNS[i], len) == 0){
3360 return XATTR_NS_INVALID;
3364 * @param namespace need not be null-terminated
3366 static bool is_valid_xattr_namespace(const char *namespace, int len)
3368 int numValidNS = sizeof(validNS)/sizeof(validNS[0]);
3370 for(i = 0; i < numValidNS; i++){
3371 if(strncmp(namespace, validNS[i], len) == 0){
3378 static bool has_cap(cap_value_t cap)
3380 pid_t pid = fuse_get_context()->pid;
3381 cap_t capt = cap_get_pid(pid);
3382 cap_flag_value_t set = 0;
3383 int r = cap_get_flag(capt, cap, CAP_EFFECTIVE, &set);
3389 static bool is_special_setxattr_use(const char* str)
3391 static const char *cmds[] = {
3392 "full_db_transaction_check",
3393 "full_db_transaction_start",
3394 "full_db_transaction_stop",
3395 "full_db_transaction_rb" };
3397 int numCmds = sizeof(cmds)/sizeof(cmds[0]);
3398 for(i = 0; i < numCmds; i++){
3399 if(strcmp(str, cmds[i]) == 0){
3406 int sqlfs_proc_setxattr(sqlfs_t *sqlfs, const char *path, const char *name, const void *value,
3407 size_t size, int flags)
3410 if((dot = strchr(name,'.'))){
3415 if(!is_valid_xattr_namespace(name, dot - name)){
3423 CHECK_PARENT_PATH(path)
3425 static const char *cmd = "insert or replace into xattr_data (key,xattr_name,xattr_value) VALUES(:key, :name, :value)";
3426 static const char *cmd_select = "select key from xattr_data where key=:key and xattr_name=:name";
3430 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd_select, -1, &stmt, &tail);
3433 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3437 sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
3438 sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC);
3440 sqlite3_reset(stmt);
3441 if(r == SQLITE_ROW){
3442 if(flags == XATTR_CREATE){
3446 }else if(r == SQLITE_DONE){
3447 if(flags == XATTR_REPLACE){
3453 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3460 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
3463 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3467 sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
3468 sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC);
3469 sqlite3_bind_blob(stmt, 3, value, size, SQLITE_STATIC);
3471 if (r != SQLITE_DONE)
3473 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3476 sqlite3_reset(stmt);
3479 }else if(is_special_setxattr_use(name)){
3485 // alignment problem
3486 // pid = (pid_t*)value;
3487 temp_value = (char*)&pid;
3488 for(i=0; i<sizeof(pid); i++)
3489 *(temp_value+i) = *((char*)(value+i));
3491 // db_transaction 을 걸고, Process 가 죽었을 경우. lock 을 풀어주어야 한다.
3492 // TODO: timeout check
3493 if(g_full_db_transactioning)
3495 if(g_transaction_pid != pid)
3497 sprintf(temp,"/proc/%d",g_transaction_pid);
3498 if(access(temp,F_OK)==-1)
3500 fprintf(stderr,"[NOTE]db_transaction owner maybe died\n");
3501 commit_transaction(get_sqlfs(sqlfs),0);
3502 g_full_db_transactioning = 0;
3503 g_transaction_pid = 0;
3508 if(strcmp(name,"full_db_transaction_check")==0)
3513 if(strcmp(name,"full_db_transaction_start")==0)
3515 if(g_full_db_transactioning==0)
3517 g_full_db_transactioning = 1;
3518 g_transaction_pid = pid;
3519 begin_transaction(get_sqlfs(sqlfs));
3524 if(g_transaction_pid != pid)
3526 fprintf(stderr,"[NOTE]someone have full_db_transaction\n");
3531 fprintf(stderr,"[NOTE]relock... check\n");
3536 else if(strcmp(name,"full_db_transaction_stop")==0)
3538 if(g_full_db_transactioning==1)
3540 commit_transaction(get_sqlfs(sqlfs),1);
3541 g_full_db_transactioning = 0;
3542 g_transaction_pid = 0;
3546 else if(strcmp(name,"full_db_transaction_rb")==0)
3548 if(g_full_db_transactioning==1)
3550 commit_transaction(get_sqlfs(sqlfs),0);
3551 g_full_db_transactioning = 0;
3552 g_transaction_pid = 0;
3563 int sqlfs_proc_getxattr(sqlfs_t *sqlfs, const char *path, const char *name, char *value, size_t size)
3566 static const char *cmd = "select xattr_value from xattr_data where key = :key and xattr_name = :name";
3572 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
3575 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3579 sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
3580 sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC);
3582 if (r == SQLITE_DONE){
3584 }else if(r == SQLITE_ROW){
3585 const void *attr_value = sqlite3_column_blob(stmt, 0);
3586 bytes = sqlite3_column_bytes(stmt, 0);
3589 memcpy(value, attr_value, bytes);
3597 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3600 sqlite3_reset(stmt);
3607 int sqlfs_proc_listxattr(sqlfs_t *sqlfs, const char *path, char *list, size_t size)
3610 static const char *cmd = "select xattr_name from xattr_data where key = :key";
3614 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
3617 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3621 sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
3622 bool sysAdminCap = has_cap(CAP_SYS_ADMIN);
3624 while((r = sql_step(stmt)) == SQLITE_ROW){
3625 const unsigned char *name = sqlite3_column_text(stmt, 0);
3626 int n = sqlite3_column_bytes(stmt, 0);
3627 if(!sysAdminCap && xattr_namespace(name) == XATTR_NS_TRUSTED){
3631 strncpy(list, name, size);
3641 if (r != SQLITE_DONE)
3643 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3646 sqlite3_reset(stmt);
3651 int sqlfs_proc_removexattr(sqlfs_t *sqlfs, const char *path, const char *name)
3658 static const char *cmd_select = "select key from xattr_data where key=:key and xattr_name=:name";
3659 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd_select, -1, &stmt, &tail);
3662 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3665 sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
3666 sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC);
3668 sqlite3_reset(stmt);
3669 if(r != SQLITE_ROW){
3670 //key,name pair doesn't exist in database
3675 static const char *cmd = "delete from xattr_data where key=:key and xattr_name=:name";
3676 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
3679 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3682 sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
3683 sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC);
3685 sqlite3_reset(stmt);
3686 if(r != SQLITE_DONE){
3693 int sqlfs_del_tree(sqlfs_t *sqlfs, const char *key)
3697 CHECK_PARENT_WRITE(key)
3698 CHECK_DIR_WRITE(key)
3700 if ((i = key_exists(get_sqlfs(sqlfs), key, 0)), (i == 0))
3707 if (SQLITE_OK == remove_key_subtree(get_sqlfs(sqlfs), key))
3717 int sqlfs_del_tree_with_exclusion(sqlfs_t *sqlfs, const char *key, const char *exclusion_pattern)
3721 CHECK_PARENT_WRITE(key)
3722 CHECK_DIR_WRITE(key)
3724 if ((i = key_exists(get_sqlfs(sqlfs), key, 0)) == 0)
3731 if (SQLITE_OK == remove_key_subtree_with_exclusion(get_sqlfs(sqlfs), key, exclusion_pattern))
3742 int sqlfs_get_value(sqlfs_t *sqlfs, const char *key, key_value *value,
3743 size_t begin, size_t end)
3747 if (check_parent_access(sqlfs, key) != 0)
3750 if (sqlfs_proc_access(sqlfs, key, R_OK | F_OK) != 0)
3753 r = get_value(get_sqlfs(sqlfs), key, value, begin, end);
3756 if (r == SQLITE_NOTFOUND)
3758 return SQLITE_OK == r;
3761 int sqlfs_set_value(sqlfs_t *sqlfs, const char *key, const key_value *value,
3762 size_t begin, size_t end)
3766 if (check_parent_access(sqlfs, key) != 0)
3769 if (sqlfs_proc_access(sqlfs, key, W_OK | F_OK) != 0)
3772 r = set_value(get_sqlfs(sqlfs), key, value, begin, end);
3774 return SQLITE_OK == r;
3777 int sqlfs_get_attr(sqlfs_t *sqlfs, const char *key, key_attr *attr)
3781 if ((i = check_parent_access(sqlfs, key)) != 0)
3785 else if (i == -EACCES)
3790 if ((i = sqlfs_proc_access(sqlfs, key, R_OK | F_OK)) != 0)
3794 else if (i == -EACCES)
3800 i = get_attr(get_sqlfs(sqlfs), key, attr);
3803 else if (i == SQLITE_NOTFOUND)
3807 //fprintf(stderr, "return %d on %s\n", r, key);//???
3812 int sqlfs_set_attr(sqlfs_t *sqlfs, const char *key, const key_attr *attr)
3817 if (check_parent_access(sqlfs, key) != 0)
3820 if (sqlfs_proc_access(sqlfs, key, W_OK | F_OK) != 0)
3823 r = set_attr(get_sqlfs(sqlfs), key, attr);
3826 return SQLITE_OK == r;
3829 int sqlfs_begin_transaction(sqlfs_t *sqlfs)
3832 r = begin_transaction(get_sqlfs(sqlfs));
3833 if (r == SQLITE_BUSY)
3835 return SQLITE_OK == r;
3839 int sqlfs_complete_transaction(sqlfs_t *sqlfs, int i)
3842 r = commit_transaction(get_sqlfs(sqlfs), i);
3843 if (r == SQLITE_BUSY)
3846 return SQLITE_OK == r;
3850 int sqlfs_break_transaction(sqlfs_t *sqlfs)
3853 r = break_transaction(sqlfs, 0);
3854 if (r == SQLITE_BUSY)
3856 return SQLITE_OK == r;
3860 int sqlfs_set_type(sqlfs_t *sqlfs, const char *key, const char *type)
3862 int r = SQLITE_DONE;
3864 if (check_parent_access(sqlfs, key) != 0)
3867 if (sqlfs_proc_access(sqlfs, key, W_OK | F_OK) != 0)
3870 r = key_set_type(get_sqlfs(sqlfs), key, type);
3873 if (r == SQLITE_BUSY)
3875 return (r == SQLITE_DONE);
3883 int sqlfs_list_keys(sqlfs_t *sqlfs, const char *pattern, void *buf, fuse_fill_dir_t filler)
3888 static const char *cmd = "select key, mode from meta_data where key glob :pattern; ";
3894 lpath = strndup(pattern,strlen(pattern));
3895 assert(lpath != NULL);;
3896 remove_tail_slash(lpath);
3898 snprintf(tmp, sizeof(tmp), "%s", pattern);
3900 SQLITE3_PREPARE(get_sqlfs(sqlfs)->db, cmd, -1, &stmt, &tail);
3903 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3909 sqlite3_bind_text(stmt, 1, tmp, -1, SQLITE_STATIC);
3914 if (r == SQLITE_ROW)
3916 t = sqlite3_column_text(stmt, 0);
3917 if (filler(buf, t, NULL, 0))
3920 else if (r == SQLITE_DONE)
3924 else if (r == SQLITE_BUSY)
3931 show_msg(stderr, "%s\n", sqlite3_errmsg(get_sqlfs(sqlfs)->db));
3936 sqlite3_reset(stmt);
3943 int sqlfs_is_dir(sqlfs_t *sqlfs, const char *key)
3945 return key_is_dir(sqlfs, key);
3949 static int create_db_table(sqlfs_t *sqlfs)
3950 { /* ensure tables are created if not existing already
3951 if already exist, command results ignored so no effects */
3952 static const char *cmd1 =
3953 " CREATE TABLE meta_data(key text, type text, inode integer, uid integer, gid integer, mode integer,"
3954 "acl text, attribute text, atime integer, mtime integer, ctime integer, size integer,"
3955 "block_size integer, primary key (key), unique(key))" ;
3956 static const char *cmd2 =
3957 " CREATE TABLE value_data (key text, block_no integer, data_block blob, unique(key, block_no))";
3958 static const char *cmd3 = "CREATE TABLE xattr_data (key text, xattr_name text, xattr_value blob, unique(key, xattr_name))";
3959 static const char *cmd4 = "create index meta_index on meta_data (key);";
3961 sqlite3_exec(get_sqlfs(sqlfs)->db, cmd1, NULL, NULL, NULL);
3962 sqlite3_exec(get_sqlfs(sqlfs)->db, cmd2, NULL, NULL, NULL);
3963 sqlite3_exec(get_sqlfs(sqlfs)->db, cmd3, NULL, NULL, NULL);
3964 sqlite3_exec(get_sqlfs(sqlfs)->db, cmd4, NULL, NULL, NULL);
3970 static void * sqlfs_t_init(const char *db_file)
3973 sqlfs_t *sql_fs = calloc(1, sizeof(*sql_fs));
3975 for (i = 0; i < (int)(sizeof(sql_fs->stmts) / sizeof(sql_fs->stmts[0])); i++)
3977 sql_fs->stmts[i] = 0;
3979 r = sqlite3_open(db_file, &(sql_fs->db));
3982 fprintf(stderr, "Cannot open the database file %s\n", db_file);
3986 sql_fs->default_mode = 0700; /* allows the creation of children under / , default user at initialization is 0 (root)*/
3988 create_db_table( sql_fs);
3991 max_inode = get_current_max_inode(sql_fs);
3993 /*sqlite3_busy_timeout( sql_fs->db, 500); *//* default timeout 0.5 seconds */
3994 sqlite3_exec(sql_fs->db, "PRAGMA synchronous = FULL;", NULL, NULL, NULL);
3995 sqlite3_exec(sql_fs->db, "PRAGMA journal_mode = persist;", NULL, NULL, NULL);
3996 ensure_existence(sql_fs, "/", TYPE_DIR);
3997 return (void *) sql_fs;
4002 static void sqlfs_t_finalize(void *arg)
4005 sqlfs_t *sql_fs = (sqlfs_t *) arg;
4008 for (i = 0; i < (int)(sizeof(sql_fs->stmts) / sizeof(sql_fs->stmts[0])); i++)
4010 if (sql_fs->stmts[i])
4011 sqlite3_finalize(sql_fs->stmts[i]);
4013 sqlite3_close(sql_fs->db);
4020 int sqlfs_open(const char *db_file, sqlfs_t **sqlfs)
4023 db_file = default_db_file;
4024 *sqlfs = sqlfs_t_init(db_file);
4030 int sqlfs_close(sqlfs_t *sqlfs)
4033 sqlfs_t_finalize(sqlfs);
4041 static int sqlfs_op_getattr(const char *path, struct stat *stbuf)
4043 return sqlfs_proc_getattr(0, path, stbuf);
4046 static int sqlfs_op_access(const char *path, int mask)
4048 return sqlfs_proc_access(0, path, mask);
4050 static int sqlfs_op_readlink(const char *path, char *buf, size_t size)
4052 return sqlfs_proc_readlink(0, path, buf, size);
4054 static int sqlfs_op_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
4055 off_t offset, struct fuse_file_info *fi)
4057 return sqlfs_proc_readdir(0, path, buf, filler, offset, fi);
4059 static int sqlfs_op_mknod(const char *path, mode_t mode, dev_t rdev)
4061 return sqlfs_proc_mknod(0, path, mode, rdev);
4063 static int sqlfs_op_mkdir(const char *path, mode_t mode)
4065 return sqlfs_proc_mkdir(0, path, mode);
4067 static int sqlfs_op_unlink(const char *path)
4069 return sqlfs_proc_unlink(0, path);
4071 static int sqlfs_op_rmdir(const char *path)
4073 return sqlfs_proc_rmdir(0, path);
4075 static int sqlfs_op_symlink(const char *path, const char *to)
4077 return sqlfs_proc_symlink(0, path, to);
4079 static int sqlfs_op_rename(const char *from, const char *to)
4081 return sqlfs_proc_rename(0, from, to);
4083 static int sqlfs_op_link(const char *from, const char *to)
4085 return sqlfs_proc_link(0, from, to);
4087 static int sqlfs_op_chmod(const char *path, mode_t mode)
4089 return sqlfs_proc_chmod(0, path, mode);
4091 static int sqlfs_op_chown(const char *path, uid_t uid, gid_t gid)
4093 return sqlfs_proc_chown(0, path, uid, gid);
4095 static int sqlfs_op_truncate(const char *path, off_t size)
4097 return sqlfs_proc_truncate(0, path, size);
4099 static int sqlfs_op_utime(const char *path, struct utimbuf *buf)
4101 return sqlfs_proc_utime(0, path, buf);
4103 int sqlfs_op_create(const char *path, mode_t mode, struct fuse_file_info *fi)
4105 return sqlfs_proc_create(0, path, mode, fi);
4108 static int sqlfs_op_open(const char *path, struct fuse_file_info *fi)
4110 return sqlfs_proc_open(0, path, fi);
4112 static int sqlfs_op_read(const char *path, char *buf, size_t size, off_t offset, struct
4115 return sqlfs_proc_read(0, path, buf, size, offset, fi);
4117 static int sqlfs_op_write(const char *path, const char *buf, size_t size, off_t offset,
4118 struct fuse_file_info *fi)
4120 return sqlfs_proc_write(0, path, buf, size, offset, fi);
4122 static int sqlfs_op_statfs(const char *path, struct statvfs *stbuf)
4124 return sqlfs_proc_statfs(0, path, stbuf);
4126 static int sqlfs_op_release(const char *path, struct fuse_file_info *fi)
4128 return sqlfs_proc_release(0, path, fi);
4130 static int sqlfs_op_fsync(const char *path, int isfdatasync, struct fuse_file_info *fi)
4132 return sqlfs_proc_fsync(0, path, isfdatasync, fi);
4134 static int sqlfs_op_setxattr(const char *path, const char *name, const char *value,
4135 size_t size, int flags)
4137 return sqlfs_proc_setxattr(0, path, name, value, size, flags);
4139 static int sqlfs_op_getxattr(const char *path, const char *name, char *value, size_t size)
4141 return sqlfs_proc_getxattr(0, path, name, value, size);
4143 static int sqlfs_op_listxattr(const char *path, char *list, size_t size)
4145 return sqlfs_proc_listxattr(0, path, list, size);
4147 static int sqlfs_op_removexattr(const char *path, const char *name)
4149 return sqlfs_proc_removexattr(0, path, name);
4152 static struct fuse_operations sqlfs_op;
4156 int sqlfs_init(const char *db_file_name)
4159 sqlfs_op.getattr = sqlfs_op_getattr;
4160 sqlfs_op.access = sqlfs_op_access;
4161 sqlfs_op.readlink = sqlfs_op_readlink;
4162 sqlfs_op.readdir = sqlfs_op_readdir;
4163 sqlfs_op.mknod = sqlfs_op_mknod;
4164 sqlfs_op.mkdir = sqlfs_op_mkdir;
4165 sqlfs_op.symlink = sqlfs_op_symlink;
4166 sqlfs_op.unlink = sqlfs_op_unlink;
4167 sqlfs_op.rmdir = sqlfs_op_rmdir;
4168 sqlfs_op.rename = sqlfs_op_rename;
4169 sqlfs_op.link = sqlfs_op_link;
4170 sqlfs_op.chmod = sqlfs_op_chmod;
4171 sqlfs_op.chown = sqlfs_op_chown;
4172 sqlfs_op.truncate = sqlfs_op_truncate;
4173 sqlfs_op.utime = sqlfs_op_utime;
4174 sqlfs_op.open = sqlfs_op_open;
4175 sqlfs_op.create = sqlfs_op_create;
4176 sqlfs_op.read = sqlfs_op_read;
4177 sqlfs_op.write = sqlfs_op_write;
4178 sqlfs_op.statfs = sqlfs_op_statfs;
4179 sqlfs_op.release = sqlfs_op_release;
4180 sqlfs_op.fsync = sqlfs_op_fsync;
4183 sqlfs_op.setxattr = sqlfs_op_setxattr;
4184 sqlfs_op.getxattr = sqlfs_op_getxattr;
4185 sqlfs_op.listxattr = sqlfs_op_listxattr;
4186 sqlfs_op.removexattr= sqlfs_op_removexattr;
4191 strncpy(default_db_file, db_file_name, sizeof(default_db_file));
4192 pthread_key_create(&sql_key, sqlfs_t_finalize);
4198 int sqlfs_fuse_main(int argc, char **argv)
4202 return fuse_main(argc, argv, &sqlfs_op);