Overview
Comment: | Updated to support unthreaded Tcl and fixed a memory leak with home directory determination |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6af0168ed827e5774e23d29cc8b9ea61 |
User & Date: | rkeene on 2014-11-14 21:46:19 |
Other Links: | manifest | tags |
Context
2014-11-15
| ||
16:46 | Added more debugging, renamed appfs_terminate_interp for with more accurate name, fixed FUSE read/write to use pread/pwrite and return no short reads as is required by FUSE, added call to Tcl_FinalizeThread() on thread termination check-in: d5bfe6710c user: rkeene tags: trunk | |
2014-11-14
| ||
21:46 | Updated to support unthreaded Tcl and fixed a memory leak with home directory determination check-in: 6af0168ed8 user: rkeene tags: trunk | |
21:44 | Updated to use TCL_DEFS from tclConfig.sh check-in: 24908ac300 user: rkeene tags: trunk | |
Changes
Modified appfsd.c from [b7668e46f2] to [1768754e26].
51 51 /* 52 52 * Global variables for AppFS caching 53 53 */ 54 54 pthread_mutex_t appfs_path_info_cache_mutex = PTHREAD_MUTEX_INITIALIZER; 55 55 int appfs_path_info_cache_size = 8209; 56 56 struct appfs_pathinfo *appfs_path_info_cache = NULL; 57 57 58 +#ifndef TCL_THREADS 59 +/* 60 + * Handle unthreaded Tcl 61 + */ 62 +pthread_mutex_t appfs_tcl_big_global_lock = PTHREAD_MUTEX_INITIALIZER; 63 +#define appfs_call_libtcl_enter pthread_mutex_lock(&appfs_tcl_big_global_lock); 64 +#define appfs_call_libtcl_exit pthread_mutex_unlock(&appfs_tcl_big_global_lock); 65 +#else 66 +#define appfs_call_libtcl_enter /**/ 67 +#define appfs_call_libtcl_exit /**/ 68 +#endif 69 +#define appfs_call_libtcl(x...) appfs_call_libtcl_enter x appfs_call_libtcl_exit 70 + 58 71 /* 59 72 * Global variables for AppFS Tcl Interpreter restarting 60 73 */ 61 74 int interp_reset_key = 0; 62 75 63 76 /* 64 77 * AppFS Path Type: Describes the type of path a given file is ................................................................................ 105 118 106 119 /* 107 120 * Create a new Tcl interpreter and completely initialize it 108 121 */ 109 122 static Tcl_Interp *appfs_create_TclInterp(char **error_string) { 110 123 Tcl_Interp *interp; 111 124 int tcl_ret; 125 + const char *tcl_setvar_ret; 112 126 113 127 APPFS_DEBUG("Creating new Tcl interpreter for TID = 0x%llx", (unsigned long long) pthread_self()); 114 128 115 - interp = Tcl_CreateInterp(); 129 + appfs_call_libtcl( 130 + interp = Tcl_CreateInterp(); 131 + ) 116 132 if (interp == NULL) { 117 133 fprintf(stderr, "Unable to create Tcl Interpreter. Aborting.\n"); 118 134 119 135 if (error_string) { 120 136 *error_string = strdup("Unable to create Tcl interpreter."); 121 137 } 122 138 123 139 return(NULL); 124 140 } 125 141 126 - Tcl_Preserve(interp); 142 + appfs_call_libtcl(Tcl_Preserve(interp);) 127 143 128 - tcl_ret = Tcl_Init(interp); 144 + appfs_call_libtcl( 145 + tcl_ret = Tcl_Init(interp); 146 + ) 129 147 if (tcl_ret != TCL_OK) { 130 148 fprintf(stderr, "Unable to initialize Tcl. Aborting.\n"); 131 - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 149 + appfs_call_libtcl( 150 + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 151 + ) 152 + 153 + if (error_string) { 154 + appfs_call_libtcl( 155 + *error_string = strdup(Tcl_GetStringResult(interp)); 156 + ) 157 + } 158 + 159 + appfs_call_libtcl(Tcl_Release(interp);) 160 + 161 + APPFS_DEBUG("Terminating Tcl interpreter."); 162 + 163 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 164 + 165 + return(NULL); 166 + } 167 + 168 + appfs_call_libtcl( 169 + tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]"); 170 + ) 171 + if (tcl_ret != TCL_OK) { 172 + fprintf(stderr, "Unable to initialize Tcl SHA1. Aborting.\n"); 173 + appfs_call_libtcl( 174 + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 175 + ) 132 176 133 177 if (error_string) { 134 - *error_string = strdup(Tcl_GetStringResult(interp)); 178 + appfs_call_libtcl( 179 + *error_string = strdup(Tcl_GetStringResult(interp)); 180 + ) 135 181 } 136 182 137 - Tcl_Release(interp); 183 + appfs_call_libtcl(Tcl_Release(interp);) 138 184 139 185 APPFS_DEBUG("Terminating Tcl interpreter."); 140 186 141 - Tcl_DeleteInterp(interp); 187 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 142 188 143 189 return(NULL); 144 190 } 145 191 146 - tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]"); 192 + appfs_call_libtcl( 193 + tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]"); 194 + ) 147 195 if (tcl_ret != TCL_OK) { 148 - fprintf(stderr, "Unable to initialize Tcl SHA1. Aborting.\n"); 149 - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 196 + fprintf(stderr, "Unable to initialize Tcl AppFS Package. Aborting.\n"); 197 + appfs_call_libtcl( 198 + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 199 + ) 150 200 151 201 if (error_string) { 152 - *error_string = strdup(Tcl_GetStringResult(interp)); 202 + appfs_call_libtcl( 203 + *error_string = strdup(Tcl_GetStringResult(interp)); 204 + ) 153 205 } 154 206 155 - Tcl_Release(interp); 207 + appfs_call_libtcl(Tcl_Release(interp);) 156 208 157 209 APPFS_DEBUG("Terminating Tcl interpreter."); 158 210 159 - Tcl_DeleteInterp(interp); 160 - 161 - return(NULL); 162 - } 163 - 164 - tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]"); 165 - if (tcl_ret != TCL_OK) { 166 - fprintf(stderr, "Unable to initialize Tcl AppFS Package. Aborting.\n"); 167 - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 168 - 169 - if (error_string) { 170 - *error_string = strdup(Tcl_GetStringResult(interp)); 171 - } 172 - 173 - Tcl_Release(interp); 174 - 175 - APPFS_DEBUG("Terminating Tcl interpreter."); 176 - 177 - Tcl_DeleteInterp(interp); 211 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 178 212 179 213 return(NULL); 180 214 } 181 215 182 216 /* 183 217 * Load "pki.tcl" in the same way as appfsd.tcl (see below) 184 218 */ 185 - tcl_ret = Tcl_Eval(interp, "" 219 + appfs_call_libtcl_enter 220 + tcl_ret = Tcl_Eval(interp, "" 186 221 #include "pki.tcl.h" 187 - ""); 222 + ""); 223 + appfs_call_libtcl_exit 188 224 if (tcl_ret != TCL_OK) { 189 225 fprintf(stderr, "Unable to initialize Tcl PKI. Aborting.\n"); 190 - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 226 + appfs_call_libtcl( 227 + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 228 + ) 191 229 192 230 if (error_string) { 193 - *error_string = strdup(Tcl_GetStringResult(interp)); 231 + appfs_call_libtcl( 232 + *error_string = strdup(Tcl_GetStringResult(interp)); 233 + ) 194 234 } 195 235 196 - Tcl_Release(interp); 236 + appfs_call_libtcl(Tcl_Release(interp);) 197 237 198 238 APPFS_DEBUG("Terminating Tcl interpreter."); 199 239 200 - Tcl_DeleteInterp(interp); 240 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 201 241 202 242 return(NULL); 203 243 } 204 244 205 245 /* 206 246 * Load the "appfsd.tcl" script, which is "compiled" into a C header 207 247 * so that it does not need to exist on the filesystem and can be 208 248 * directly evaluated. 209 249 */ 210 - tcl_ret = Tcl_Eval(interp, "" 250 + appfs_call_libtcl_enter 251 + tcl_ret = Tcl_Eval(interp, "" 211 252 #include "appfsd.tcl.h" 212 - ""); 253 + ""); 254 + appfs_call_libtcl_exit 213 255 if (tcl_ret != TCL_OK) { 214 256 fprintf(stderr, "Unable to initialize Tcl AppFS script. Aborting.\n"); 215 - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 257 + appfs_call_libtcl( 258 + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 259 + ) 216 260 217 261 if (error_string) { 218 - *error_string = strdup(Tcl_GetStringResult(interp)); 262 + appfs_call_libtcl( 263 + *error_string = strdup(Tcl_GetStringResult(interp)); 264 + ) 219 265 } 220 266 221 - Tcl_Release(interp); 267 + appfs_call_libtcl(Tcl_Release(interp);) 222 268 223 269 APPFS_DEBUG("Terminating Tcl interpreter."); 224 270 225 - Tcl_DeleteInterp(interp); 271 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 226 272 227 273 return(NULL); 228 274 } 229 275 230 276 /* 231 277 * Set global variables from C to Tcl 232 278 */ 233 - if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) { 279 + appfs_call_libtcl( 280 + tcl_setvar_ret = Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY); 281 + ) 282 + if (tcl_setvar_ret == NULL) { 234 283 fprintf(stderr, "Unable to set cache directory. This should never fail.\n"); 235 284 236 285 if (error_string) { 237 - *error_string = strdup(Tcl_GetStringResult(interp)); 286 + appfs_call_libtcl( 287 + *error_string = strdup(Tcl_GetStringResult(interp)); 288 + ) 238 289 } 239 290 240 - Tcl_Release(interp); 291 + appfs_call_libtcl(Tcl_Release(interp);) 241 292 242 293 APPFS_DEBUG("Terminating Tcl interpreter."); 243 294 244 - Tcl_DeleteInterp(interp); 295 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 245 296 246 297 return(NULL); 247 298 } 248 299 249 300 /* 250 301 * Initialize the "appfsd.tcl" environment, which must be done after 251 302 * global variables are set. 252 303 */ 253 - tcl_ret = Tcl_Eval(interp, "::appfs::init"); 304 + appfs_call_libtcl( 305 + tcl_ret = Tcl_Eval(interp, "::appfs::init"); 306 + ) 254 307 if (tcl_ret != TCL_OK) { 255 308 fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init). Aborting.\n"); 256 - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 309 + appfs_call_libtcl( 310 + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 311 + ) 257 312 258 313 if (error_string) { 259 - *error_string = strdup(Tcl_GetStringResult(interp)); 314 + appfs_call_libtcl( 315 + *error_string = strdup(Tcl_GetStringResult(interp)); 316 + ) 260 317 } 261 318 262 - Tcl_Release(interp); 319 + appfs_call_libtcl(Tcl_Release(interp);) 263 320 264 321 APPFS_DEBUG("Terminating Tcl interpreter."); 265 322 266 - Tcl_DeleteInterp(interp); 323 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 267 324 268 325 return(NULL); 269 326 } 270 327 271 328 /* 272 329 * Hide some Tcl commands that we do not care to use and which may 273 330 * slow down run-time operations. 274 331 */ 275 - Tcl_HideCommand(interp, "auto_load_index", "auto_load_index"); 276 - Tcl_HideCommand(interp, "unknown", "unknown"); 277 - Tcl_HideCommand(interp, "exit", "exit"); 332 + appfs_call_libtcl( 333 + Tcl_HideCommand(interp, "auto_load_index", "auto_load_index"); 334 + Tcl_HideCommand(interp, "unknown", "unknown"); 335 + Tcl_HideCommand(interp, "exit", "exit"); 336 + ) 278 337 279 338 /* 280 339 * Release the hold we have on the interpreter so that it may be 281 340 * deleted if needed 282 341 */ 283 - Tcl_Release(interp); 342 + appfs_call_libtcl(Tcl_Release(interp);) 284 343 285 344 /* 286 345 * Return the completely initialized interpreter 287 346 */ 288 347 return(interp); 289 348 } 290 349 ................................................................................ 299 358 300 359 global_interp_reset_key = __sync_fetch_and_add(&interp_reset_key, 0); 301 360 302 361 interp = pthread_getspecific(interpKey); 303 362 if (interp != NULL && thread_interp_reset_key != global_interp_reset_key) { 304 363 APPFS_DEBUG("Terminating old interpreter and restarting due to reset request."); 305 364 306 - Tcl_DeleteInterp(interp); 365 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 307 366 308 367 interp = NULL; 309 368 310 369 pthread_ret = pthread_setspecific(interpKey, interp); 311 370 } 312 371 313 372 if (global_interp_reset_key == -1) { ................................................................................ 325 384 return(NULL); 326 385 } 327 386 328 387 pthread_ret = pthread_setspecific(interpKey, interp); 329 388 if (pthread_ret != 0) { 330 389 APPFS_DEBUG("pthread_setspecific() failed. Terminating Tcl interpreter."); 331 390 332 - Tcl_DeleteInterp(interp); 391 + appfs_call_libtcl(Tcl_DeleteInterp(interp);) 333 392 334 393 return(NULL); 335 394 } 336 395 } 337 396 338 397 return(interp); 339 398 } ................................................................................ 351 410 352 411 if (interp == NULL) { 353 412 return(TCL_ERROR); 354 413 } 355 414 356 415 objv = (void *) ckalloc(sizeof(*objv) * objc); 357 416 358 - objv[0] = Tcl_NewStringObj(cmd, -1); 359 - 360 - Tcl_IncrRefCount(objv[0]); 361 - 362 - va_start(argp, cmd); 363 - for (i = 1; i < objc; i++) { 364 - arg = va_arg(argp, const char *); 365 - 366 - objv[i] = Tcl_NewStringObj(arg, -1); 367 - 368 - Tcl_IncrRefCount(objv[i]); 369 - } 370 - va_end(argp); 371 - 372 - retval = Tcl_EvalObjv(interp, objc, objv, 0); 373 - 374 - for (i = 0; i < objc; i++) { 375 - Tcl_DecrRefCount(objv[i]); 376 - } 417 + appfs_call_libtcl( 418 + objv[0] = Tcl_NewStringObj(cmd, -1); 419 + 420 + Tcl_IncrRefCount(objv[0]); 421 + 422 + va_start(argp, cmd); 423 + for (i = 1; i < objc; i++) { 424 + arg = va_arg(argp, const char *); 425 + 426 + objv[i] = Tcl_NewStringObj(arg, -1); 427 + 428 + Tcl_IncrRefCount(objv[i]); 429 + } 430 + va_end(argp); 431 + ) 432 + 433 + appfs_call_libtcl( 434 + retval = Tcl_EvalObjv(interp, objc, objv, 0); 435 + ) 436 + 437 + appfs_call_libtcl( 438 + for (i = 0; i < objc; i++) { 439 + Tcl_DecrRefCount(objv[i]); 440 + } 441 + ) 377 442 378 443 ckfree((void *) objv); 379 444 380 445 if (retval != TCL_OK) { 381 - APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0)); 446 + appfs_call_libtcl( 447 + APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0)); 448 + ) 382 449 } 383 450 384 451 return(retval); 385 452 } 386 453 387 454 /* 388 455 * Request all Tcl interpreters restart ................................................................................ 696 763 Tcl_Obj *attrs_dict, *attr_value; 697 764 const char *attr_value_str; 698 765 Tcl_WideInt attr_value_wide; 699 766 int attr_value_int; 700 767 static __thread Tcl_Obj *attr_key_type = NULL, *attr_key_perms = NULL, *attr_key_size = NULL, *attr_key_time = NULL, *attr_key_source = NULL, *attr_key_childcount = NULL, *attr_key_packaged = NULL; 701 768 int cache_ret; 702 769 int tcl_ret; 770 + int retval; 703 771 uid_t fsuid; 772 + 773 + retval = 0; 704 774 705 775 fsuid = appfs_get_fsuid(); 706 776 707 777 cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo); 708 778 if (cache_ret == 0) { 709 779 if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) { 710 780 return(-ENOENT); ................................................................................ 718 788 } 719 789 720 790 interp = appfs_TclInterp(); 721 791 if (interp == NULL) { 722 792 return(-EIO); 723 793 } 724 794 725 - Tcl_Preserve(interp); 795 + appfs_call_libtcl(Tcl_Preserve(interp);) 726 796 727 797 tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path); 728 798 if (tcl_ret != TCL_OK) { 729 799 APPFS_DEBUG("::appfs::getattr(%s) failed.", path); 730 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 800 + appfs_call_libtcl( 801 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 802 + ) 731 803 732 804 pathinfo->type = APPFS_PATHTYPE_DOES_NOT_EXIST; 733 805 734 806 appfs_get_path_info_cache_add(path, fsuid, pathinfo); 735 807 736 - Tcl_Release(interp); 808 + appfs_call_libtcl(Tcl_Release(interp);) 737 809 738 810 return(-ENOENT); 739 811 } 740 812 741 813 if (attr_key_type == NULL) { 742 - attr_key_type = Tcl_NewStringObj("type", -1); 743 - attr_key_perms = Tcl_NewStringObj("perms", -1); 744 - attr_key_size = Tcl_NewStringObj("size", -1); 745 - attr_key_time = Tcl_NewStringObj("time", -1); 746 - attr_key_source = Tcl_NewStringObj("source", -1); 747 - attr_key_childcount = Tcl_NewStringObj("childcount", -1); 748 - attr_key_packaged = Tcl_NewStringObj("packaged", -1); 814 + appfs_call_libtcl( 815 + attr_key_type = Tcl_NewStringObj("type", -1); 816 + attr_key_perms = Tcl_NewStringObj("perms", -1); 817 + attr_key_size = Tcl_NewStringObj("size", -1); 818 + attr_key_time = Tcl_NewStringObj("time", -1); 819 + attr_key_source = Tcl_NewStringObj("source", -1); 820 + attr_key_childcount = Tcl_NewStringObj("childcount", -1); 821 + attr_key_packaged = Tcl_NewStringObj("packaged", -1); 822 + 823 + Tcl_IncrRefCount(attr_key_type); 824 + Tcl_IncrRefCount(attr_key_perms); 825 + Tcl_IncrRefCount(attr_key_size); 826 + Tcl_IncrRefCount(attr_key_time); 827 + Tcl_IncrRefCount(attr_key_source); 828 + Tcl_IncrRefCount(attr_key_childcount); 829 + Tcl_IncrRefCount(attr_key_packaged); 830 + ) 749 831 } 750 832 751 - attrs_dict = Tcl_GetObjResult(interp); 752 - tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value); 833 + appfs_call_libtcl( 834 + attrs_dict = Tcl_GetObjResult(interp); 835 + tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value); 836 + ) 753 837 if (tcl_ret != TCL_OK) { 754 838 APPFS_DEBUG("[dict get \"type\"] failed"); 755 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 839 + appfs_call_libtcl( 840 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 841 + ) 756 842 757 - Tcl_Release(interp); 843 + appfs_call_libtcl(Tcl_Release(interp);) 758 844 759 845 return(-EIO); 760 846 } 761 847 762 848 if (attr_value == NULL) { 763 - Tcl_Release(interp); 849 + appfs_call_libtcl(Tcl_Release(interp);) 764 850 765 851 return(-EIO); 766 852 } 767 853 768 854 pathinfo->packaged = 0; 769 855 pathinfo->inode = appfs_get_path_inode(path); 770 856 771 - attr_value_str = Tcl_GetString(attr_value); 857 + appfs_call_libtcl( 858 + attr_value_str = Tcl_GetString(attr_value); 772 859 773 - switch (attr_value_str[0]) { 774 - case 'd': /* directory */ 775 - pathinfo->type = APPFS_PATHTYPE_DIRECTORY; 776 - pathinfo->typeinfo.dir.childcount = 0; 860 + switch (attr_value_str[0]) { 861 + case 'd': /* directory */ 862 + pathinfo->type = APPFS_PATHTYPE_DIRECTORY; 863 + pathinfo->typeinfo.dir.childcount = 0; 777 864 778 - Tcl_DictObjGet(interp, attrs_dict, attr_key_childcount, &attr_value); 779 - if (attr_value != NULL) { 780 - tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); 781 - if (tcl_ret == TCL_OK) { 782 - pathinfo->typeinfo.dir.childcount = attr_value_wide; 865 + Tcl_DictObjGet(interp, attrs_dict, attr_key_childcount, &attr_value); 866 + if (attr_value != NULL) { 867 + tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); 868 + if (tcl_ret == TCL_OK) { 869 + pathinfo->typeinfo.dir.childcount = attr_value_wide; 870 + } 871 + } 872 + 873 + break; 874 + case 'f': /* file */ 875 + pathinfo->type = APPFS_PATHTYPE_FILE; 876 + pathinfo->typeinfo.file.size = 0; 877 + pathinfo->typeinfo.file.executable = 0; 878 + 879 + Tcl_DictObjGet(interp, attrs_dict, attr_key_size, &attr_value); 880 + if (attr_value != NULL) { 881 + tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); 882 + if (tcl_ret == TCL_OK) { 883 + pathinfo->typeinfo.file.size = attr_value_wide; 884 + } 783 885 } 784 - } 785 886 786 - break; 787 - case 'f': /* file */ 788 - pathinfo->type = APPFS_PATHTYPE_FILE; 789 - pathinfo->typeinfo.file.size = 0; 790 - pathinfo->typeinfo.file.executable = 0; 791 - 792 - Tcl_DictObjGet(interp, attrs_dict, attr_key_size, &attr_value); 793 - if (attr_value != NULL) { 794 - tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); 795 - if (tcl_ret == TCL_OK) { 796 - pathinfo->typeinfo.file.size = attr_value_wide; 887 + Tcl_DictObjGet(interp, attrs_dict, attr_key_perms, &attr_value); 888 + if (attr_value != NULL) { 889 + attr_value_str = Tcl_GetString(attr_value); 890 + if (attr_value_str[0] == 'x') { 891 + pathinfo->typeinfo.file.executable = 1; 892 + } 797 893 } 798 - } 894 + break; 895 + case 's': /* symlink */ 896 + pathinfo->type = APPFS_PATHTYPE_SYMLINK; 897 + pathinfo->typeinfo.symlink.size = 0; 898 + pathinfo->typeinfo.symlink.source[0] = '\0'; 799 899 800 - Tcl_DictObjGet(interp, attrs_dict, attr_key_perms, &attr_value); 801 - if (attr_value != NULL) { 802 - attr_value_str = Tcl_GetString(attr_value); 803 - if (attr_value_str[0] == 'x') { 804 - pathinfo->typeinfo.file.executable = 1; 805 - } 806 - } 807 - break; 808 - case 's': /* symlink */ 809 - pathinfo->type = APPFS_PATHTYPE_SYMLINK; 810 - pathinfo->typeinfo.symlink.size = 0; 811 - pathinfo->typeinfo.symlink.source[0] = '\0'; 900 + Tcl_DictObjGet(interp, attrs_dict, attr_key_source, &attr_value); 901 + if (attr_value != NULL) { 902 + attr_value_str = Tcl_GetStringFromObj(attr_value, &attr_value_int); 812 903 813 - Tcl_DictObjGet(interp, attrs_dict, attr_key_source, &attr_value); 814 - if (attr_value != NULL) { 815 - attr_value_str = Tcl_GetStringFromObj(attr_value, &attr_value_int); 904 + if ((attr_value_int + 1) <= sizeof(pathinfo->typeinfo.symlink.source)) { 905 + pathinfo->typeinfo.symlink.size = attr_value_int; 906 + pathinfo->typeinfo.symlink.source[attr_value_int] = '\0'; 816 907 817 - if ((attr_value_int + 1) <= sizeof(pathinfo->typeinfo.symlink.source)) { 818 - pathinfo->typeinfo.symlink.size = attr_value_int; 819 - pathinfo->typeinfo.symlink.source[attr_value_int] = '\0'; 820 - 821 - memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int); 908 + memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int); 909 + } 822 910 } 911 + break; 912 + case 'F': /* pipe/fifo */ 913 + pathinfo->type = APPFS_PATHTYPE_FIFO; 914 + break; 915 + case 'S': /* UNIX domain socket */ 916 + pathinfo->type = APPFS_PATHTYPE_SOCKET; 917 + break; 918 + default: 919 + retval = -EIO; 920 + } 921 + 922 + Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value); 923 + if (attr_value != NULL) { 924 + pathinfo->packaged = 1; 925 + } 926 + 927 + Tcl_DictObjGet(interp, attrs_dict, attr_key_time, &attr_value); 928 + if (attr_value != NULL) { 929 + tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); 930 + if (tcl_ret == TCL_OK) { 931 + pathinfo->time = attr_value_wide; 823 932 } 824 - break; 825 - case 'F': /* pipe/fifo */ 826 - pathinfo->type = APPFS_PATHTYPE_FIFO; 827 - break; 828 - case 'S': /* UNIX domain socket */ 829 - pathinfo->type = APPFS_PATHTYPE_SOCKET; 830 - break; 831 - default: 832 - Tcl_Release(interp); 833 - 834 - return(-EIO); 835 - } 836 - 837 - Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value); 838 - if (attr_value != NULL) { 839 - pathinfo->packaged = 1; 840 - } 841 - 842 - Tcl_DictObjGet(interp, attrs_dict, attr_key_time, &attr_value); 843 - if (attr_value != NULL) { 844 - tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); 845 - if (tcl_ret == TCL_OK) { 846 - pathinfo->time = attr_value_wide; 933 + } else { 934 + pathinfo->time = 0; 847 935 } 848 - } else { 849 - pathinfo->time = 0; 936 + 937 + Tcl_Release(interp); 938 + ) 939 + 940 + if (retval == 0) { 941 + appfs_get_path_info_cache_add(path, fsuid, pathinfo); 850 942 } 851 943 852 - Tcl_Release(interp); 853 - 854 - appfs_get_path_info_cache_add(path, fsuid, pathinfo); 855 - 856 - return(0); 944 + return(retval); 857 945 } 858 946 859 947 static char *appfs_prepare_to_create(const char *path) { 860 948 Tcl_Interp *interp; 861 949 const char *real_path; 862 950 int tcl_ret; 863 951 ................................................................................ 864 952 appfs_get_path_info_cache_flush(appfs_get_fsuid(), -1); 865 953 866 954 interp = appfs_TclInterp(); 867 955 if (interp == NULL) { 868 956 return(NULL); 869 957 } 870 958 871 - Tcl_Preserve(interp); 959 + appfs_call_libtcl(Tcl_Preserve(interp);) 872 960 873 - tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::prepare_to_create", path); 961 + appfs_call_libtcl( 962 + tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::prepare_to_create", path); 963 + ) 874 964 if (tcl_ret != TCL_OK) { 875 965 APPFS_DEBUG("::appfs::prepare_to_create(%s) failed.", path); 876 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 966 + appfs_call_libtcl( 967 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 968 + ) 877 969 878 - Tcl_Release(interp); 970 + appfs_call_libtcl(Tcl_Release(interp);) 879 971 880 972 return(NULL); 881 973 } 882 974 883 - real_path = Tcl_GetStringResult(interp); 975 + appfs_call_libtcl( 976 + real_path = Tcl_GetStringResult(interp); 977 + ) 884 978 885 - Tcl_Release(interp); 979 + appfs_call_libtcl(Tcl_Release(interp);) 886 980 887 981 if (real_path == NULL) { 888 982 return(NULL); 889 983 } 890 984 891 985 return(strdup(real_path)); 892 986 } ................................................................................ 897 991 int tcl_ret; 898 992 899 993 interp = appfs_TclInterp(); 900 994 if (interp == NULL) { 901 995 return(NULL); 902 996 } 903 997 904 - Tcl_Preserve(interp); 998 + appfs_call_libtcl(Tcl_Preserve(interp);) 905 999 906 - tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::localpath", path); 1000 + appfs_call_libtcl( 1001 + tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::localpath", path); 1002 + ) 907 1003 if (tcl_ret != TCL_OK) { 908 1004 APPFS_DEBUG("::appfs::localpath(%s) failed.", path); 909 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1005 + appfs_call_libtcl( 1006 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1007 + ) 910 1008 911 1009 return(NULL); 912 1010 } 913 1011 914 - real_path = Tcl_GetStringResult(interp); 1012 + appfs_call_libtcl( 1013 + real_path = Tcl_GetStringResult(interp); 1014 + ) 915 1015 916 - Tcl_Release(interp); 1016 + appfs_call_libtcl(Tcl_Release(interp);) 917 1017 918 1018 if (real_path == NULL) { 919 1019 return(NULL); 920 1020 } 921 1021 922 1022 return(strdup(real_path)); 923 1023 } ................................................................................ 1064 1164 APPFS_DEBUG("Enter (path = %s, ...)", path); 1065 1165 1066 1166 interp = appfs_TclInterp(); 1067 1167 if (interp == NULL) { 1068 1168 return(0); 1069 1169 } 1070 1170 1071 - Tcl_Preserve(interp); 1171 + appfs_call_libtcl(Tcl_Preserve(interp);) 1072 1172 1073 1173 filler(buf, ".", NULL, 0); 1074 1174 filler(buf, "..", NULL, 0); 1075 1175 1076 1176 tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path); 1077 1177 if (tcl_ret != TCL_OK) { 1078 1178 APPFS_DEBUG("::appfs::getchildren(%s) failed.", path); 1079 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1179 + appfs_call_libtcl( 1180 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1181 + ) 1080 1182 1081 - Tcl_Release(interp); 1183 + appfs_call_libtcl(Tcl_Release(interp);) 1082 1184 1083 1185 return(0); 1084 1186 } 1085 1187 1086 - tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children); 1188 + appfs_call_libtcl( 1189 + tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children); 1190 + ) 1087 1191 if (tcl_ret != TCL_OK) { 1088 1192 APPFS_DEBUG("Parsing list of children on path %s failed.", path); 1089 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1193 + appfs_call_libtcl( 1194 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1195 + ) 1090 1196 1091 - Tcl_Release(interp); 1197 + appfs_call_libtcl(Tcl_Release(interp);) 1092 1198 1093 1199 return(0); 1094 1200 } 1095 1201 1096 1202 for (idx = 0; idx < children_count; idx++) { 1097 - filler(buf, Tcl_GetString(children[idx]), NULL, 0); 1203 + appfs_call_libtcl( 1204 + filler(buf, Tcl_GetString(children[idx]), NULL, 0); 1205 + ) 1098 1206 } 1099 1207 1100 - Tcl_Release(interp); 1208 + appfs_call_libtcl(Tcl_Release(interp);) 1101 1209 1102 1210 return(0); 1103 1211 } 1104 1212 1105 1213 static int appfs_fuse_open(const char *path, struct fuse_file_info *fi) { 1106 1214 Tcl_Interp *interp; 1107 1215 struct appfs_pathinfo pathinfo; ................................................................................ 1144 1252 } 1145 1253 1146 1254 interp = appfs_TclInterp(); 1147 1255 if (interp == NULL) { 1148 1256 return(-EIO); 1149 1257 } 1150 1258 1151 - Tcl_Preserve(interp); 1259 + appfs_call_libtcl(Tcl_Preserve(interp);) 1152 1260 1153 1261 tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode); 1154 1262 if (tcl_ret != TCL_OK) { 1155 1263 APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, mode); 1156 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1264 + appfs_call_libtcl( 1265 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1266 + ) 1157 1267 1158 - Tcl_Release(interp); 1268 + appfs_call_libtcl(Tcl_Release(interp);) 1159 1269 1160 1270 return(-EIO); 1161 1271 } 1162 1272 1163 - real_path = Tcl_GetStringResult(interp); 1273 + appfs_call_libtcl( 1274 + real_path = Tcl_GetStringResult(interp); 1275 + ) 1164 1276 1165 - Tcl_Release(interp); 1277 + appfs_call_libtcl(Tcl_Release(interp);) 1166 1278 1167 1279 if (real_path == NULL) { 1168 1280 return(-EIO); 1169 1281 } 1170 1282 1171 1283 APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode); 1172 1284 ................................................................................ 1338 1450 if (interp == NULL) { 1339 1451 return(-EIO); 1340 1452 } 1341 1453 1342 1454 tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::unlinkpath", path); 1343 1455 if (tcl_ret != TCL_OK) { 1344 1456 APPFS_DEBUG("::appfs::unlinkpath(%s) failed.", path); 1345 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1457 + appfs_call_libtcl( 1458 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1459 + ) 1346 1460 1347 - Tcl_Release(interp); 1461 + appfs_call_libtcl(Tcl_Release(interp);) 1348 1462 1349 1463 return(-EIO); 1350 1464 } 1351 1465 1352 - Tcl_Release(interp); 1466 + appfs_call_libtcl(Tcl_Release(interp);) 1353 1467 1354 1468 return(0); 1355 1469 } 1356 1470 1357 1471 static int appfs_fuse_mkdir(const char *path, mode_t mode) { 1358 1472 char *real_path; 1359 1473 int mkdir_ret; ................................................................................ 1392 1506 appfs_get_path_info_cache_rm(path, appfs_get_fsuid()); 1393 1507 1394 1508 interp = appfs_TclInterp(); 1395 1509 if (interp == NULL) { 1396 1510 return(-EIO); 1397 1511 } 1398 1512 1399 - Tcl_Preserve(interp); 1513 + appfs_call_libtcl(Tcl_Preserve(interp);) 1400 1514 1401 1515 tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, "write"); 1402 1516 if (tcl_ret != TCL_OK) { 1403 1517 APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, "write"); 1404 - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1518 + appfs_call_libtcl( 1519 + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 1520 + ) 1405 1521 1406 - Tcl_Release(interp); 1522 + appfs_call_libtcl(Tcl_Release(interp);) 1407 1523 1408 1524 return(-EIO); 1409 1525 } 1410 1526 1411 - real_path = Tcl_GetStringResult(interp); 1527 + appfs_call_libtcl( 1528 + real_path = Tcl_GetStringResult(interp); 1529 + ) 1412 1530 1413 - Tcl_Release(interp); 1531 + appfs_call_libtcl(Tcl_Release(interp);) 1414 1532 1415 1533 if (real_path == NULL) { 1416 1534 return(-EIO); 1417 1535 } 1418 1536 1419 1537 appfs_simulate_user_fs_enter(); 1420 1538 ................................................................................ 1508 1626 return(TCL_ERROR); 1509 1627 } 1510 1628 1511 1629 fsuid = appfs_get_fsuid(); 1512 1630 1513 1631 if (fsuid == last_fsuid && last_homedir_obj != NULL) { 1514 1632 homedir_obj = last_homedir_obj; 1633 + 1634 + Tcl_IncrRefCount(homedir_obj); 1515 1635 } else { 1516 1636 homedir = appfs_get_homedir(appfs_get_fsuid()); 1517 1637 1518 1638 if (homedir == NULL) { 1519 1639 return(TCL_ERROR); 1520 1640 } 1521 1641 1522 1642 homedir_obj = Tcl_NewStringObj(homedir, -1); 1523 1643 1524 1644 free(homedir); 1645 + 1646 + Tcl_IncrRefCount(homedir_obj); 1525 1647 1526 1648 if (last_homedir_obj != NULL) { 1527 1649 Tcl_DecrRefCount(last_homedir_obj); 1528 1650 } 1529 1651 1530 1652 last_homedir_obj = homedir_obj; 1531 1653 last_fsuid = fsuid; 1532 1654 1533 - Tcl_IncrRefCount(last_homedir_obj); 1655 + Tcl_IncrRefCount(homedir_obj); 1534 1656 } 1535 1657 1536 1658 Tcl_SetObjResult(interp, homedir_obj); 1659 + 1660 + Tcl_DecrRefCount(homedir_obj); 1537 1661 1538 1662 return(TCL_OK); 1539 1663 } 1540 1664 1541 1665 static int tcl_appfs_simulate_user_fs_enter(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { 1542 1666 appfs_simulate_user_fs_enter(); 1543 1667 ................................................................................ 1655 1779 return; 1656 1780 } 1657 1781 1658 1782 interp = _interp; 1659 1783 1660 1784 APPFS_DEBUG("Terminating interpreter due to thread termination"); 1661 1785 1662 - Tcl_DeleteInterp(interp); 1786 + appfs_call_libtcl( 1787 + Tcl_DeleteInterp(interp); 1788 + ) 1663 1789 1664 1790 return; 1665 1791 } 1666 1792 1667 1793 /* 1668 1794 * FUSE operations structure 1669 1795 */ ................................................................................ 1791 1917 } 1792 1918 1793 1919 fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n"); 1794 1920 fprintf(stderr, "%s\n", test_interp_error); 1795 1921 1796 1922 return(1); 1797 1923 } 1924 + 1798 1925 Tcl_DeleteInterp(test_interp); 1926 + 1799 1927 Tcl_FinalizeNotifier(NULL); 1800 1928 1801 1929 /* 1802 1930 * Register a signal handler for hot-restart requests 1803 1931 */ 1804 1932 signal_ret = signal(SIGHUP, appfs_signal_handler); 1805 1933 if (signal_ret == SIG_ERR) {