Hex Artifact Content

Artifact 405b834b47e9c9fd34d961593923e13e7f738e26:


0000: 23 64 65 66 69 6e 65 20 46 55 53 45 5f 55 53 45  #define FUSE_USE
0010: 5f 56 45 52 53 49 4f 4e 20 32 36 0a 0a 23 69 6e  _VERSION 26..#in
0020: 63 6c 75 64 65 20 3c 73 79 73 2f 66 73 75 69 64  clude <sys/fsuid
0030: 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c 73 79  .h>.#include <sy
0040: 73 2f 74 79 70 65 73 2e 68 3e 0a 23 69 6e 63 6c  s/types.h>.#incl
0050: 75 64 65 20 3c 70 74 68 72 65 61 64 2e 68 3e 0a  ude <pthread.h>.
0060: 23 69 6e 63 6c 75 64 65 20 3c 73 74 72 69 6e 67  #include <string
0070: 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c 73 74  .h>.#include <st
0080: 64 61 72 67 2e 68 3e 0a 23 69 6e 63 6c 75 64 65  darg.h>.#include
0090: 20 3c 73 74 64 6c 69 62 2e 68 3e 0a 23 69 6e 63   <stdlib.h>.#inc
00a0: 6c 75 64 65 20 3c 75 6e 69 73 74 64 2e 68 3e 0a  lude <unistd.h>.
00b0: 23 69 6e 63 6c 75 64 65 20 3c 65 72 72 6e 6f 2e  #include <errno.
00c0: 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c 66 63 6e  h>.#include <fcn
00d0: 74 6c 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c  tl.h>.#include <
00e0: 73 74 64 69 6f 2e 68 3e 0a 23 69 6e 63 6c 75 64  stdio.h>.#includ
00f0: 65 20 3c 66 75 73 65 2e 68 3e 0a 23 69 6e 63 6c  e <fuse.h>.#incl
0100: 75 64 65 20 3c 70 77 64 2e 68 3e 0a 23 69 6e 63  ude <pwd.h>.#inc
0110: 6c 75 64 65 20 3c 74 63 6c 2e 68 3e 0a 0a 2f 2a  lude <tcl.h>../*
0120: 0a 20 2a 20 44 65 66 61 75 6c 74 20 63 61 63 68  . * Default cach
0130: 65 20 64 69 72 65 63 74 6f 72 79 0a 20 2a 2f 0a  e directory. */.
0140: 23 69 66 6e 64 65 66 20 41 50 50 46 53 5f 43 41  #ifndef APPFS_CA
0150: 43 48 45 44 49 52 0a 23 64 65 66 69 6e 65 20 41  CHEDIR.#define A
0160: 50 50 46 53 5f 43 41 43 48 45 44 49 52 20 22 2f  PPFS_CACHEDIR "/
0170: 76 61 72 2f 63 61 63 68 65 2f 61 70 70 66 73 22  var/cache/appfs"
0180: 0a 23 65 6e 64 69 66 0a 0a 2f 2a 20 44 65 62 75  .#endif../* Debu
0190: 67 67 69 6e 67 20 6d 61 63 72 6f 73 20 2a 2f 0a  gging macros */.
01a0: 23 69 66 64 65 66 20 44 45 42 55 47 0a 23 64 65  #ifdef DEBUG.#de
01b0: 66 69 6e 65 20 41 50 50 46 53 5f 44 45 42 55 47  fine APPFS_DEBUG
01c0: 28 78 2e 2e 2e 29 20 7b 20 66 70 72 69 6e 74 66  (x...) { fprintf
01d0: 28 73 74 64 65 72 72 2c 20 22 5b 64 65 62 75 67  (stderr, "[debug
01e0: 5d 20 25 73 3a 25 69 3a 25 73 3a 20 22 2c 20 5f  ] %s:%i:%s: ", _
01f0: 5f 46 49 4c 45 5f 5f 2c 20 5f 5f 4c 49 4e 45 5f  _FILE__, __LINE_
0200: 5f 2c 20 5f 5f 66 75 6e 63 5f 5f 29 3b 20 66 70  _, __func__); fp
0210: 72 69 6e 74 66 28 73 74 64 65 72 72 2c 20 78 29  rintf(stderr, x)
0220: 3b 20 66 70 72 69 6e 74 66 28 73 74 64 65 72 72  ; fprintf(stderr
0230: 2c 20 22 5c 6e 22 29 3b 20 7d 0a 23 65 6c 73 65  , "\n"); }.#else
0240: 0a 23 64 65 66 69 6e 65 20 41 50 50 46 53 5f 44  .#define APPFS_D
0250: 45 42 55 47 28 78 2e 2e 2e 29 20 2f 2a 2a 2f 0a  EBUG(x...) /**/.
0260: 23 65 6e 64 69 66 0a 0a 2f 2a 0a 20 2a 20 53 48  #endif../*. * SH
0270: 41 31 20 54 63 6c 20 50 61 63 6b 61 67 65 20 69  A1 Tcl Package i
0280: 6e 69 74 69 61 6c 69 7a 65 72 2c 20 66 72 6f 6d  nitializer, from
0290: 20 73 68 61 31 2e 6f 0a 20 2a 2f 0a 69 6e 74 20   sha1.o. */.int 
02a0: 53 68 61 31 5f 49 6e 69 74 28 54 63 6c 5f 49 6e  Sha1_Init(Tcl_In
02b0: 74 65 72 70 20 2a 69 6e 74 65 72 70 29 3b 0a 0a  terp *interp);..
02c0: 2f 2a 0a 20 2a 20 54 68 72 65 61 64 20 53 70 65  /*. * Thread Spe
02d0: 63 69 66 69 63 20 44 61 74 61 20 28 54 53 44 29  cific Data (TSD)
02e0: 20 66 6f 72 20 54 63 6c 20 49 6e 74 65 72 70 72   for Tcl Interpr
02f0: 65 74 65 72 20 66 6f 72 20 74 68 65 20 63 75 72  eter for the cur
0300: 72 65 6e 74 20 74 68 72 65 61 64 0a 20 2a 2f 0a  rent thread. */.
0310: 73 74 61 74 69 63 20 70 74 68 72 65 61 64 5f 6b  static pthread_k
0320: 65 79 5f 74 20 69 6e 74 65 72 70 4b 65 79 3b 0a  ey_t interpKey;.
0330: 0a 2f 2a 0a 20 2a 20 47 6c 6f 62 61 6c 20 76 61  ./*. * Global va
0340: 72 69 61 62 6c 65 73 2c 20 6e 65 65 64 65 64 20  riables, needed 
0350: 66 6f 72 20 61 6c 6c 20 74 68 72 65 61 64 73 20  for all threads 
0360: 62 75 74 20 6f 6e 6c 79 20 69 6e 69 74 69 61 6c  but only initial
0370: 69 7a 65 64 20 62 65 66 6f 72 65 20 61 6e 79 0a  ized before any.
0380: 20 2a 20 46 55 53 45 20 74 68 72 65 61 64 73 20   * FUSE threads 
0390: 61 72 65 20 63 72 65 61 74 65 64 0a 20 2a 2f 0a  are created. */.
03a0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 61 70 70 66  const char *appf
03b0: 73 5f 63 61 63 68 65 64 69 72 3b 0a 74 69 6d 65  s_cachedir;.time
03c0: 5f 74 20 61 70 70 66 73 5f 62 6f 6f 74 74 69 6d  _t appfs_boottim
03d0: 65 3b 0a 69 6e 74 20 61 70 70 66 73 5f 66 75 73  e;.int appfs_fus
03e0: 65 5f 73 74 61 72 74 65 64 20 3d 20 30 3b 0a 0a  e_started = 0;..
03f0: 2f 2a 0a 20 2a 20 41 70 70 46 53 20 50 61 74 68  /*. * AppFS Path
0400: 20 54 79 70 65 3a 20 20 44 65 73 63 72 69 62 65   Type:  Describe
0410: 73 20 74 68 65 20 74 79 70 65 20 6f 66 20 70 61  s the type of pa
0420: 74 68 20 61 20 67 69 76 65 6e 20 66 69 6c 65 20  th a given file 
0430: 69 73 0a 20 2a 2f 0a 74 79 70 65 64 65 66 20 65  is. */.typedef e
0440: 6e 75 6d 20 7b 0a 09 41 50 50 46 53 5f 50 41 54  num {..APPFS_PAT
0450: 48 54 59 50 45 5f 49 4e 56 41 4c 49 44 2c 0a 09  HTYPE_INVALID,..
0460: 41 50 50 46 53 5f 50 41 54 48 54 59 50 45 5f 46  APPFS_PATHTYPE_F
0470: 49 4c 45 2c 0a 09 41 50 50 46 53 5f 50 41 54 48  ILE,..APPFS_PATH
0480: 54 59 50 45 5f 44 49 52 45 43 54 4f 52 59 2c 0a  TYPE_DIRECTORY,.
0490: 09 41 50 50 46 53 5f 50 41 54 48 54 59 50 45 5f  .APPFS_PATHTYPE_
04a0: 53 59 4d 4c 49 4e 4b 2c 0a 09 41 50 50 46 53 5f  SYMLINK,..APPFS_
04b0: 50 41 54 48 54 59 50 45 5f 53 4f 43 4b 45 54 2c  PATHTYPE_SOCKET,
04c0: 0a 09 41 50 50 46 53 5f 50 41 54 48 54 59 50 45  ..APPFS_PATHTYPE
04d0: 5f 46 49 46 4f 2c 0a 7d 20 61 70 70 66 73 5f 70  _FIFO,.} appfs_p
04e0: 61 74 68 74 79 70 65 5f 74 3b 0a 0a 2f 2a 0a 20  athtype_t;../*. 
04f0: 2a 20 41 70 70 46 53 20 50 61 74 68 20 49 6e 66  * AppFS Path Inf
0500: 6f 72 6d 61 74 69 6f 6e 3a 0a 20 2a 20 20 20 20  ormation:. *    
0510: 20 20 20 20 20 43 6f 6d 70 6c 65 74 65 6c 79 20       Completely 
0520: 64 65 73 63 72 69 62 65 73 20 61 20 73 70 65 63  describes a spec
0530: 69 66 69 63 20 70 61 74 68 2c 20 68 6f 77 20 69  ific path, how i
0540: 74 20 73 68 6f 75 6c 64 20 62 65 20 72 65 74 75  t should be retu
0550: 72 6e 65 64 20 74 6f 0a 20 2a 20 20 20 20 20 20  rned to. *      
0560: 20 20 20 74 6f 20 74 68 65 20 6b 65 72 6e 65 6c     to the kernel
0570: 0a 20 2a 2f 0a 73 74 72 75 63 74 20 61 70 70 66  . */.struct appf
0580: 73 5f 70 61 74 68 69 6e 66 6f 20 7b 0a 09 61 70  s_pathinfo {..ap
0590: 70 66 73 5f 70 61 74 68 74 79 70 65 5f 74 20 74  pfs_pathtype_t t
05a0: 79 70 65 3b 0a 09 74 69 6d 65 5f 74 20 74 69 6d  ype;..time_t tim
05b0: 65 3b 0a 09 63 68 61 72 20 68 6f 73 74 6e 61 6d  e;..char hostnam
05c0: 65 5b 32 35 36 5d 3b 0a 09 69 6e 74 20 70 61 63  e[256];..int pac
05d0: 6b 61 67 65 64 3b 0a 09 75 6e 73 69 67 6e 65 64  kaged;..unsigned
05e0: 20 6c 6f 6e 67 20 6c 6f 6e 67 20 69 6e 6f 64 65   long long inode
05f0: 3b 0a 09 75 6e 69 6f 6e 20 7b 0a 09 09 73 74 72  ;..union {...str
0600: 75 63 74 20 7b 0a 09 09 09 69 6e 74 20 63 68 69  uct {....int chi
0610: 6c 64 63 6f 75 6e 74 3b 0a 09 09 7d 20 64 69 72  ldcount;...} dir
0620: 3b 0a 09 09 73 74 72 75 63 74 20 7b 0a 09 09 09  ;...struct {....
0630: 69 6e 74 20 65 78 65 63 75 74 61 62 6c 65 3b 0a  int executable;.
0640: 09 09 09 6f 66 66 5f 74 20 73 69 7a 65 3b 0a 09  ...off_t size;..
0650: 09 7d 20 66 69 6c 65 3b 0a 09 09 73 74 72 75 63  .} file;...struc
0660: 74 20 7b 0a 09 09 09 6f 66 66 5f 74 20 73 69 7a  t {....off_t siz
0670: 65 3b 0a 09 09 09 63 68 61 72 20 73 6f 75 72 63  e;....char sourc
0680: 65 5b 32 35 36 5d 3b 0a 09 09 7d 20 73 79 6d 6c  e[256];...} syml
0690: 69 6e 6b 3b 0a 09 7d 20 74 79 70 65 69 6e 66 6f  ink;..} typeinfo
06a0: 3b 0a 7d 3b 0a 0a 2f 2a 0a 20 2a 20 43 72 65 61  ;.};../*. * Crea
06b0: 74 65 20 61 20 6e 65 77 20 54 63 6c 20 69 6e 74  te a new Tcl int
06c0: 65 72 70 72 65 74 65 72 20 61 6e 64 20 63 6f 6d  erpreter and com
06d0: 70 6c 65 74 65 6c 79 20 69 6e 69 74 69 61 6c 69  pletely initiali
06e0: 7a 65 20 69 74 0a 20 2a 2f 0a 73 74 61 74 69 63  ze it. */.static
06f0: 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a 61 70 70   Tcl_Interp *app
0700: 66 73 5f 63 72 65 61 74 65 5f 54 63 6c 49 6e 74  fs_create_TclInt
0710: 65 72 70 28 63 68 61 72 20 2a 2a 65 72 72 6f 72  erp(char **error
0720: 5f 73 74 72 69 6e 67 29 20 7b 0a 09 54 63 6c 5f  _string) {..Tcl_
0730: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 3b 0a  Interp *interp;.
0740: 09 69 6e 74 20 74 63 6c 5f 72 65 74 3b 0a 0a 09  .int tcl_ret;...
0750: 41 50 50 46 53 5f 44 45 42 55 47 28 22 43 72 65  APPFS_DEBUG("Cre
0760: 61 74 69 6e 67 20 6e 65 77 20 54 63 6c 20 69 6e  ating new Tcl in
0770: 74 65 72 70 72 65 74 65 72 20 66 6f 72 20 54 49  terpreter for TI
0780: 44 20 3d 20 30 78 25 6c 6c 78 22 2c 20 28 75 6e  D = 0x%llx", (un
0790: 73 69 67 6e 65 64 20 6c 6f 6e 67 20 6c 6f 6e 67  signed long long
07a0: 29 20 70 74 68 72 65 61 64 5f 73 65 6c 66 28 29  ) pthread_self()
07b0: 29 3b 0a 0a 09 69 6e 74 65 72 70 20 3d 20 54 63  );...interp = Tc
07c0: 6c 5f 43 72 65 61 74 65 49 6e 74 65 72 70 28 29  l_CreateInterp()
07d0: 3b 0a 09 69 66 20 28 69 6e 74 65 72 70 20 3d 3d  ;..if (interp ==
07e0: 20 4e 55 4c 4c 29 20 7b 0a 09 09 66 70 72 69 6e   NULL) {...fprin
07f0: 74 66 28 73 74 64 65 72 72 2c 20 22 55 6e 61 62  tf(stderr, "Unab
0800: 6c 65 20 74 6f 20 63 72 65 61 74 65 20 54 63 6c  le to create Tcl
0810: 20 49 6e 74 65 72 70 72 65 74 65 72 2e 20 20 41   Interpreter.  A
0820: 62 6f 72 74 69 6e 67 2e 5c 6e 22 29 3b 0a 0a 09  borting.\n");...
0830: 09 69 66 20 28 65 72 72 6f 72 5f 73 74 72 69 6e  .if (error_strin
0840: 67 29 20 7b 0a 09 09 09 2a 65 72 72 6f 72 5f 73  g) {....*error_s
0850: 74 72 69 6e 67 20 3d 20 73 74 72 64 75 70 28 22  tring = strdup("
0860: 55 6e 61 62 6c 65 20 74 6f 20 63 72 65 61 74 65  Unable to create
0870: 20 54 63 6c 20 69 6e 74 65 72 70 72 65 74 65 72   Tcl interpreter
0880: 2e 22 29 3b 0a 09 09 7d 0a 0a 09 09 72 65 74 75  .");...}....retu
0890: 72 6e 28 4e 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 74  rn(NULL);..}...t
08a0: 63 6c 5f 72 65 74 20 3d 20 54 63 6c 5f 49 6e 69  cl_ret = Tcl_Ini
08b0: 74 28 69 6e 74 65 72 70 29 3b 0a 09 69 66 20 28  t(interp);..if (
08c0: 74 63 6c 5f 72 65 74 20 21 3d 20 54 43 4c 5f 4f  tcl_ret != TCL_O
08d0: 4b 29 20 7b 0a 09 09 66 70 72 69 6e 74 66 28 73  K) {...fprintf(s
08e0: 74 64 65 72 72 2c 20 22 55 6e 61 62 6c 65 20 74  tderr, "Unable t
08f0: 6f 20 69 6e 69 74 69 61 6c 69 7a 65 20 54 63 6c  o initialize Tcl
0900: 2e 20 20 41 62 6f 72 74 69 6e 67 2e 5c 6e 22 29  .  Aborting.\n")
0910: 3b 0a 09 09 66 70 72 69 6e 74 66 28 73 74 64 65  ;...fprintf(stde
0920: 72 72 2c 20 22 54 63 6c 20 45 72 72 6f 72 20 69  rr, "Tcl Error i
0930: 73 3a 20 25 73 5c 6e 22 2c 20 54 63 6c 5f 47 65  s: %s\n", Tcl_Ge
0940: 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69 6e  tStringResult(in
0950: 74 65 72 70 29 29 3b 0a 0a 09 09 69 66 20 28 65  terp));....if (e
0960: 72 72 6f 72 5f 73 74 72 69 6e 67 29 20 7b 0a 09  rror_string) {..
0970: 09 09 2a 65 72 72 6f 72 5f 73 74 72 69 6e 67 20  ..*error_string 
0980: 3d 20 73 74 72 64 75 70 28 54 63 6c 5f 47 65 74  = strdup(Tcl_Get
0990: 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69 6e 74  StringResult(int
09a0: 65 72 70 29 29 3b 0a 09 09 7d 0a 0a 09 09 54 63  erp));...}....Tc
09b0: 6c 5f 44 65 6c 65 74 65 49 6e 74 65 72 70 28 69  l_DeleteInterp(i
09c0: 6e 74 65 72 70 29 3b 0a 0a 09 09 72 65 74 75 72  nterp);....retur
09d0: 6e 28 4e 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 74 63  n(NULL);..}...tc
09e0: 6c 5f 72 65 74 20 3d 20 54 63 6c 5f 45 76 61 6c  l_ret = Tcl_Eval
09f0: 28 69 6e 74 65 72 70 2c 20 22 70 61 63 6b 61 67  (interp, "packag
0a00: 65 20 69 66 6e 65 65 64 65 64 20 73 68 61 31 20  e ifneeded sha1 
0a10: 31 2e 30 20 5b 6c 69 73 74 20 6c 6f 61 64 20 7b  1.0 [list load {
0a20: 7d 20 73 68 61 31 5d 22 29 3b 0a 09 69 66 20 28  } sha1]");..if (
0a30: 74 63 6c 5f 72 65 74 20 21 3d 20 54 43 4c 5f 4f  tcl_ret != TCL_O
0a40: 4b 29 20 7b 0a 09 09 66 70 72 69 6e 74 66 28 73  K) {...fprintf(s
0a50: 74 64 65 72 72 2c 20 22 55 6e 61 62 6c 65 20 74  tderr, "Unable t
0a60: 6f 20 69 6e 69 74 69 61 6c 69 7a 65 20 54 63 6c  o initialize Tcl
0a70: 20 53 48 41 31 2e 20 20 41 62 6f 72 74 69 6e 67   SHA1.  Aborting
0a80: 2e 5c 6e 22 29 3b 0a 09 09 66 70 72 69 6e 74 66  .\n");...fprintf
0a90: 28 73 74 64 65 72 72 2c 20 22 54 63 6c 20 45 72  (stderr, "Tcl Er
0aa0: 72 6f 72 20 69 73 3a 20 25 73 5c 6e 22 2c 20 54  ror is: %s\n", T
0ab0: 63 6c 5f 47 65 74 53 74 72 69 6e 67 52 65 73 75  cl_GetStringResu
0ac0: 6c 74 28 69 6e 74 65 72 70 29 29 3b 0a 0a 09 09  lt(interp));....
0ad0: 69 66 20 28 65 72 72 6f 72 5f 73 74 72 69 6e 67  if (error_string
0ae0: 29 20 7b 0a 09 09 09 2a 65 72 72 6f 72 5f 73 74  ) {....*error_st
0af0: 72 69 6e 67 20 3d 20 73 74 72 64 75 70 28 54 63  ring = strdup(Tc
0b00: 6c 5f 47 65 74 53 74 72 69 6e 67 52 65 73 75 6c  l_GetStringResul
0b10: 74 28 69 6e 74 65 72 70 29 29 3b 0a 09 09 7d 0a  t(interp));...}.
0b20: 0a 09 09 54 63 6c 5f 44 65 6c 65 74 65 49 6e 74  ...Tcl_DeleteInt
0b30: 65 72 70 28 69 6e 74 65 72 70 29 3b 0a 0a 09 09  erp(interp);....
0b40: 72 65 74 75 72 6e 28 4e 55 4c 4c 29 3b 0a 09 7d  return(NULL);..}
0b50: 0a 0a 09 74 63 6c 5f 72 65 74 20 3d 20 54 63 6c  ...tcl_ret = Tcl
0b60: 5f 45 76 61 6c 28 69 6e 74 65 72 70 2c 20 22 70  _Eval(interp, "p
0b70: 61 63 6b 61 67 65 20 69 66 6e 65 65 64 65 64 20  ackage ifneeded 
0b80: 61 70 70 66 73 64 20 31 2e 30 20 5b 6c 69 73 74  appfsd 1.0 [list
0b90: 20 6c 6f 61 64 20 7b 7d 20 61 70 70 66 73 64 5d   load {} appfsd]
0ba0: 22 29 3b 0a 09 69 66 20 28 74 63 6c 5f 72 65 74  ");..if (tcl_ret
0bb0: 20 21 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09   != TCL_OK) {...
0bc0: 66 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c 20  fprintf(stderr, 
0bd0: 22 55 6e 61 62 6c 65 20 74 6f 20 69 6e 69 74 69  "Unable to initi
0be0: 61 6c 69 7a 65 20 54 63 6c 20 41 70 70 46 53 20  alize Tcl AppFS 
0bf0: 50 61 63 6b 61 67 65 2e 20 20 41 62 6f 72 74 69  Package.  Aborti
0c00: 6e 67 2e 5c 6e 22 29 3b 0a 09 09 66 70 72 69 6e  ng.\n");...fprin
0c10: 74 66 28 73 74 64 65 72 72 2c 20 22 54 63 6c 20  tf(stderr, "Tcl 
0c20: 45 72 72 6f 72 20 69 73 3a 20 25 73 5c 6e 22 2c  Error is: %s\n",
0c30: 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67 52 65   Tcl_GetStringRe
0c40: 73 75 6c 74 28 69 6e 74 65 72 70 29 29 3b 0a 0a  sult(interp));..
0c50: 09 09 69 66 20 28 65 72 72 6f 72 5f 73 74 72 69  ..if (error_stri
0c60: 6e 67 29 20 7b 0a 09 09 09 2a 65 72 72 6f 72 5f  ng) {....*error_
0c70: 73 74 72 69 6e 67 20 3d 20 73 74 72 64 75 70 28  string = strdup(
0c80: 54 63 6c 5f 47 65 74 53 74 72 69 6e 67 52 65 73  Tcl_GetStringRes
0c90: 75 6c 74 28 69 6e 74 65 72 70 29 29 3b 0a 09 09  ult(interp));...
0ca0: 7d 0a 0a 09 09 54 63 6c 5f 44 65 6c 65 74 65 49  }....Tcl_DeleteI
0cb0: 6e 74 65 72 70 28 69 6e 74 65 72 70 29 3b 0a 0a  nterp(interp);..
0cc0: 09 09 72 65 74 75 72 6e 28 4e 55 4c 4c 29 3b 0a  ..return(NULL);.
0cd0: 09 7d 0a 0a 09 2f 2a 0a 09 20 2a 20 4c 6f 61 64  .}.../*.. * Load
0ce0: 20 22 70 6b 69 2e 74 63 6c 22 20 69 6e 20 74 68   "pki.tcl" in th
0cf0: 65 20 73 61 6d 65 20 77 61 79 20 61 73 20 61 70  e same way as ap
0d00: 70 66 73 64 2e 74 63 6c 20 28 73 65 65 20 62 65  pfsd.tcl (see be
0d10: 6c 6f 77 29 0a 09 20 2a 2f 0a 09 74 63 6c 5f 72  low).. */..tcl_r
0d20: 65 74 20 3d 20 54 63 6c 5f 45 76 61 6c 28 69 6e  et = Tcl_Eval(in
0d30: 74 65 72 70 2c 20 22 22 0a 23 69 6e 63 6c 75 64  terp, "".#includ
0d40: 65 20 22 70 6b 69 2e 74 63 6c 2e 68 22 0a 09 22  e "pki.tcl.h".."
0d50: 22 29 3b 0a 09 69 66 20 28 74 63 6c 5f 72 65 74  ");..if (tcl_ret
0d60: 20 21 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09   != TCL_OK) {...
0d70: 66 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c 20  fprintf(stderr, 
0d80: 22 55 6e 61 62 6c 65 20 74 6f 20 69 6e 69 74 69  "Unable to initi
0d90: 61 6c 69 7a 65 20 54 63 6c 20 50 4b 49 2e 20 20  alize Tcl PKI.  
0da0: 41 62 6f 72 74 69 6e 67 2e 5c 6e 22 29 3b 0a 09  Aborting.\n");..
0db0: 09 66 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c  .fprintf(stderr,
0dc0: 20 22 54 63 6c 20 45 72 72 6f 72 20 69 73 3a 20   "Tcl Error is: 
0dd0: 25 73 5c 6e 22 2c 20 54 63 6c 5f 47 65 74 53 74  %s\n", Tcl_GetSt
0de0: 72 69 6e 67 52 65 73 75 6c 74 28 69 6e 74 65 72  ringResult(inter
0df0: 70 29 29 3b 0a 0a 09 09 69 66 20 28 65 72 72 6f  p));....if (erro
0e00: 72 5f 73 74 72 69 6e 67 29 20 7b 0a 09 09 09 2a  r_string) {....*
0e10: 65 72 72 6f 72 5f 73 74 72 69 6e 67 20 3d 20 73  error_string = s
0e20: 74 72 64 75 70 28 54 63 6c 5f 47 65 74 53 74 72  trdup(Tcl_GetStr
0e30: 69 6e 67 52 65 73 75 6c 74 28 69 6e 74 65 72 70  ingResult(interp
0e40: 29 29 3b 0a 09 09 7d 0a 0a 09 09 54 63 6c 5f 44  ));...}....Tcl_D
0e50: 65 6c 65 74 65 49 6e 74 65 72 70 28 69 6e 74 65  eleteInterp(inte
0e60: 72 70 29 3b 0a 0a 09 09 72 65 74 75 72 6e 28 4e  rp);....return(N
0e70: 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 2f 2a 0a 09 20  ULL);..}.../*.. 
0e80: 2a 20 4c 6f 61 64 20 74 68 65 20 22 61 70 70 66  * Load the "appf
0e90: 73 64 2e 74 63 6c 22 20 73 63 72 69 70 74 2c 20  sd.tcl" script, 
0ea0: 77 68 69 63 68 20 69 73 20 22 63 6f 6d 70 69 6c  which is "compil
0eb0: 65 64 22 20 69 6e 74 6f 20 61 20 43 20 68 65 61  ed" into a C hea
0ec0: 64 65 72 0a 09 20 2a 20 73 6f 20 74 68 61 74 20  der.. * so that 
0ed0: 69 74 20 64 6f 65 73 20 6e 6f 74 20 6e 65 65 64  it does not need
0ee0: 20 74 6f 20 65 78 69 73 74 20 6f 6e 20 74 68 65   to exist on the
0ef0: 20 66 69 6c 65 73 79 73 74 65 6d 20 61 6e 64 20   filesystem and 
0f00: 63 61 6e 20 62 65 0a 09 20 2a 20 64 69 72 65 63  can be.. * direc
0f10: 74 6c 79 20 65 76 61 6c 75 61 74 65 64 2e 0a 09  tly evaluated...
0f20: 20 2a 2f 0a 09 74 63 6c 5f 72 65 74 20 3d 20 54   */..tcl_ret = T
0f30: 63 6c 5f 45 76 61 6c 28 69 6e 74 65 72 70 2c 20  cl_Eval(interp, 
0f40: 22 22 0a 23 69 6e 63 6c 75 64 65 20 22 61 70 70  "".#include "app
0f50: 66 73 64 2e 74 63 6c 2e 68 22 0a 09 22 22 29 3b  fsd.tcl.h".."");
0f60: 0a 09 69 66 20 28 74 63 6c 5f 72 65 74 20 21 3d  ..if (tcl_ret !=
0f70: 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09 66 70 72   TCL_OK) {...fpr
0f80: 69 6e 74 66 28 73 74 64 65 72 72 2c 20 22 55 6e  intf(stderr, "Un
0f90: 61 62 6c 65 20 74 6f 20 69 6e 69 74 69 61 6c 69  able to initiali
0fa0: 7a 65 20 54 63 6c 20 41 70 70 46 53 20 73 63 72  ze Tcl AppFS scr
0fb0: 69 70 74 2e 20 20 41 62 6f 72 74 69 6e 67 2e 5c  ipt.  Aborting.\
0fc0: 6e 22 29 3b 0a 09 09 66 70 72 69 6e 74 66 28 73  n");...fprintf(s
0fd0: 74 64 65 72 72 2c 20 22 54 63 6c 20 45 72 72 6f  tderr, "Tcl Erro
0fe0: 72 20 69 73 3a 20 25 73 5c 6e 22 2c 20 54 63 6c  r is: %s\n", Tcl
0ff0: 5f 47 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74  _GetStringResult
1000: 28 69 6e 74 65 72 70 29 29 3b 0a 0a 09 09 69 66  (interp));....if
1010: 20 28 65 72 72 6f 72 5f 73 74 72 69 6e 67 29 20   (error_string) 
1020: 7b 0a 09 09 09 2a 65 72 72 6f 72 5f 73 74 72 69  {....*error_stri
1030: 6e 67 20 3d 20 73 74 72 64 75 70 28 54 63 6c 5f  ng = strdup(Tcl_
1040: 47 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28  GetStringResult(
1050: 69 6e 74 65 72 70 29 29 3b 0a 09 09 7d 0a 0a 09  interp));...}...
1060: 09 54 63 6c 5f 44 65 6c 65 74 65 49 6e 74 65 72  .Tcl_DeleteInter
1070: 70 28 69 6e 74 65 72 70 29 3b 0a 0a 09 09 72 65  p(interp);....re
1080: 74 75 72 6e 28 4e 55 4c 4c 29 3b 0a 09 7d 0a 0a  turn(NULL);..}..
1090: 09 2f 2a 0a 09 20 2a 20 53 65 74 20 67 6c 6f 62  ./*.. * Set glob
10a0: 61 6c 20 76 61 72 69 61 62 6c 65 73 20 66 72 6f  al variables fro
10b0: 6d 20 43 20 74 6f 20 54 63 6c 0a 09 20 2a 2f 0a  m C to Tcl.. */.
10c0: 09 69 66 20 28 54 63 6c 5f 53 65 74 56 61 72 28  .if (Tcl_SetVar(
10d0: 69 6e 74 65 72 70 2c 20 22 3a 3a 61 70 70 66 73  interp, "::appfs
10e0: 3a 3a 63 61 63 68 65 64 69 72 22 2c 20 61 70 70  ::cachedir", app
10f0: 66 73 5f 63 61 63 68 65 64 69 72 2c 20 54 43 4c  fs_cachedir, TCL
1100: 5f 47 4c 4f 42 41 4c 5f 4f 4e 4c 59 29 20 3d 3d  _GLOBAL_ONLY) ==
1110: 20 4e 55 4c 4c 29 20 7b 0a 09 09 66 70 72 69 6e   NULL) {...fprin
1120: 74 66 28 73 74 64 65 72 72 2c 20 22 55 6e 61 62  tf(stderr, "Unab
1130: 6c 65 20 74 6f 20 73 65 74 20 63 61 63 68 65 20  le to set cache 
1140: 64 69 72 65 63 74 6f 72 79 2e 20 20 54 68 69 73  directory.  This
1150: 20 73 68 6f 75 6c 64 20 6e 65 76 65 72 20 66 61   should never fa
1160: 69 6c 2e 5c 6e 22 29 3b 0a 0a 09 09 69 66 20 28  il.\n");....if (
1170: 65 72 72 6f 72 5f 73 74 72 69 6e 67 29 20 7b 0a  error_string) {.
1180: 09 09 09 2a 65 72 72 6f 72 5f 73 74 72 69 6e 67  ...*error_string
1190: 20 3d 20 73 74 72 64 75 70 28 54 63 6c 5f 47 65   = strdup(Tcl_Ge
11a0: 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69 6e  tStringResult(in
11b0: 74 65 72 70 29 29 3b 0a 09 09 7d 0a 0a 09 09 54  terp));...}....T
11c0: 63 6c 5f 44 65 6c 65 74 65 49 6e 74 65 72 70 28  cl_DeleteInterp(
11d0: 69 6e 74 65 72 70 29 3b 0a 0a 09 09 72 65 74 75  interp);....retu
11e0: 72 6e 28 4e 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 2f  rn(NULL);..}.../
11f0: 2a 0a 09 20 2a 20 49 6e 69 74 69 61 6c 69 7a 65  *.. * Initialize
1200: 20 74 68 65 20 22 61 70 70 66 73 64 2e 74 63 6c   the "appfsd.tcl
1210: 22 20 65 6e 76 69 72 6f 6e 6d 65 6e 74 2c 20 77  " environment, w
1220: 68 69 63 68 20 6d 75 73 74 20 62 65 20 64 6f 6e  hich must be don
1230: 65 20 61 66 74 65 72 0a 09 20 2a 20 67 6c 6f 62  e after.. * glob
1240: 61 6c 20 76 61 72 69 61 62 6c 65 73 20 61 72 65  al variables are
1250: 20 73 65 74 2e 0a 09 20 2a 2f 0a 09 74 63 6c 5f   set... */..tcl_
1260: 72 65 74 20 3d 20 54 63 6c 5f 45 76 61 6c 28 69  ret = Tcl_Eval(i
1270: 6e 74 65 72 70 2c 20 22 3a 3a 61 70 70 66 73 3a  nterp, "::appfs:
1280: 3a 69 6e 69 74 22 29 3b 0a 09 69 66 20 28 74 63  :init");..if (tc
1290: 6c 5f 72 65 74 20 21 3d 20 54 43 4c 5f 4f 4b 29  l_ret != TCL_OK)
12a0: 20 7b 0a 09 09 66 70 72 69 6e 74 66 28 73 74 64   {...fprintf(std
12b0: 65 72 72 2c 20 22 55 6e 61 62 6c 65 20 74 6f 20  err, "Unable to 
12c0: 69 6e 69 74 69 61 6c 69 7a 65 20 54 63 6c 20 41  initialize Tcl A
12d0: 70 70 46 53 20 73 63 72 69 70 74 20 28 3a 3a 61  ppFS script (::a
12e0: 70 70 66 73 3a 3a 69 6e 69 74 29 2e 20 20 41 62  ppfs::init).  Ab
12f0: 6f 72 74 69 6e 67 2e 5c 6e 22 29 3b 0a 09 09 66  orting.\n");...f
1300: 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c 20 22  printf(stderr, "
1310: 54 63 6c 20 45 72 72 6f 72 20 69 73 3a 20 25 73  Tcl Error is: %s
1320: 5c 6e 22 2c 20 54 63 6c 5f 47 65 74 53 74 72 69  \n", Tcl_GetStri
1330: 6e 67 52 65 73 75 6c 74 28 69 6e 74 65 72 70 29  ngResult(interp)
1340: 29 3b 0a 0a 09 09 69 66 20 28 65 72 72 6f 72 5f  );....if (error_
1350: 73 74 72 69 6e 67 29 20 7b 0a 09 09 09 2a 65 72  string) {....*er
1360: 72 6f 72 5f 73 74 72 69 6e 67 20 3d 20 73 74 72  ror_string = str
1370: 64 75 70 28 54 63 6c 5f 47 65 74 53 74 72 69 6e  dup(Tcl_GetStrin
1380: 67 52 65 73 75 6c 74 28 69 6e 74 65 72 70 29 29  gResult(interp))
1390: 3b 0a 09 09 7d 0a 0a 09 09 54 63 6c 5f 44 65 6c  ;...}....Tcl_Del
13a0: 65 74 65 49 6e 74 65 72 70 28 69 6e 74 65 72 70  eteInterp(interp
13b0: 29 3b 0a 0a 09 09 72 65 74 75 72 6e 28 4e 55 4c  );....return(NUL
13c0: 4c 29 3b 0a 09 7d 0a 0a 09 2f 2a 0a 09 20 2a 20  L);..}.../*.. * 
13d0: 48 69 64 65 20 73 6f 6d 65 20 54 63 6c 20 63 6f  Hide some Tcl co
13e0: 6d 6d 61 6e 64 73 20 74 68 61 74 20 77 65 20 64  mmands that we d
13f0: 6f 20 6e 6f 74 20 63 61 72 65 20 74 6f 20 75 73  o not care to us
1400: 65 20 61 6e 64 20 77 68 69 63 68 20 6d 61 79 0a  e and which may.
1410: 09 20 2a 20 73 6c 6f 77 20 64 6f 77 6e 20 72 75  . * slow down ru
1420: 6e 2d 74 69 6d 65 20 6f 70 65 72 61 74 69 6f 6e  n-time operation
1430: 73 2e 0a 09 20 2a 2f 0a 09 54 63 6c 5f 48 69 64  s... */..Tcl_Hid
1440: 65 43 6f 6d 6d 61 6e 64 28 69 6e 74 65 72 70 2c  eCommand(interp,
1450: 20 22 61 75 74 6f 5f 6c 6f 61 64 5f 69 6e 64 65   "auto_load_inde
1460: 78 22 2c 20 22 61 75 74 6f 5f 6c 6f 61 64 5f 69  x", "auto_load_i
1470: 6e 64 65 78 22 29 3b 0a 09 54 63 6c 5f 48 69 64  ndex");..Tcl_Hid
1480: 65 43 6f 6d 6d 61 6e 64 28 69 6e 74 65 72 70 2c  eCommand(interp,
1490: 20 22 75 6e 6b 6e 6f 77 6e 22 2c 20 22 75 6e 6b   "unknown", "unk
14a0: 6e 6f 77 6e 22 29 3b 0a 0a 09 2f 2a 0a 09 20 2a  nown");.../*.. *
14b0: 20 52 65 74 75 72 6e 20 74 68 65 20 63 6f 6d 70   Return the comp
14c0: 6c 65 74 65 6c 79 20 69 6e 69 74 69 61 6c 69 7a  letely initializ
14d0: 65 64 20 69 6e 74 65 72 70 72 65 74 65 72 0a 09  ed interpreter..
14e0: 20 2a 2f 0a 09 72 65 74 75 72 6e 28 69 6e 74 65   */..return(inte
14f0: 72 70 29 3b 0a 7d 0a 0a 2f 2a 0a 20 2a 20 52 65  rp);.}../*. * Re
1500: 74 75 72 6e 20 74 68 65 20 74 68 72 65 61 64 2d  turn the thread-
1510: 73 70 65 63 69 66 69 63 20 54 63 6c 20 69 6e 74  specific Tcl int
1520: 65 72 70 72 65 74 65 72 2c 20 63 72 65 61 74 69  erpreter, creati
1530: 6e 67 20 69 74 20 69 66 20 6e 65 65 64 65 64 0a  ng it if needed.
1540: 20 2a 2f 0a 73 74 61 74 69 63 20 54 63 6c 5f 49   */.static Tcl_I
1550: 6e 74 65 72 70 20 2a 61 70 70 66 73 5f 54 63 6c  nterp *appfs_Tcl
1560: 49 6e 74 65 72 70 28 76 6f 69 64 29 20 7b 0a 09  Interp(void) {..
1570: 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65  Tcl_Interp *inte
1580: 72 70 3b 0a 09 69 6e 74 20 70 74 68 72 65 61 64  rp;..int pthread
1590: 5f 72 65 74 3b 0a 0a 09 69 6e 74 65 72 70 20 3d  _ret;...interp =
15a0: 20 70 74 68 72 65 61 64 5f 67 65 74 73 70 65 63   pthread_getspec
15b0: 69 66 69 63 28 69 6e 74 65 72 70 4b 65 79 29 3b  ific(interpKey);
15c0: 0a 09 69 66 20 28 69 6e 74 65 72 70 20 3d 3d 20  ..if (interp == 
15d0: 4e 55 4c 4c 29 20 7b 0a 09 09 69 6e 74 65 72 70  NULL) {...interp
15e0: 20 3d 20 61 70 70 66 73 5f 63 72 65 61 74 65 5f   = appfs_create_
15f0: 54 63 6c 49 6e 74 65 72 70 28 4e 55 4c 4c 29 3b  TclInterp(NULL);
1600: 0a 0a 09 09 69 66 20 28 69 6e 74 65 72 70 20 3d  ....if (interp =
1610: 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 09 72 65 74  = NULL) {....ret
1620: 75 72 6e 28 4e 55 4c 4c 29 3b 0a 09 09 7d 0a 0a  urn(NULL);...}..
1630: 09 09 70 74 68 72 65 61 64 5f 72 65 74 20 3d 20  ..pthread_ret = 
1640: 70 74 68 72 65 61 64 5f 73 65 74 73 70 65 63 69  pthread_setspeci
1650: 66 69 63 28 69 6e 74 65 72 70 4b 65 79 2c 20 69  fic(interpKey, i
1660: 6e 74 65 72 70 29 3b 0a 09 09 69 66 20 28 70 74  nterp);...if (pt
1670: 68 72 65 61 64 5f 72 65 74 20 21 3d 20 30 29 20  hread_ret != 0) 
1680: 7b 0a 09 09 09 54 63 6c 5f 44 65 6c 65 74 65 49  {....Tcl_DeleteI
1690: 6e 74 65 72 70 28 69 6e 74 65 72 70 29 3b 0a 0a  nterp(interp);..
16a0: 09 09 09 72 65 74 75 72 6e 28 4e 55 4c 4c 29 3b  ...return(NULL);
16b0: 0a 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e  ...}..}...return
16c0: 28 69 6e 74 65 72 70 29 3b 0a 7d 0a 0a 2f 2a 0a  (interp);.}../*.
16d0: 20 2a 20 45 76 61 6c 75 61 74 65 20 61 20 54 63   * Evaluate a Tc
16e0: 6c 20 73 63 72 69 70 74 20 63 6f 6e 73 74 72 75  l script constru
16f0: 63 74 65 64 20 62 79 20 63 6f 6e 63 61 74 65 6e  cted by concaten
1700: 61 74 69 6e 67 20 61 20 62 75 6e 63 68 20 6f 66  ating a bunch of
1710: 20 43 20 73 74 72 69 6e 67 73 0a 20 2a 20 74 6f   C strings. * to
1720: 67 65 74 68 65 72 2e 0a 20 2a 2f 0a 73 74 61 74  gether.. */.stat
1730: 69 63 20 69 6e 74 20 61 70 70 66 73 5f 54 63 6c  ic int appfs_Tcl
1740: 5f 45 76 61 6c 28 54 63 6c 5f 49 6e 74 65 72 70  _Eval(Tcl_Interp
1750: 20 2a 69 6e 74 65 72 70 2c 20 69 6e 74 20 6f 62   *interp, int ob
1760: 6a 63 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  jc, const char *
1770: 63 6d 64 2c 20 2e 2e 2e 29 20 7b 0a 09 54 63 6c  cmd, ...) {..Tcl
1780: 5f 4f 62 6a 20 2a 2a 6f 62 6a 76 3b 0a 09 63 6f  _Obj **objv;..co
1790: 6e 73 74 20 63 68 61 72 20 2a 61 72 67 3b 0a 09  nst char *arg;..
17a0: 76 61 5f 6c 69 73 74 20 61 72 67 70 3b 0a 09 69  va_list argp;..i
17b0: 6e 74 20 72 65 74 76 61 6c 3b 0a 09 69 6e 74 20  nt retval;..int 
17c0: 69 3b 0a 0a 09 69 66 20 28 69 6e 74 65 72 70 20  i;...if (interp 
17d0: 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 72 65 74  == NULL) {...ret
17e0: 75 72 6e 28 54 43 4c 5f 45 52 52 4f 52 29 3b 0a  urn(TCL_ERROR);.
17f0: 09 7d 0a 0a 09 6f 62 6a 76 20 3d 20 28 76 6f 69  .}...objv = (voi
1800: 64 20 2a 29 20 63 6b 61 6c 6c 6f 63 28 73 69 7a  d *) ckalloc(siz
1810: 65 6f 66 28 2a 6f 62 6a 76 29 20 2a 20 6f 62 6a  eof(*objv) * obj
1820: 63 29 3b 0a 09 6f 62 6a 76 5b 30 5d 20 3d 20 54  c);..objv[0] = T
1830: 63 6c 5f 4e 65 77 53 74 72 69 6e 67 4f 62 6a 28  cl_NewStringObj(
1840: 63 6d 64 2c 20 2d 31 29 3b 0a 09 54 63 6c 5f 49  cmd, -1);..Tcl_I
1850: 6e 63 72 52 65 66 43 6f 75 6e 74 28 6f 62 6a 76  ncrRefCount(objv
1860: 5b 30 5d 29 3b 0a 0a 09 76 61 5f 73 74 61 72 74  [0]);...va_start
1870: 28 61 72 67 70 2c 20 63 6d 64 29 3b 0a 09 66 6f  (argp, cmd);..fo
1880: 72 20 28 69 20 3d 20 31 3b 20 69 20 3c 20 6f 62  r (i = 1; i < ob
1890: 6a 63 3b 20 69 2b 2b 29 20 7b 0a 09 09 61 72 67  jc; i++) {...arg
18a0: 20 3d 20 76 61 5f 61 72 67 28 61 72 67 70 2c 20   = va_arg(argp, 
18b0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 29 3b 0a 09  const char *);..
18c0: 09 6f 62 6a 76 5b 69 5d 20 3d 20 54 63 6c 5f 4e  .objv[i] = Tcl_N
18d0: 65 77 53 74 72 69 6e 67 4f 62 6a 28 61 72 67 2c  ewStringObj(arg,
18e0: 20 2d 31 29 3b 0a 09 09 54 63 6c 5f 49 6e 63 72   -1);...Tcl_Incr
18f0: 52 65 66 43 6f 75 6e 74 28 6f 62 6a 76 5b 69 5d  RefCount(objv[i]
1900: 29 3b 0a 09 7d 0a 09 76 61 5f 65 6e 64 28 61 72  );..}..va_end(ar
1910: 67 70 29 3b 0a 0a 09 72 65 74 76 61 6c 20 3d 20  gp);...retval = 
1920: 54 63 6c 5f 45 76 61 6c 4f 62 6a 76 28 69 6e 74  Tcl_EvalObjv(int
1930: 65 72 70 2c 20 6f 62 6a 63 2c 20 6f 62 6a 76 2c  erp, objc, objv,
1940: 20 30 29 3b 0a 0a 09 66 6f 72 20 28 69 20 3d 20   0);...for (i = 
1950: 30 3b 20 69 20 3c 20 6f 62 6a 63 3b 20 69 2b 2b  0; i < objc; i++
1960: 29 20 7b 0a 09 09 54 63 6c 5f 44 65 63 72 52 65  ) {...Tcl_DecrRe
1970: 66 43 6f 75 6e 74 28 6f 62 6a 76 5b 69 5d 29 3b  fCount(objv[i]);
1980: 0a 09 7d 0a 0a 09 63 6b 66 72 65 65 28 28 76 6f  ..}...ckfree((vo
1990: 69 64 20 2a 29 20 6f 62 6a 76 29 3b 0a 0a 09 69  id *) objv);...i
19a0: 66 20 28 72 65 74 76 61 6c 20 21 3d 20 54 43 4c  f (retval != TCL
19b0: 5f 4f 4b 29 20 7b 0a 09 09 41 50 50 46 53 5f 44  _OK) {...APPFS_D
19c0: 45 42 55 47 28 22 54 63 6c 20 63 6f 6d 6d 61 6e  EBUG("Tcl comman
19d0: 64 20 66 61 69 6c 65 64 2c 20 3a 3a 65 72 72 6f  d failed, ::erro
19e0: 72 49 6e 66 6f 20 63 6f 6e 74 61 69 6e 73 3a 20  rInfo contains: 
19f0: 25 73 5c 6e 22 2c 20 54 63 6c 5f 47 65 74 56 61  %s\n", Tcl_GetVa
1a00: 72 28 69 6e 74 65 72 70 2c 20 22 3a 3a 65 72 72  r(interp, "::err
1a10: 6f 72 49 6e 66 6f 22 2c 20 30 29 29 3b 0a 09 7d  orInfo", 0));..}
1a20: 0a 0a 09 72 65 74 75 72 6e 28 72 65 74 76 61 6c  ...return(retval
1a30: 29 3b 0a 7d 0a 0a 2f 2a 0a 20 2a 20 44 65 74 65  );.}../*. * Dete
1a40: 72 6d 69 6e 65 20 74 68 65 20 55 49 44 20 66 6f  rmine the UID fo
1a50: 72 20 74 68 65 20 75 73 65 72 20 6d 61 6b 69 6e  r the user makin
1a60: 67 20 74 68 65 20 63 75 72 72 65 6e 74 20 46 55  g the current FU
1a70: 53 45 20 66 69 6c 65 73 79 73 74 65 6d 20 72 65  SE filesystem re
1a80: 71 75 65 73 74 2e 0a 20 2a 20 54 68 69 73 20 77  quest.. * This w
1a90: 69 6c 6c 20 62 65 20 75 73 65 64 20 74 6f 20 6c  ill be used to l
1aa0: 6f 6f 6b 75 70 20 74 68 65 20 75 73 65 72 27 73  ookup the user's
1ab0: 20 68 6f 6d 65 20 64 69 72 65 63 74 6f 72 79 20   home directory 
1ac0: 73 6f 20 77 65 20 63 61 6e 20 73 65 61 72 63 68  so we can search
1ad0: 20 66 6f 72 0a 20 2a 20 6c 6f 63 61 6c 6c 79 20   for. * locally 
1ae0: 6d 6f 64 69 66 69 65 64 20 66 69 6c 65 73 2e 0a  modified files..
1af0: 20 2a 2f 0a 73 74 61 74 69 63 20 75 69 64 5f 74   */.static uid_t
1b00: 20 61 70 70 66 73 5f 67 65 74 5f 66 73 75 69 64   appfs_get_fsuid
1b10: 28 76 6f 69 64 29 20 7b 0a 09 73 74 72 75 63 74  (void) {..struct
1b20: 20 66 75 73 65 5f 63 6f 6e 74 65 78 74 20 2a 63   fuse_context *c
1b30: 74 78 3b 0a 0a 09 69 66 20 28 21 61 70 70 66 73  tx;...if (!appfs
1b40: 5f 66 75 73 65 5f 73 74 61 72 74 65 64 29 20 7b  _fuse_started) {
1b50: 0a 09 09 72 65 74 75 72 6e 28 67 65 74 75 69 64  ...return(getuid
1b60: 28 29 29 3b 0a 09 7d 0a 0a 09 63 74 78 20 3d 20  ());..}...ctx = 
1b70: 66 75 73 65 5f 67 65 74 5f 63 6f 6e 74 65 78 74  fuse_get_context
1b80: 28 29 3b 0a 09 69 66 20 28 63 74 78 20 3d 3d 20  ();..if (ctx == 
1b90: 4e 55 4c 4c 29 20 7b 0a 09 09 2f 2a 20 55 6e 61  NULL) {.../* Una
1ba0: 62 6c 65 20 74 6f 20 6c 6f 6f 6b 75 70 20 75 73  ble to lookup us
1bb0: 65 72 20 66 6f 72 20 73 6f 6d 65 20 72 65 61 73  er for some reas
1bc0: 6f 6e 20 2a 2f 0a 09 09 2f 2a 20 52 65 74 75 72  on */.../* Retur
1bd0: 6e 20 61 6e 20 75 6e 70 72 69 76 69 6c 65 67 65  n an unprivilege
1be0: 64 20 75 73 65 72 20 49 44 20 2a 2f 0a 09 09 72  d user ID */...r
1bf0: 65 74 75 72 6e 28 31 29 3b 0a 09 7d 0a 0a 09 72  eturn(1);..}...r
1c00: 65 74 75 72 6e 28 63 74 78 2d 3e 75 69 64 29 3b  eturn(ctx->uid);
1c10: 0a 7d 0a 0a 2f 2a 0a 20 2a 20 44 65 74 65 72 6d  .}../*. * Determ
1c20: 69 6e 65 20 74 68 65 20 47 49 44 20 66 6f 72 20  ine the GID for 
1c30: 74 68 65 20 75 73 65 72 20 6d 61 6b 69 6e 67 20  the user making 
1c40: 74 68 65 20 63 75 72 72 65 6e 74 20 46 55 53 45  the current FUSE
1c50: 20 66 69 6c 65 73 79 73 74 65 6d 20 72 65 71 75   filesystem requ
1c60: 65 73 74 2e 0a 20 2a 20 54 68 69 73 20 77 69 6c  est.. * This wil
1c70: 6c 20 62 65 20 75 73 65 64 20 74 6f 20 6c 6f 6f  l be used to loo
1c80: 6b 75 70 20 74 68 65 20 75 73 65 72 27 73 20 68  kup the user's h
1c90: 6f 6d 65 20 64 69 72 65 63 74 6f 72 79 20 73 6f  ome directory so
1ca0: 20 77 65 20 63 61 6e 20 73 65 61 72 63 68 20 66   we can search f
1cb0: 6f 72 0a 20 2a 20 6c 6f 63 61 6c 6c 79 20 6d 6f  or. * locally mo
1cc0: 64 69 66 69 65 64 20 66 69 6c 65 73 2e 0a 20 2a  dified files.. *
1cd0: 2f 0a 73 74 61 74 69 63 20 67 69 64 5f 74 20 61  /.static gid_t a
1ce0: 70 70 66 73 5f 67 65 74 5f 66 73 67 69 64 28 76  ppfs_get_fsgid(v
1cf0: 6f 69 64 29 20 7b 0a 09 73 74 72 75 63 74 20 66  oid) {..struct f
1d00: 75 73 65 5f 63 6f 6e 74 65 78 74 20 2a 63 74 78  use_context *ctx
1d10: 3b 0a 0a 09 69 66 20 28 21 61 70 70 66 73 5f 66  ;...if (!appfs_f
1d20: 75 73 65 5f 73 74 61 72 74 65 64 29 20 7b 0a 09  use_started) {..
1d30: 09 72 65 74 75 72 6e 28 67 65 74 67 69 64 28 29  .return(getgid()
1d40: 29 3b 0a 09 7d 0a 0a 09 63 74 78 20 3d 20 66 75  );..}...ctx = fu
1d50: 73 65 5f 67 65 74 5f 63 6f 6e 74 65 78 74 28 29  se_get_context()
1d60: 3b 0a 09 69 66 20 28 63 74 78 20 3d 3d 20 4e 55  ;..if (ctx == NU
1d70: 4c 4c 29 20 7b 0a 09 09 2f 2a 20 55 6e 61 62 6c  LL) {.../* Unabl
1d80: 65 20 74 6f 20 6c 6f 6f 6b 75 70 20 75 73 65 72  e to lookup user
1d90: 20 66 6f 72 20 73 6f 6d 65 20 72 65 61 73 6f 6e   for some reason
1da0: 20 2a 2f 0a 09 09 2f 2a 20 52 65 74 75 72 6e 20   */.../* Return 
1db0: 61 6e 20 75 6e 70 72 69 76 69 6c 65 67 65 64 20  an unprivileged 
1dc0: 75 73 65 72 20 49 44 20 2a 2f 0a 09 09 72 65 74  user ID */...ret
1dd0: 75 72 6e 28 31 29 3b 0a 09 7d 0a 0a 09 72 65 74  urn(1);..}...ret
1de0: 75 72 6e 28 63 74 78 2d 3e 67 69 64 29 3b 0a 7d  urn(ctx->gid);.}
1df0: 0a 0a 73 74 61 74 69 63 20 76 6f 69 64 20 61 70  ..static void ap
1e00: 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65  pfs_simulate_use
1e10: 72 5f 66 73 5f 65 6e 74 65 72 28 76 6f 69 64 29  r_fs_enter(void)
1e20: 20 7b 0a 09 73 65 74 66 73 75 69 64 28 61 70 70   {..setfsuid(app
1e30: 66 73 5f 67 65 74 5f 66 73 75 69 64 28 29 29 3b  fs_get_fsuid());
1e40: 0a 09 73 65 74 66 73 67 69 64 28 61 70 70 66 73  ..setfsgid(appfs
1e50: 5f 67 65 74 5f 66 73 67 69 64 28 29 29 3b 0a 7d  _get_fsgid());.}
1e60: 0a 0a 73 74 61 74 69 63 20 76 6f 69 64 20 61 70  ..static void ap
1e70: 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65  pfs_simulate_use
1e80: 72 5f 66 73 5f 6c 65 61 76 65 28 76 6f 69 64 29  r_fs_leave(void)
1e90: 20 7b 0a 09 73 65 74 66 73 75 69 64 28 30 29 3b   {..setfsuid(0);
1ea0: 0a 09 73 65 74 66 73 67 69 64 28 30 29 3b 0a 7d  ..setfsgid(0);.}
1eb0: 0a 0a 2f 2a 0a 20 2a 20 4c 6f 6f 6b 20 75 70 20  ../*. * Look up 
1ec0: 74 68 65 20 68 6f 6d 65 20 64 69 72 65 63 74 6f  the home directo
1ed0: 72 79 20 66 6f 72 20 61 20 67 69 76 65 6e 20 55  ry for a given U
1ee0: 49 44 0a 20 2a 20 20 20 20 20 20 20 20 52 65 74  ID. *        Ret
1ef0: 75 72 6e 73 20 61 20 43 20 73 74 72 69 6e 67 20  urns a C string 
1f00: 63 6f 6e 74 61 69 6e 69 6e 67 20 74 68 65 20 75  containing the u
1f10: 73 65 72 27 73 20 68 6f 6d 65 20 64 69 72 65 63  ser's home direc
1f20: 74 6f 72 79 20 6f 72 20 4e 55 4c 4c 20 69 66 0a  tory or NULL if.
1f30: 20 2a 20 20 20 20 20 20 20 20 74 68 65 20 75 73   *        the us
1f40: 65 72 27 73 20 68 6f 6d 65 20 64 69 72 65 63 74  er's home direct
1f50: 6f 72 79 20 64 6f 65 73 20 6e 6f 74 20 65 78 69  ory does not exi
1f60: 73 74 20 6f 72 20 69 73 20 6e 6f 74 20 63 6f 72  st or is not cor
1f70: 72 65 63 74 6c 79 0a 20 2a 20 20 20 20 20 20 20  rectly. *       
1f80: 20 63 6f 6e 66 69 67 75 72 65 64 0a 20 2a 2f 0a   configured. */.
1f90: 73 74 61 74 69 63 20 63 68 61 72 20 2a 61 70 70  static char *app
1fa0: 66 73 5f 67 65 74 5f 68 6f 6d 65 64 69 72 28 75  fs_get_homedir(u
1fb0: 69 64 5f 74 20 66 73 75 69 64 29 20 7b 0a 09 73  id_t fsuid) {..s
1fc0: 74 72 75 63 74 20 70 61 73 73 77 64 20 65 6e 74  truct passwd ent
1fd0: 72 79 2c 20 2a 72 65 73 75 6c 74 3b 0a 09 73 74  ry, *result;..st
1fe0: 72 75 63 74 20 73 74 61 74 20 73 74 62 75 66 3b  ruct stat stbuf;
1ff0: 0a 09 63 68 61 72 20 62 75 66 5b 31 30 32 34 5d  ..char buf[1024]
2000: 2c 20 2a 72 65 74 76 61 6c 3b 0a 09 69 6e 74 20  , *retval;..int 
2010: 67 70 75 5f 72 65 74 2c 20 73 74 61 74 5f 72 65  gpu_ret, stat_re
2020: 74 3b 0a 0a 09 67 70 75 5f 72 65 74 20 3d 20 67  t;...gpu_ret = g
2030: 65 74 70 77 75 69 64 5f 72 28 66 73 75 69 64 2c  etpwuid_r(fsuid,
2040: 20 26 65 6e 74 72 79 2c 20 62 75 66 2c 20 73 69   &entry, buf, si
2050: 7a 65 6f 66 28 62 75 66 29 2c 20 26 72 65 73 75  zeof(buf), &resu
2060: 6c 74 29 3b 0a 09 69 66 20 28 67 70 75 5f 72 65  lt);..if (gpu_re
2070: 74 20 21 3d 20 30 29 20 7b 0a 09 09 41 50 50 46  t != 0) {...APPF
2080: 53 5f 44 45 42 55 47 28 22 67 65 74 70 77 75 69  S_DEBUG("getpwui
2090: 64 5f 72 28 25 6c 6c 75 2c 20 2e 2e 2e 29 20 72  d_r(%llu, ...) r
20a0: 65 74 75 72 6e 65 64 20 69 6e 20 66 61 69 6c 75  eturned in failu
20b0: 72 65 22 2c 20 28 75 6e 73 69 67 6e 65 64 20 6c  re", (unsigned l
20c0: 6f 6e 67 20 6c 6f 6e 67 29 20 66 73 75 69 64 29  ong long) fsuid)
20d0: 3b 0a 0a 09 09 72 65 74 75 72 6e 28 4e 55 4c 4c  ;....return(NULL
20e0: 29 3b 0a 09 7d 0a 0a 09 69 66 20 28 72 65 73 75  );..}...if (resu
20f0: 6c 74 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09  lt == NULL) {...
2100: 41 50 50 46 53 5f 44 45 42 55 47 28 22 67 65 74  APPFS_DEBUG("get
2110: 70 77 75 69 64 5f 72 28 25 6c 6c 75 2c 20 2e 2e  pwuid_r(%llu, ..
2120: 2e 29 20 72 65 74 75 72 6e 65 64 20 4e 55 4c 4c  .) returned NULL
2130: 20 72 65 73 75 6c 74 22 2c 20 28 75 6e 73 69 67   result", (unsig
2140: 6e 65 64 20 6c 6f 6e 67 20 6c 6f 6e 67 29 20 66  ned long long) f
2150: 73 75 69 64 29 3b 0a 0a 09 09 72 65 74 75 72 6e  suid);....return
2160: 28 4e 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 69 66 20  (NULL);..}...if 
2170: 28 72 65 73 75 6c 74 2d 3e 70 77 5f 64 69 72 20  (result->pw_dir 
2180: 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 41 50 50  == NULL) {...APP
2190: 46 53 5f 44 45 42 55 47 28 22 67 65 74 70 77 75  FS_DEBUG("getpwu
21a0: 69 64 5f 72 28 25 6c 6c 75 2c 20 2e 2e 2e 29 20  id_r(%llu, ...) 
21b0: 72 65 74 75 72 6e 65 64 20 4e 55 4c 4c 20 68 6f  returned NULL ho
21c0: 6d 65 20 64 69 72 65 63 74 6f 72 79 22 2c 20 28  me directory", (
21d0: 75 6e 73 69 67 6e 65 64 20 6c 6f 6e 67 20 6c 6f  unsigned long lo
21e0: 6e 67 29 20 66 73 75 69 64 29 3b 0a 0a 09 09 72  ng) fsuid);....r
21f0: 65 74 75 72 6e 28 4e 55 4c 4c 29 3b 0a 09 7d 0a  eturn(NULL);..}.
2200: 0a 09 73 74 61 74 5f 72 65 74 20 3d 20 73 74 61  ..stat_ret = sta
2210: 74 28 72 65 73 75 6c 74 2d 3e 70 77 5f 64 69 72  t(result->pw_dir
2220: 2c 20 26 73 74 62 75 66 29 3b 0a 09 69 66 20 28  , &stbuf);..if (
2230: 73 74 61 74 5f 72 65 74 20 21 3d 20 30 29 20 7b  stat_ret != 0) {
2240: 0a 09 09 41 50 50 46 53 5f 44 45 42 55 47 28 22  ...APPFS_DEBUG("
2250: 73 74 61 74 28 25 73 29 20 72 65 74 75 72 6e 65  stat(%s) returne
2260: 64 20 69 6e 20 66 61 69 6c 75 72 65 22 2c 20 72  d in failure", r
2270: 65 73 75 6c 74 2d 3e 70 77 5f 64 69 72 29 3b 0a  esult->pw_dir);.
2280: 0a 09 09 72 65 74 75 72 6e 28 4e 55 4c 4c 29 3b  ...return(NULL);
2290: 0a 09 7d 0a 0a 09 69 66 20 28 73 74 62 75 66 2e  ..}...if (stbuf.
22a0: 73 74 5f 75 69 64 20 21 3d 20 66 73 75 69 64 29  st_uid != fsuid)
22b0: 20 7b 0a 09 09 41 50 50 46 53 5f 44 45 42 55 47   {...APPFS_DEBUG
22c0: 28 22 55 49 44 20 6d 69 73 2d 6d 61 74 63 68 20  ("UID mis-match 
22d0: 6f 6e 20 75 73 65 72 20 25 6c 6c 75 27 73 20 68  on user %llu's h
22e0: 6f 6d 65 20 64 69 72 65 63 74 6f 72 79 20 28 25  ome directory (%
22f0: 73 29 2e 20 20 49 74 27 73 20 6f 77 6e 65 64 20  s).  It's owned 
2300: 62 79 20 25 6c 6c 75 2e 22 2c 0a 09 09 20 20 20  by %llu.",...   
2310: 20 28 75 6e 73 69 67 6e 65 64 20 6c 6f 6e 67 20   (unsigned long 
2320: 6c 6f 6e 67 29 20 66 73 75 69 64 2c 0a 09 09 20  long) fsuid,... 
2330: 20 20 20 72 65 73 75 6c 74 2d 3e 70 77 5f 64 69     result->pw_di
2340: 72 2c 0a 09 09 20 20 20 20 28 75 6e 73 69 67 6e  r,...    (unsign
2350: 65 64 20 6c 6f 6e 67 20 6c 6f 6e 67 29 20 73 74  ed long long) st
2360: 62 75 66 2e 73 74 5f 75 69 64 0a 09 09 29 3b 0a  buf.st_uid...);.
2370: 0a 09 09 72 65 74 75 72 6e 28 4e 55 4c 4c 29 3b  ...return(NULL);
2380: 0a 09 7d 0a 0a 09 72 65 74 76 61 6c 20 3d 20 73  ..}...retval = s
2390: 74 72 64 75 70 28 72 65 73 75 6c 74 2d 3e 70 77  trdup(result->pw
23a0: 5f 64 69 72 29 3b 0a 0a 09 72 65 74 75 72 6e 28  _dir);...return(
23b0: 72 65 74 76 61 6c 29 3b 0a 7d 0a 0a 2f 2a 0a 20  retval);.}../*. 
23c0: 2a 20 54 63 6c 20 69 6e 74 65 72 66 61 63 65 20  * Tcl interface 
23d0: 74 6f 20 67 65 74 20 74 68 65 20 68 6f 6d 65 20  to get the home 
23e0: 64 69 72 65 63 74 6f 72 79 20 66 6f 72 20 74 68  directory for th
23f0: 65 20 75 73 65 72 20 6d 61 6b 69 6e 67 20 74 68  e user making th
2400: 65 20 22 63 75 72 72 65 6e 74 22 0a 20 2a 20 46  e "current". * F
2410: 55 53 45 20 49 2f 4f 20 72 65 71 75 65 73 74 0a  USE I/O request.
2420: 20 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74   */.static int t
2430: 63 6c 5f 61 70 70 66 73 5f 67 65 74 5f 68 6f 6d  cl_appfs_get_hom
2440: 65 64 69 72 28 43 6c 69 65 6e 74 44 61 74 61 20  edir(ClientData 
2450: 63 64 2c 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a  cd, Tcl_Interp *
2460: 69 6e 74 65 72 70 2c 20 69 6e 74 20 6f 62 6a 63  interp, int objc
2470: 2c 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54  , Tcl_Obj *CONST
2480: 20 6f 62 6a 76 5b 5d 29 20 7b 0a 09 63 68 61 72   objv[]) {..char
2490: 20 2a 68 6f 6d 65 64 69 72 3b 0a 09 54 63 6c 5f   *homedir;..Tcl_
24a0: 4f 62 6a 20 2a 68 6f 6d 65 64 69 72 5f 6f 62 6a  Obj *homedir_obj
24b0: 3b 0a 09 75 69 64 5f 74 20 66 73 75 69 64 3b 0a  ;..uid_t fsuid;.
24c0: 09 73 74 61 74 69 63 20 5f 5f 74 68 72 65 61 64  .static __thread
24d0: 20 54 63 6c 5f 4f 62 6a 20 2a 6c 61 73 74 5f 68   Tcl_Obj *last_h
24e0: 6f 6d 65 64 69 72 5f 6f 62 6a 20 3d 20 4e 55 4c  omedir_obj = NUL
24f0: 4c 3b 0a 09 73 74 61 74 69 63 20 5f 5f 74 68 72  L;..static __thr
2500: 65 61 64 20 75 69 64 5f 74 20 6c 61 73 74 5f 66  ead uid_t last_f
2510: 73 75 69 64 20 3d 20 2d 31 3b 0a 0a 20 20 20 20  suid = -1;..    
2520: 20 20 20 20 69 66 20 28 6f 62 6a 63 20 21 3d 20      if (objc != 
2530: 31 29 20 7b 0a 20 20 20 20 20 20 20 20 20 20 20  1) {.           
2540: 20 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75       Tcl_WrongNu
2550: 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31 2c  mArgs(interp, 1,
2560: 20 6f 62 6a 76 2c 20 4e 55 4c 4c 29 3b 0a 20 20   objv, NULL);.  
2570: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
2580: 74 75 72 6e 28 54 43 4c 5f 45 52 52 4f 52 29 3b  turn(TCL_ERROR);
2590: 0a 20 20 20 20 20 20 20 20 7d 0a 0a 09 66 73 75  .        }...fsu
25a0: 69 64 20 3d 20 61 70 70 66 73 5f 67 65 74 5f 66  id = appfs_get_f
25b0: 73 75 69 64 28 29 3b 0a 0a 09 69 66 20 28 66 73  suid();...if (fs
25c0: 75 69 64 20 3d 3d 20 6c 61 73 74 5f 66 73 75 69  uid == last_fsui
25d0: 64 20 26 26 20 6c 61 73 74 5f 68 6f 6d 65 64 69  d && last_homedi
25e0: 72 5f 6f 62 6a 20 21 3d 20 4e 55 4c 4c 29 20 7b  r_obj != NULL) {
25f0: 0a 09 09 68 6f 6d 65 64 69 72 5f 6f 62 6a 20 3d  ...homedir_obj =
2600: 20 6c 61 73 74 5f 68 6f 6d 65 64 69 72 5f 6f 62   last_homedir_ob
2610: 6a 3b 0a 09 7d 20 65 6c 73 65 20 7b 0a 09 09 69  j;..} else {...i
2620: 66 20 28 6c 61 73 74 5f 68 6f 6d 65 64 69 72 5f  f (last_homedir_
2630: 6f 62 6a 20 21 3d 20 4e 55 4c 4c 29 20 7b 0a 09  obj != NULL) {..
2640: 09 09 54 63 6c 5f 44 65 63 72 52 65 66 43 6f 75  ..Tcl_DecrRefCou
2650: 6e 74 28 6c 61 73 74 5f 68 6f 6d 65 64 69 72 5f  nt(last_homedir_
2660: 6f 62 6a 29 3b 0a 09 09 7d 0a 0a 09 09 68 6f 6d  obj);...}....hom
2670: 65 64 69 72 20 3d 20 61 70 70 66 73 5f 67 65 74  edir = appfs_get
2680: 5f 68 6f 6d 65 64 69 72 28 61 70 70 66 73 5f 67  _homedir(appfs_g
2690: 65 74 5f 66 73 75 69 64 28 29 29 3b 0a 0a 09 09  et_fsuid());....
26a0: 69 66 20 28 68 6f 6d 65 64 69 72 20 3d 3d 20 4e  if (homedir == N
26b0: 55 4c 4c 29 20 7b 0a 09 09 09 72 65 74 75 72 6e  ULL) {....return
26c0: 28 54 43 4c 5f 45 52 52 4f 52 29 3b 0a 09 09 7d  (TCL_ERROR);...}
26d0: 0a 0a 09 09 68 6f 6d 65 64 69 72 5f 6f 62 6a 20  ....homedir_obj 
26e0: 3d 20 54 63 6c 5f 4e 65 77 53 74 72 69 6e 67 4f  = Tcl_NewStringO
26f0: 62 6a 28 68 6f 6d 65 64 69 72 2c 20 2d 31 29 3b  bj(homedir, -1);
2700: 0a 0a 09 09 66 72 65 65 28 68 6f 6d 65 64 69 72  ....free(homedir
2710: 29 3b 0a 0a 09 09 6c 61 73 74 5f 68 6f 6d 65 64  );....last_homed
2720: 69 72 5f 6f 62 6a 20 3d 20 68 6f 6d 65 64 69 72  ir_obj = homedir
2730: 5f 6f 62 6a 3b 0a 09 09 6c 61 73 74 5f 66 73 75  _obj;...last_fsu
2740: 69 64 20 3d 20 66 73 75 69 64 3b 0a 0a 09 09 54  id = fsuid;....T
2750: 63 6c 5f 49 6e 63 72 52 65 66 43 6f 75 6e 74 28  cl_IncrRefCount(
2760: 6c 61 73 74 5f 68 6f 6d 65 64 69 72 5f 6f 62 6a  last_homedir_obj
2770: 29 3b 0a 09 7d 0a 0a 20 20 20 20 20 20 20 09 54  );..}..       .T
2780: 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c 74 28  cl_SetObjResult(
2790: 69 6e 74 65 72 70 2c 20 68 6f 6d 65 64 69 72 5f  interp, homedir_
27a0: 6f 62 6a 29 3b 0a 0a 20 20 20 20 20 20 20 20 72  obj);..        r
27b0: 65 74 75 72 6e 28 54 43 4c 5f 4f 4b 29 3b 0a 7d  eturn(TCL_OK);.}
27c0: 0a 0a 73 74 61 74 69 63 20 69 6e 74 20 74 63 6c  ..static int tcl
27d0: 5f 61 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f  _appfs_simulate_
27e0: 75 73 65 72 5f 66 73 5f 65 6e 74 65 72 28 43 6c  user_fs_enter(Cl
27f0: 69 65 6e 74 44 61 74 61 20 63 64 2c 20 54 63 6c  ientData cd, Tcl
2800: 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c  _Interp *interp,
2810: 20 69 6e 74 20 6f 62 6a 63 2c 20 54 63 6c 5f 4f   int objc, Tcl_O
2820: 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d  bj *CONST objv[]
2830: 29 20 7b 0a 09 61 70 70 66 73 5f 73 69 6d 75 6c  ) {..appfs_simul
2840: 61 74 65 5f 75 73 65 72 5f 66 73 5f 65 6e 74 65  ate_user_fs_ente
2850: 72 28 29 3b 0a 0a 09 72 65 74 75 72 6e 28 54 43  r();...return(TC
2860: 4c 5f 4f 4b 29 3b 0a 7d 0a 0a 73 74 61 74 69 63  L_OK);.}..static
2870: 20 69 6e 74 20 74 63 6c 5f 61 70 70 66 73 5f 73   int tcl_appfs_s
2880: 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f  imulate_user_fs_
2890: 6c 65 61 76 65 28 43 6c 69 65 6e 74 44 61 74 61  leave(ClientData
28a0: 20 63 64 2c 20 54 63 6c 5f 49 6e 74 65 72 70 20   cd, Tcl_Interp 
28b0: 2a 69 6e 74 65 72 70 2c 20 69 6e 74 20 6f 62 6a  *interp, int obj
28c0: 63 2c 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53  c, Tcl_Obj *CONS
28d0: 54 20 6f 62 6a 76 5b 5d 29 20 7b 0a 09 61 70 70  T objv[]) {..app
28e0: 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65 72  fs_simulate_user
28f0: 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a 0a 09 72  _fs_leave();...r
2900: 65 74 75 72 6e 28 54 43 4c 5f 4f 4b 29 3b 0a 7d  eturn(TCL_OK);.}
2910: 0a 0a 2f 2a 0a 20 2a 20 47 65 6e 65 72 61 74 65  ../*. * Generate
2920: 20 61 6e 20 69 6e 6f 64 65 20 66 6f 72 20 61 20   an inode for a 
2930: 67 69 76 65 6e 20 70 61 74 68 2e 20 20 54 68 65  given path.  The
2940: 20 69 6e 6f 64 65 20 73 68 6f 75 6c 64 20 62 65   inode should be
2950: 20 63 6f 6d 70 75 74 65 64 20 69 6e 20 73 75 63   computed in suc
2960: 68 0a 20 2a 20 61 20 77 61 79 20 74 68 61 74 20  h. * a way that 
2970: 69 74 20 69 73 20 75 6e 6c 69 6b 65 6c 79 20 74  it is unlikely t
2980: 6f 20 62 65 20 64 75 70 6c 69 63 61 74 65 64 20  o be duplicated 
2990: 61 6e 64 20 72 65 6d 61 69 6e 73 20 74 68 65 20  and remains the 
29a0: 73 61 6d 65 20 66 6f 72 20 61 20 67 69 76 65 6e  same for a given
29b0: 0a 20 2a 20 66 69 6c 65 0a 20 2a 2f 0a 73 74 61  . * file. */.sta
29c0: 74 69 63 20 6c 6f 6e 67 20 6c 6f 6e 67 20 61 70  tic long long ap
29d0: 70 66 73 5f 67 65 74 5f 70 61 74 68 5f 69 6e 6f  pfs_get_path_ino
29e0: 64 65 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 70  de(const char *p
29f0: 61 74 68 29 20 7b 0a 09 6c 6f 6e 67 20 6c 6f 6e  ath) {..long lon
2a00: 67 20 72 65 74 76 61 6c 3b 0a 09 63 6f 6e 73 74  g retval;..const
2a10: 20 63 68 61 72 20 2a 70 3b 0a 0a 09 72 65 74 76   char *p;...retv
2a20: 61 6c 20 3d 20 31 30 3b 0a 0a 09 66 6f 72 20 28  al = 10;...for (
2a30: 70 20 3d 20 70 61 74 68 3b 20 2a 70 3b 20 70 2b  p = path; *p; p+
2a40: 2b 29 20 7b 0a 09 09 72 65 74 76 61 6c 20 25 3d  +) {...retval %=
2a50: 20 34 32 39 30 39 36 30 32 39 30 55 4c 4c 3b 0a   4290960290ULL;.
2a60: 09 09 72 65 74 76 61 6c 20 2b 3d 20 2a 70 3b 0a  ..retval += *p;.
2a70: 09 09 72 65 74 76 61 6c 20 3c 3c 3d 20 37 3b 0a  ..retval <<= 7;.
2a80: 09 7d 0a 0a 09 72 65 74 76 61 6c 20 2b 3d 20 31  .}...retval += 1
2a90: 30 3b 0a 09 72 65 74 76 61 6c 20 25 3d 20 34 32  0;..retval %= 42
2aa0: 39 34 39 36 37 32 39 36 55 4c 4c 3b 0a 0a 09 72  94967296ULL;...r
2ab0: 65 74 75 72 6e 28 72 65 74 76 61 6c 29 3b 0a 7d  eturn(retval);.}
2ac0: 0a 0a 2f 2a 20 47 65 74 20 69 6e 66 6f 72 6d 61  ../* Get informa
2ad0: 74 69 6f 6e 20 61 62 6f 75 74 20 61 20 70 61 74  tion about a pat
2ae0: 68 2c 20 61 6e 64 20 6f 70 74 69 6f 6e 61 6c 6c  h, and optionall
2af0: 79 20 6c 69 73 74 20 63 68 69 6c 64 72 65 6e 20  y list children 
2b00: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 61 70  */.static int ap
2b10: 70 66 73 5f 67 65 74 5f 70 61 74 68 5f 69 6e 66  pfs_get_path_inf
2b20: 6f 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 70 61  o(const char *pa
2b30: 74 68 2c 20 73 74 72 75 63 74 20 61 70 70 66 73  th, struct appfs
2b40: 5f 70 61 74 68 69 6e 66 6f 20 2a 70 61 74 68 69  _pathinfo *pathi
2b50: 6e 66 6f 29 20 7b 0a 09 54 63 6c 5f 49 6e 74 65  nfo) {..Tcl_Inte
2b60: 72 70 20 2a 69 6e 74 65 72 70 3b 0a 09 54 63 6c  rp *interp;..Tcl
2b70: 5f 4f 62 6a 20 2a 61 74 74 72 73 5f 64 69 63 74  _Obj *attrs_dict
2b80: 2c 20 2a 61 74 74 72 5f 76 61 6c 75 65 3b 0a 09  , *attr_value;..
2b90: 63 6f 6e 73 74 20 63 68 61 72 20 2a 61 74 74 72  const char *attr
2ba0: 5f 76 61 6c 75 65 5f 73 74 72 3b 0a 09 54 63 6c  _value_str;..Tcl
2bb0: 5f 57 69 64 65 49 6e 74 20 61 74 74 72 5f 76 61  _WideInt attr_va
2bc0: 6c 75 65 5f 77 69 64 65 3b 0a 09 69 6e 74 20 61  lue_wide;..int a
2bd0: 74 74 72 5f 76 61 6c 75 65 5f 69 6e 74 3b 0a 09  ttr_value_int;..
2be0: 73 74 61 74 69 63 20 5f 5f 74 68 72 65 61 64 20  static __thread 
2bf0: 54 63 6c 5f 4f 62 6a 20 2a 61 74 74 72 5f 6b 65  Tcl_Obj *attr_ke
2c00: 79 5f 74 79 70 65 20 3d 20 4e 55 4c 4c 2c 20 2a  y_type = NULL, *
2c10: 61 74 74 72 5f 6b 65 79 5f 70 65 72 6d 73 20 3d  attr_key_perms =
2c20: 20 4e 55 4c 4c 2c 20 2a 61 74 74 72 5f 6b 65 79   NULL, *attr_key
2c30: 5f 73 69 7a 65 20 3d 20 4e 55 4c 4c 2c 20 2a 61  _size = NULL, *a
2c40: 74 74 72 5f 6b 65 79 5f 74 69 6d 65 20 3d 20 4e  ttr_key_time = N
2c50: 55 4c 4c 2c 20 2a 61 74 74 72 5f 6b 65 79 5f 73  ULL, *attr_key_s
2c60: 6f 75 72 63 65 20 3d 20 4e 55 4c 4c 2c 20 2a 61  ource = NULL, *a
2c70: 74 74 72 5f 6b 65 79 5f 63 68 69 6c 64 63 6f 75  ttr_key_childcou
2c80: 6e 74 20 3d 20 4e 55 4c 4c 2c 20 2a 61 74 74 72  nt = NULL, *attr
2c90: 5f 6b 65 79 5f 70 61 63 6b 61 67 65 64 20 3d 20  _key_packaged = 
2ca0: 4e 55 4c 4c 3b 0a 09 69 6e 74 20 74 63 6c 5f 72  NULL;..int tcl_r
2cb0: 65 74 3b 0a 0a 09 69 6e 74 65 72 70 20 3d 20 61  et;...interp = a
2cc0: 70 70 66 73 5f 54 63 6c 49 6e 74 65 72 70 28 29  ppfs_TclInterp()
2cd0: 3b 0a 09 69 66 20 28 69 6e 74 65 72 70 20 3d 3d  ;..if (interp ==
2ce0: 20 4e 55 4c 4c 29 20 7b 0a 09 09 72 65 74 75 72   NULL) {...retur
2cf0: 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a 09 61 70  n(-EIO);..}...ap
2d00: 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65  pfs_simulate_use
2d10: 72 5f 66 73 5f 65 6e 74 65 72 28 29 3b 0a 0a 09  r_fs_enter();...
2d20: 74 63 6c 5f 72 65 74 20 3d 20 61 70 70 66 73 5f  tcl_ret = appfs_
2d30: 54 63 6c 5f 45 76 61 6c 28 69 6e 74 65 72 70 2c  Tcl_Eval(interp,
2d40: 20 32 2c 20 22 3a 3a 61 70 70 66 73 3a 3a 67 65   2, "::appfs::ge
2d50: 74 61 74 74 72 22 2c 20 70 61 74 68 29 3b 0a 0a  tattr", path);..
2d60: 09 61 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f  .appfs_simulate_
2d70: 75 73 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b  user_fs_leave();
2d80: 0a 0a 09 69 66 20 28 74 63 6c 5f 72 65 74 20 21  ...if (tcl_ret !
2d90: 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09 41 50  = TCL_OK) {...AP
2da0: 50 46 53 5f 44 45 42 55 47 28 22 3a 3a 61 70 70  PFS_DEBUG("::app
2db0: 66 73 3a 3a 67 65 74 61 74 74 72 28 25 73 29 20  fs::getattr(%s) 
2dc0: 66 61 69 6c 65 64 2e 22 2c 20 70 61 74 68 29 3b  failed.", path);
2dd0: 0a 09 09 41 50 50 46 53 5f 44 45 42 55 47 28 22  ...APPFS_DEBUG("
2de0: 54 63 6c 20 45 72 72 6f 72 20 69 73 3a 20 25 73  Tcl Error is: %s
2df0: 22 2c 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67  ", Tcl_GetString
2e00: 52 65 73 75 6c 74 28 69 6e 74 65 72 70 29 29 3b  Result(interp));
2e10: 0a 0a 09 09 72 65 74 75 72 6e 28 2d 45 4e 4f 45  ....return(-ENOE
2e20: 4e 54 29 3b 0a 09 7d 0a 0a 09 69 66 20 28 61 74  NT);..}...if (at
2e30: 74 72 5f 6b 65 79 5f 74 79 70 65 20 3d 3d 20 4e  tr_key_type == N
2e40: 55 4c 4c 29 20 7b 0a 09 09 61 74 74 72 5f 6b 65  ULL) {...attr_ke
2e50: 79 5f 74 79 70 65 20 20 20 20 20 20 20 3d 20 54  y_type       = T
2e60: 63 6c 5f 4e 65 77 53 74 72 69 6e 67 4f 62 6a 28  cl_NewStringObj(
2e70: 22 74 79 70 65 22 2c 20 2d 31 29 3b 0a 09 09 61  "type", -1);...a
2e80: 74 74 72 5f 6b 65 79 5f 70 65 72 6d 73 20 20 20  ttr_key_perms   
2e90: 20 20 20 3d 20 54 63 6c 5f 4e 65 77 53 74 72 69     = Tcl_NewStri
2ea0: 6e 67 4f 62 6a 28 22 70 65 72 6d 73 22 2c 20 2d  ngObj("perms", -
2eb0: 31 29 3b 0a 09 09 61 74 74 72 5f 6b 65 79 5f 73  1);...attr_key_s
2ec0: 69 7a 65 20 20 20 20 20 20 20 3d 20 54 63 6c 5f  ize       = Tcl_
2ed0: 4e 65 77 53 74 72 69 6e 67 4f 62 6a 28 22 73 69  NewStringObj("si
2ee0: 7a 65 22 2c 20 2d 31 29 3b 0a 09 09 61 74 74 72  ze", -1);...attr
2ef0: 5f 6b 65 79 5f 74 69 6d 65 20 20 20 20 20 20 20  _key_time       
2f00: 3d 20 54 63 6c 5f 4e 65 77 53 74 72 69 6e 67 4f  = Tcl_NewStringO
2f10: 62 6a 28 22 74 69 6d 65 22 2c 20 2d 31 29 3b 0a  bj("time", -1);.
2f20: 09 09 61 74 74 72 5f 6b 65 79 5f 73 6f 75 72 63  ..attr_key_sourc
2f30: 65 20 20 20 20 20 3d 20 54 63 6c 5f 4e 65 77 53  e     = Tcl_NewS
2f40: 74 72 69 6e 67 4f 62 6a 28 22 73 6f 75 72 63 65  tringObj("source
2f50: 22 2c 20 2d 31 29 3b 0a 09 09 61 74 74 72 5f 6b  ", -1);...attr_k
2f60: 65 79 5f 63 68 69 6c 64 63 6f 75 6e 74 20 3d 20  ey_childcount = 
2f70: 54 63 6c 5f 4e 65 77 53 74 72 69 6e 67 4f 62 6a  Tcl_NewStringObj
2f80: 28 22 63 68 69 6c 64 63 6f 75 6e 74 22 2c 20 2d  ("childcount", -
2f90: 31 29 3b 0a 09 09 61 74 74 72 5f 6b 65 79 5f 70  1);...attr_key_p
2fa0: 61 63 6b 61 67 65 64 20 20 20 3d 20 54 63 6c 5f  ackaged   = Tcl_
2fb0: 4e 65 77 53 74 72 69 6e 67 4f 62 6a 28 22 70 61  NewStringObj("pa
2fc0: 63 6b 61 67 65 64 22 2c 20 2d 31 29 3b 0a 09 7d  ckaged", -1);..}
2fd0: 0a 0a 09 61 74 74 72 73 5f 64 69 63 74 20 3d 20  ...attrs_dict = 
2fe0: 54 63 6c 5f 47 65 74 4f 62 6a 52 65 73 75 6c 74  Tcl_GetObjResult
2ff0: 28 69 6e 74 65 72 70 29 3b 0a 09 74 63 6c 5f 72  (interp);..tcl_r
3000: 65 74 20 3d 20 54 63 6c 5f 44 69 63 74 4f 62 6a  et = Tcl_DictObj
3010: 47 65 74 28 69 6e 74 65 72 70 2c 20 61 74 74 72  Get(interp, attr
3020: 73 5f 64 69 63 74 2c 20 61 74 74 72 5f 6b 65 79  s_dict, attr_key
3030: 5f 74 79 70 65 2c 20 26 61 74 74 72 5f 76 61 6c  _type, &attr_val
3040: 75 65 29 3b 0a 09 69 66 20 28 74 63 6c 5f 72 65  ue);..if (tcl_re
3050: 74 20 21 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09  t != TCL_OK) {..
3060: 09 41 50 50 46 53 5f 44 45 42 55 47 28 22 5b 64  .APPFS_DEBUG("[d
3070: 69 63 74 20 67 65 74 20 5c 22 74 79 70 65 5c 22  ict get \"type\"
3080: 5d 20 66 61 69 6c 65 64 22 29 3b 0a 09 09 41 50  ] failed");...AP
3090: 50 46 53 5f 44 45 42 55 47 28 22 54 63 6c 20 45  PFS_DEBUG("Tcl E
30a0: 72 72 6f 72 20 69 73 3a 20 25 73 22 2c 20 54 63  rror is: %s", Tc
30b0: 6c 5f 47 65 74 53 74 72 69 6e 67 52 65 73 75 6c  l_GetStringResul
30c0: 74 28 69 6e 74 65 72 70 29 29 3b 0a 0a 09 09 72  t(interp));....r
30d0: 65 74 75 72 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a  eturn(-EIO);..}.
30e0: 0a 09 69 66 20 28 61 74 74 72 5f 76 61 6c 75 65  ..if (attr_value
30f0: 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 72 65   == NULL) {...re
3100: 74 75 72 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a  turn(-EIO);..}..
3110: 09 70 61 74 68 69 6e 66 6f 2d 3e 70 61 63 6b 61  .pathinfo->packa
3120: 67 65 64 20 3d 20 30 3b 0a 09 70 61 74 68 69 6e  ged = 0;..pathin
3130: 66 6f 2d 3e 69 6e 6f 64 65 20 3d 20 61 70 70 66  fo->inode = appf
3140: 73 5f 67 65 74 5f 70 61 74 68 5f 69 6e 6f 64 65  s_get_path_inode
3150: 28 70 61 74 68 29 3b 0a 0a 09 61 74 74 72 5f 76  (path);...attr_v
3160: 61 6c 75 65 5f 73 74 72 20 3d 20 54 63 6c 5f 47  alue_str = Tcl_G
3170: 65 74 53 74 72 69 6e 67 28 61 74 74 72 5f 76 61  etString(attr_va
3180: 6c 75 65 29 3b 0a 09 73 77 69 74 63 68 20 28 61  lue);..switch (a
3190: 74 74 72 5f 76 61 6c 75 65 5f 73 74 72 5b 30 5d  ttr_value_str[0]
31a0: 29 20 7b 0a 09 09 63 61 73 65 20 27 64 27 3a 20  ) {...case 'd': 
31b0: 2f 2a 20 64 69 72 65 63 74 6f 72 79 20 2a 2f 0a  /* directory */.
31c0: 09 09 09 70 61 74 68 69 6e 66 6f 2d 3e 74 79 70  ...pathinfo->typ
31d0: 65 20 3d 20 41 50 50 46 53 5f 50 41 54 48 54 59  e = APPFS_PATHTY
31e0: 50 45 5f 44 49 52 45 43 54 4f 52 59 3b 0a 09 09  PE_DIRECTORY;...
31f0: 09 70 61 74 68 69 6e 66 6f 2d 3e 74 79 70 65 69  .pathinfo->typei
3200: 6e 66 6f 2e 64 69 72 2e 63 68 69 6c 64 63 6f 75  nfo.dir.childcou
3210: 6e 74 20 3d 20 30 3b 0a 0a 09 09 09 54 63 6c 5f  nt = 0;.....Tcl_
3220: 44 69 63 74 4f 62 6a 47 65 74 28 69 6e 74 65 72  DictObjGet(inter
3230: 70 2c 20 61 74 74 72 73 5f 64 69 63 74 2c 20 61  p, attrs_dict, a
3240: 74 74 72 5f 6b 65 79 5f 63 68 69 6c 64 63 6f 75  ttr_key_childcou
3250: 6e 74 2c 20 26 61 74 74 72 5f 76 61 6c 75 65 29  nt, &attr_value)
3260: 3b 0a 09 09 09 69 66 20 28 61 74 74 72 5f 76 61  ;....if (attr_va
3270: 6c 75 65 20 21 3d 20 4e 55 4c 4c 29 20 7b 0a 09  lue != NULL) {..
3280: 09 09 09 74 63 6c 5f 72 65 74 20 3d 20 54 63 6c  ...tcl_ret = Tcl
3290: 5f 47 65 74 57 69 64 65 49 6e 74 46 72 6f 6d 4f  _GetWideIntFromO
32a0: 62 6a 28 4e 55 4c 4c 2c 20 61 74 74 72 5f 76 61  bj(NULL, attr_va
32b0: 6c 75 65 2c 20 26 61 74 74 72 5f 76 61 6c 75 65  lue, &attr_value
32c0: 5f 77 69 64 65 29 3b 0a 09 09 09 09 69 66 20 28  _wide);.....if (
32d0: 74 63 6c 5f 72 65 74 20 3d 3d 20 54 43 4c 5f 4f  tcl_ret == TCL_O
32e0: 4b 29 20 7b 0a 09 09 09 09 09 70 61 74 68 69 6e  K) {......pathin
32f0: 66 6f 2d 3e 74 79 70 65 69 6e 66 6f 2e 64 69 72  fo->typeinfo.dir
3300: 2e 63 68 69 6c 64 63 6f 75 6e 74 20 3d 20 61 74  .childcount = at
3310: 74 72 5f 76 61 6c 75 65 5f 77 69 64 65 3b 0a 09  tr_value_wide;..
3320: 09 09 09 7d 0a 09 09 09 7d 0a 0a 09 09 09 62 72  ...}....}.....br
3330: 65 61 6b 3b 0a 09 09 63 61 73 65 20 27 66 27 3a  eak;...case 'f':
3340: 20 2f 2a 20 66 69 6c 65 20 2a 2f 0a 09 09 09 70   /* file */....p
3350: 61 74 68 69 6e 66 6f 2d 3e 74 79 70 65 20 3d 20  athinfo->type = 
3360: 41 50 50 46 53 5f 50 41 54 48 54 59 50 45 5f 46  APPFS_PATHTYPE_F
3370: 49 4c 45 3b 0a 09 09 09 70 61 74 68 69 6e 66 6f  ILE;....pathinfo
3380: 2d 3e 74 79 70 65 69 6e 66 6f 2e 66 69 6c 65 2e  ->typeinfo.file.
3390: 73 69 7a 65 20 3d 20 30 3b 0a 09 09 09 70 61 74  size = 0;....pat
33a0: 68 69 6e 66 6f 2d 3e 74 79 70 65 69 6e 66 6f 2e  hinfo->typeinfo.
33b0: 66 69 6c 65 2e 65 78 65 63 75 74 61 62 6c 65 20  file.executable 
33c0: 3d 20 30 3b 0a 0a 09 09 09 54 63 6c 5f 44 69 63  = 0;.....Tcl_Dic
33d0: 74 4f 62 6a 47 65 74 28 69 6e 74 65 72 70 2c 20  tObjGet(interp, 
33e0: 61 74 74 72 73 5f 64 69 63 74 2c 20 61 74 74 72  attrs_dict, attr
33f0: 5f 6b 65 79 5f 73 69 7a 65 2c 20 26 61 74 74 72  _key_size, &attr
3400: 5f 76 61 6c 75 65 29 3b 0a 09 09 09 69 66 20 28  _value);....if (
3410: 61 74 74 72 5f 76 61 6c 75 65 20 21 3d 20 4e 55  attr_value != NU
3420: 4c 4c 29 20 7b 0a 09 09 09 09 74 63 6c 5f 72 65  LL) {.....tcl_re
3430: 74 20 3d 20 54 63 6c 5f 47 65 74 57 69 64 65 49  t = Tcl_GetWideI
3440: 6e 74 46 72 6f 6d 4f 62 6a 28 4e 55 4c 4c 2c 20  ntFromObj(NULL, 
3450: 61 74 74 72 5f 76 61 6c 75 65 2c 20 26 61 74 74  attr_value, &att
3460: 72 5f 76 61 6c 75 65 5f 77 69 64 65 29 3b 0a 09  r_value_wide);..
3470: 09 09 09 69 66 20 28 74 63 6c 5f 72 65 74 20 3d  ...if (tcl_ret =
3480: 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09 09 09  = TCL_OK) {.....
3490: 09 70 61 74 68 69 6e 66 6f 2d 3e 74 79 70 65 69  .pathinfo->typei
34a0: 6e 66 6f 2e 66 69 6c 65 2e 73 69 7a 65 20 3d 20  nfo.file.size = 
34b0: 61 74 74 72 5f 76 61 6c 75 65 5f 77 69 64 65 3b  attr_value_wide;
34c0: 0a 09 09 09 09 7d 0a 09 09 09 7d 0a 0a 09 09 09  .....}....}.....
34d0: 54 63 6c 5f 44 69 63 74 4f 62 6a 47 65 74 28 69  Tcl_DictObjGet(i
34e0: 6e 74 65 72 70 2c 20 61 74 74 72 73 5f 64 69 63  nterp, attrs_dic
34f0: 74 2c 20 61 74 74 72 5f 6b 65 79 5f 70 65 72 6d  t, attr_key_perm
3500: 73 2c 20 26 61 74 74 72 5f 76 61 6c 75 65 29 3b  s, &attr_value);
3510: 0a 09 09 09 69 66 20 28 61 74 74 72 5f 76 61 6c  ....if (attr_val
3520: 75 65 20 21 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09  ue != NULL) {...
3530: 09 09 61 74 74 72 5f 76 61 6c 75 65 5f 73 74 72  ..attr_value_str
3540: 20 3d 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67   = Tcl_GetString
3550: 28 61 74 74 72 5f 76 61 6c 75 65 29 3b 0a 09 09  (attr_value);...
3560: 09 09 69 66 20 28 61 74 74 72 5f 76 61 6c 75 65  ..if (attr_value
3570: 5f 73 74 72 5b 30 5d 20 3d 3d 20 27 78 27 29 20  _str[0] == 'x') 
3580: 7b 0a 09 09 09 09 09 70 61 74 68 69 6e 66 6f 2d  {......pathinfo-
3590: 3e 74 79 70 65 69 6e 66 6f 2e 66 69 6c 65 2e 65  >typeinfo.file.e
35a0: 78 65 63 75 74 61 62 6c 65 20 3d 20 31 3b 0a 09  xecutable = 1;..
35b0: 09 09 09 7d 0a 09 09 09 7d 0a 09 09 09 62 72 65  ...}....}....bre
35c0: 61 6b 3b 0a 09 09 63 61 73 65 20 27 73 27 3a 20  ak;...case 's': 
35d0: 2f 2a 20 73 79 6d 6c 69 6e 6b 20 2a 2f 0a 09 09  /* symlink */...
35e0: 09 70 61 74 68 69 6e 66 6f 2d 3e 74 79 70 65 20  .pathinfo->type 
35f0: 3d 20 41 50 50 46 53 5f 50 41 54 48 54 59 50 45  = APPFS_PATHTYPE
3600: 5f 53 59 4d 4c 49 4e 4b 3b 0a 09 09 09 70 61 74  _SYMLINK;....pat
3610: 68 69 6e 66 6f 2d 3e 74 79 70 65 69 6e 66 6f 2e  hinfo->typeinfo.
3620: 73 79 6d 6c 69 6e 6b 2e 73 69 7a 65 20 3d 20 30  symlink.size = 0
3630: 3b 0a 09 09 09 70 61 74 68 69 6e 66 6f 2d 3e 74  ;....pathinfo->t
3640: 79 70 65 69 6e 66 6f 2e 73 79 6d 6c 69 6e 6b 2e  ypeinfo.symlink.
3650: 73 6f 75 72 63 65 5b 30 5d 20 3d 20 27 5c 30 27  source[0] = '\0'
3660: 3b 0a 0a 09 09 09 54 63 6c 5f 44 69 63 74 4f 62  ;.....Tcl_DictOb
3670: 6a 47 65 74 28 69 6e 74 65 72 70 2c 20 61 74 74  jGet(interp, att
3680: 72 73 5f 64 69 63 74 2c 20 61 74 74 72 5f 6b 65  rs_dict, attr_ke
3690: 79 5f 73 6f 75 72 63 65 2c 20 26 61 74 74 72 5f  y_source, &attr_
36a0: 76 61 6c 75 65 29 3b 0a 09 09 09 69 66 20 28 61  value);....if (a
36b0: 74 74 72 5f 76 61 6c 75 65 20 21 3d 20 4e 55 4c  ttr_value != NUL
36c0: 4c 29 20 7b 0a 09 09 09 09 61 74 74 72 5f 76 61  L) {.....attr_va
36d0: 6c 75 65 5f 73 74 72 20 3d 20 54 63 6c 5f 47 65  lue_str = Tcl_Ge
36e0: 74 53 74 72 69 6e 67 46 72 6f 6d 4f 62 6a 28 61  tStringFromObj(a
36f0: 74 74 72 5f 76 61 6c 75 65 2c 20 26 61 74 74 72  ttr_value, &attr
3700: 5f 76 61 6c 75 65 5f 69 6e 74 29 3b 20 0a 0a 09  _value_int); ...
3710: 09 09 09 69 66 20 28 28 61 74 74 72 5f 76 61 6c  ...if ((attr_val
3720: 75 65 5f 69 6e 74 20 2b 20 31 29 20 3c 3d 20 73  ue_int + 1) <= s
3730: 69 7a 65 6f 66 28 70 61 74 68 69 6e 66 6f 2d 3e  izeof(pathinfo->
3740: 74 79 70 65 69 6e 66 6f 2e 73 79 6d 6c 69 6e 6b  typeinfo.symlink
3750: 2e 73 6f 75 72 63 65 29 29 20 7b 0a 09 09 09 09  .source)) {.....
3760: 09 70 61 74 68 69 6e 66 6f 2d 3e 74 79 70 65 69  .pathinfo->typei
3770: 6e 66 6f 2e 73 79 6d 6c 69 6e 6b 2e 73 69 7a 65  nfo.symlink.size
3780: 20 3d 20 61 74 74 72 5f 76 61 6c 75 65 5f 69 6e   = attr_value_in
3790: 74 3b 0a 09 09 09 09 09 70 61 74 68 69 6e 66 6f  t;......pathinfo
37a0: 2d 3e 74 79 70 65 69 6e 66 6f 2e 73 79 6d 6c 69  ->typeinfo.symli
37b0: 6e 6b 2e 73 6f 75 72 63 65 5b 61 74 74 72 5f 76  nk.source[attr_v
37c0: 61 6c 75 65 5f 69 6e 74 5d 20 3d 20 27 5c 30 27  alue_int] = '\0'
37d0: 3b 0a 0a 09 09 09 09 09 6d 65 6d 63 70 79 28 70  ;.......memcpy(p
37e0: 61 74 68 69 6e 66 6f 2d 3e 74 79 70 65 69 6e 66  athinfo->typeinf
37f0: 6f 2e 73 79 6d 6c 69 6e 6b 2e 73 6f 75 72 63 65  o.symlink.source
3800: 2c 20 61 74 74 72 5f 76 61 6c 75 65 5f 73 74 72  , attr_value_str
3810: 2c 20 61 74 74 72 5f 76 61 6c 75 65 5f 69 6e 74  , attr_value_int
3820: 29 3b 0a 09 09 09 09 7d 0a 09 09 09 7d 0a 09 09  );.....}....}...
3830: 09 62 72 65 61 6b 3b 0a 09 09 63 61 73 65 20 27  .break;...case '
3840: 46 27 3a 20 2f 2a 20 70 69 70 65 2f 66 69 66 6f  F': /* pipe/fifo
3850: 20 2a 2f 0a 09 09 09 70 61 74 68 69 6e 66 6f 2d   */....pathinfo-
3860: 3e 74 79 70 65 20 3d 20 41 50 50 46 53 5f 50 41  >type = APPFS_PA
3870: 54 48 54 59 50 45 5f 46 49 46 4f 3b 0a 09 09 09  THTYPE_FIFO;....
3880: 62 72 65 61 6b 3b 0a 09 09 63 61 73 65 20 27 53  break;...case 'S
3890: 27 3a 20 2f 2a 20 55 4e 49 58 20 64 6f 6d 61 69  ': /* UNIX domai
38a0: 6e 20 73 6f 63 6b 65 74 20 2a 2f 0a 09 09 09 70  n socket */....p
38b0: 61 74 68 69 6e 66 6f 2d 3e 74 79 70 65 20 3d 20  athinfo->type = 
38c0: 41 50 50 46 53 5f 50 41 54 48 54 59 50 45 5f 53  APPFS_PATHTYPE_S
38d0: 4f 43 4b 45 54 3b 0a 09 09 09 62 72 65 61 6b 3b  OCKET;....break;
38e0: 0a 09 09 64 65 66 61 75 6c 74 3a 0a 09 09 09 72  ...default:....r
38f0: 65 74 75 72 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a  eturn(-EIO);..}.
3900: 0a 09 54 63 6c 5f 44 69 63 74 4f 62 6a 47 65 74  ..Tcl_DictObjGet
3910: 28 69 6e 74 65 72 70 2c 20 61 74 74 72 73 5f 64  (interp, attrs_d
3920: 69 63 74 2c 20 61 74 74 72 5f 6b 65 79 5f 70 61  ict, attr_key_pa
3930: 63 6b 61 67 65 64 2c 20 26 61 74 74 72 5f 76 61  ckaged, &attr_va
3940: 6c 75 65 29 3b 0a 09 69 66 20 28 61 74 74 72 5f  lue);..if (attr_
3950: 76 61 6c 75 65 20 21 3d 20 4e 55 4c 4c 29 20 7b  value != NULL) {
3960: 0a 09 09 70 61 74 68 69 6e 66 6f 2d 3e 70 61 63  ...pathinfo->pac
3970: 6b 61 67 65 64 20 3d 20 31 3b 0a 09 7d 0a 0a 09  kaged = 1;..}...
3980: 54 63 6c 5f 44 69 63 74 4f 62 6a 47 65 74 28 69  Tcl_DictObjGet(i
3990: 6e 74 65 72 70 2c 20 61 74 74 72 73 5f 64 69 63  nterp, attrs_dic
39a0: 74 2c 20 61 74 74 72 5f 6b 65 79 5f 74 69 6d 65  t, attr_key_time
39b0: 2c 20 26 61 74 74 72 5f 76 61 6c 75 65 29 3b 0a  , &attr_value);.
39c0: 09 69 66 20 28 61 74 74 72 5f 76 61 6c 75 65 20  .if (attr_value 
39d0: 21 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 74 63 6c  != NULL) {...tcl
39e0: 5f 72 65 74 20 3d 20 54 63 6c 5f 47 65 74 57 69  _ret = Tcl_GetWi
39f0: 64 65 49 6e 74 46 72 6f 6d 4f 62 6a 28 4e 55 4c  deIntFromObj(NUL
3a00: 4c 2c 20 61 74 74 72 5f 76 61 6c 75 65 2c 20 26  L, attr_value, &
3a10: 61 74 74 72 5f 76 61 6c 75 65 5f 77 69 64 65 29  attr_value_wide)
3a20: 3b 0a 09 09 69 66 20 28 74 63 6c 5f 72 65 74 20  ;...if (tcl_ret 
3a30: 3d 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09 09  == TCL_OK) {....
3a40: 70 61 74 68 69 6e 66 6f 2d 3e 74 69 6d 65 20 3d  pathinfo->time =
3a50: 20 61 74 74 72 5f 76 61 6c 75 65 5f 77 69 64 65   attr_value_wide
3a60: 3b 0a 09 09 7d 0a 09 7d 20 65 6c 73 65 20 7b 0a  ;...}..} else {.
3a70: 09 09 70 61 74 68 69 6e 66 6f 2d 3e 74 69 6d 65  ..pathinfo->time
3a80: 20 3d 20 30 3b 0a 09 7d 0a 0a 09 72 65 74 75 72   = 0;..}...retur
3a90: 6e 28 30 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20  n(0);.}..static 
3aa0: 63 68 61 72 20 2a 61 70 70 66 73 5f 70 72 65 70  char *appfs_prep
3ab0: 61 72 65 5f 74 6f 5f 63 72 65 61 74 65 28 63 6f  are_to_create(co
3ac0: 6e 73 74 20 63 68 61 72 20 2a 70 61 74 68 29 20  nst char *path) 
3ad0: 7b 0a 09 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69  {..Tcl_Interp *i
3ae0: 6e 74 65 72 70 3b 0a 09 63 6f 6e 73 74 20 63 68  nterp;..const ch
3af0: 61 72 20 2a 72 65 61 6c 5f 70 61 74 68 3b 0a 09  ar *real_path;..
3b00: 69 6e 74 20 74 63 6c 5f 72 65 74 3b 0a 0a 09 69  int tcl_ret;...i
3b10: 6e 74 65 72 70 20 3d 20 61 70 70 66 73 5f 54 63  nterp = appfs_Tc
3b20: 6c 49 6e 74 65 72 70 28 29 3b 0a 09 69 66 20 28  lInterp();..if (
3b30: 69 6e 74 65 72 70 20 3d 3d 20 4e 55 4c 4c 29 20  interp == NULL) 
3b40: 7b 0a 09 09 72 65 74 75 72 6e 28 4e 55 4c 4c 29  {...return(NULL)
3b50: 3b 0a 09 7d 0a 0a 09 74 63 6c 5f 72 65 74 20 3d  ;..}...tcl_ret =
3b60: 20 61 70 70 66 73 5f 54 63 6c 5f 45 76 61 6c 28   appfs_Tcl_Eval(
3b70: 69 6e 74 65 72 70 2c 20 32 2c 20 22 3a 3a 61 70  interp, 2, "::ap
3b80: 70 66 73 3a 3a 70 72 65 70 61 72 65 5f 74 6f 5f  pfs::prepare_to_
3b90: 63 72 65 61 74 65 22 2c 20 70 61 74 68 29 3b 0a  create", path);.
3ba0: 09 69 66 20 28 74 63 6c 5f 72 65 74 20 21 3d 20  .if (tcl_ret != 
3bb0: 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09 41 50 50 46  TCL_OK) {...APPF
3bc0: 53 5f 44 45 42 55 47 28 22 3a 3a 61 70 70 66 73  S_DEBUG("::appfs
3bd0: 3a 3a 70 72 65 70 61 72 65 5f 74 6f 5f 63 72 65  ::prepare_to_cre
3be0: 61 74 65 28 25 73 29 20 66 61 69 6c 65 64 2e 22  ate(%s) failed."
3bf0: 2c 20 70 61 74 68 29 3b 0a 09 09 41 50 50 46 53  , path);...APPFS
3c00: 5f 44 45 42 55 47 28 22 54 63 6c 20 45 72 72 6f  _DEBUG("Tcl Erro
3c10: 72 20 69 73 3a 20 25 73 22 2c 20 54 63 6c 5f 47  r is: %s", Tcl_G
3c20: 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69  etStringResult(i
3c30: 6e 74 65 72 70 29 29 3b 0a 0a 09 09 72 65 74 75  nterp));....retu
3c40: 72 6e 28 4e 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 72  rn(NULL);..}...r
3c50: 65 61 6c 5f 70 61 74 68 20 3d 20 54 63 6c 5f 47  eal_path = Tcl_G
3c60: 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69  etStringResult(i
3c70: 6e 74 65 72 70 29 3b 0a 09 69 66 20 28 72 65 61  nterp);..if (rea
3c80: 6c 5f 70 61 74 68 20 3d 3d 20 4e 55 4c 4c 29 20  l_path == NULL) 
3c90: 7b 0a 09 09 72 65 74 75 72 6e 28 4e 55 4c 4c 29  {...return(NULL)
3ca0: 3b 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 28 73 74  ;..}...return(st
3cb0: 72 64 75 70 28 72 65 61 6c 5f 70 61 74 68 29 29  rdup(real_path))
3cc0: 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 63 68 61 72  ;.}..static char
3cd0: 20 2a 61 70 70 66 73 5f 6c 6f 63 61 6c 70 61 74   *appfs_localpat
3ce0: 68 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 70 61  h(const char *pa
3cf0: 74 68 29 20 7b 0a 09 54 63 6c 5f 49 6e 74 65 72  th) {..Tcl_Inter
3d00: 70 20 2a 69 6e 74 65 72 70 3b 0a 09 63 6f 6e 73  p *interp;..cons
3d10: 74 20 63 68 61 72 20 2a 72 65 61 6c 5f 70 61 74  t char *real_pat
3d20: 68 3b 0a 09 69 6e 74 20 74 63 6c 5f 72 65 74 3b  h;..int tcl_ret;
3d30: 0a 0a 09 69 6e 74 65 72 70 20 3d 20 61 70 70 66  ...interp = appf
3d40: 73 5f 54 63 6c 49 6e 74 65 72 70 28 29 3b 0a 09  s_TclInterp();..
3d50: 69 66 20 28 69 6e 74 65 72 70 20 3d 3d 20 4e 55  if (interp == NU
3d60: 4c 4c 29 20 7b 0a 09 09 72 65 74 75 72 6e 28 4e  LL) {...return(N
3d70: 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 74 63 6c 5f 72  ULL);..}...tcl_r
3d80: 65 74 20 3d 20 61 70 70 66 73 5f 54 63 6c 5f 45  et = appfs_Tcl_E
3d90: 76 61 6c 28 69 6e 74 65 72 70 2c 20 32 2c 20 22  val(interp, 2, "
3da0: 3a 3a 61 70 70 66 73 3a 3a 6c 6f 63 61 6c 70 61  ::appfs::localpa
3db0: 74 68 22 2c 20 70 61 74 68 29 3b 0a 09 69 66 20  th", path);..if 
3dc0: 28 74 63 6c 5f 72 65 74 20 21 3d 20 54 43 4c 5f  (tcl_ret != TCL_
3dd0: 4f 4b 29 20 7b 0a 09 09 41 50 50 46 53 5f 44 45  OK) {...APPFS_DE
3de0: 42 55 47 28 22 3a 3a 61 70 70 66 73 3a 3a 6c 6f  BUG("::appfs::lo
3df0: 63 61 6c 70 61 74 68 28 25 73 29 20 66 61 69 6c  calpath(%s) fail
3e00: 65 64 2e 22 2c 20 70 61 74 68 29 3b 0a 09 09 41  ed.", path);...A
3e10: 50 50 46 53 5f 44 45 42 55 47 28 22 54 63 6c 20  PPFS_DEBUG("Tcl 
3e20: 45 72 72 6f 72 20 69 73 3a 20 25 73 22 2c 20 54  Error is: %s", T
3e30: 63 6c 5f 47 65 74 53 74 72 69 6e 67 52 65 73 75  cl_GetStringResu
3e40: 6c 74 28 69 6e 74 65 72 70 29 29 3b 0a 0a 09 09  lt(interp));....
3e50: 72 65 74 75 72 6e 28 4e 55 4c 4c 29 3b 0a 09 7d  return(NULL);..}
3e60: 0a 0a 09 72 65 61 6c 5f 70 61 74 68 20 3d 20 54  ...real_path = T
3e70: 63 6c 5f 47 65 74 53 74 72 69 6e 67 52 65 73 75  cl_GetStringResu
3e80: 6c 74 28 69 6e 74 65 72 70 29 3b 0a 09 69 66 20  lt(interp);..if 
3e90: 28 72 65 61 6c 5f 70 61 74 68 20 3d 3d 20 4e 55  (real_path == NU
3ea0: 4c 4c 29 20 7b 0a 09 09 72 65 74 75 72 6e 28 4e  LL) {...return(N
3eb0: 55 4c 4c 29 3b 0a 09 7d 0a 0a 09 72 65 74 75 72  ULL);..}...retur
3ec0: 6e 28 73 74 72 64 75 70 28 72 65 61 6c 5f 70 61  n(strdup(real_pa
3ed0: 74 68 29 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20  th));.}..static 
3ee0: 69 6e 74 20 61 70 70 66 73 5f 66 75 73 65 5f 72  int appfs_fuse_r
3ef0: 65 61 64 6c 69 6e 6b 28 63 6f 6e 73 74 20 63 68  eadlink(const ch
3f00: 61 72 20 2a 70 61 74 68 2c 20 63 68 61 72 20 2a  ar *path, char *
3f10: 62 75 66 2c 20 73 69 7a 65 5f 74 20 73 69 7a 65  buf, size_t size
3f20: 29 20 7b 0a 09 73 74 72 75 63 74 20 61 70 70 66  ) {..struct appf
3f30: 73 5f 70 61 74 68 69 6e 66 6f 20 70 61 74 68 69  s_pathinfo pathi
3f40: 6e 66 6f 3b 0a 09 69 6e 74 20 72 65 74 76 61 6c  nfo;..int retval
3f50: 20 3d 20 30 3b 0a 0a 09 41 50 50 46 53 5f 44 45   = 0;...APPFS_DE
3f60: 42 55 47 28 22 45 6e 74 65 72 20 28 70 61 74 68  BUG("Enter (path
3f70: 20 3d 20 25 73 2c 20 2e 2e 2e 29 22 2c 20 70 61   = %s, ...)", pa
3f80: 74 68 29 3b 0a 0a 09 70 61 74 68 69 6e 66 6f 2e  th);...pathinfo.
3f90: 74 79 70 65 20 3d 20 41 50 50 46 53 5f 50 41 54  type = APPFS_PAT
3fa0: 48 54 59 50 45 5f 49 4e 56 41 4c 49 44 3b 0a 0a  HTYPE_INVALID;..
3fb0: 09 72 65 74 76 61 6c 20 3d 20 61 70 70 66 73 5f  .retval = appfs_
3fc0: 67 65 74 5f 70 61 74 68 5f 69 6e 66 6f 28 70 61  get_path_info(pa
3fd0: 74 68 2c 20 26 70 61 74 68 69 6e 66 6f 29 3b 0a  th, &pathinfo);.
3fe0: 09 69 66 20 28 72 65 74 76 61 6c 20 21 3d 20 30  .if (retval != 0
3ff0: 29 20 7b 0a 09 09 72 65 74 75 72 6e 28 72 65 74  ) {...return(ret
4000: 76 61 6c 29 3b 0a 09 7d 0a 0a 09 69 66 20 28 70  val);..}...if (p
4010: 61 74 68 69 6e 66 6f 2e 74 79 70 65 20 21 3d 20  athinfo.type != 
4020: 41 50 50 46 53 5f 50 41 54 48 54 59 50 45 5f 53  APPFS_PATHTYPE_S
4030: 59 4d 4c 49 4e 4b 29 20 7b 0a 09 09 72 65 74 75  YMLINK) {...retu
4040: 72 6e 28 2d 45 49 4e 56 41 4c 29 3b 0a 09 7d 0a  rn(-EINVAL);..}.
4050: 0a 09 69 66 20 28 28 73 74 72 6c 65 6e 28 70 61  ..if ((strlen(pa
4060: 74 68 69 6e 66 6f 2e 74 79 70 65 69 6e 66 6f 2e  thinfo.typeinfo.
4070: 73 79 6d 6c 69 6e 6b 2e 73 6f 75 72 63 65 29 20  symlink.source) 
4080: 2b 20 31 29 20 3e 20 73 69 7a 65 29 20 7b 0a 09  + 1) > size) {..
4090: 09 72 65 74 75 72 6e 28 2d 45 4e 41 4d 45 54 4f  .return(-ENAMETO
40a0: 4f 4c 4f 4e 47 29 3b 0a 09 7d 0a 0a 09 6d 65 6d  OLONG);..}...mem
40b0: 63 70 79 28 62 75 66 2c 20 70 61 74 68 69 6e 66  cpy(buf, pathinf
40c0: 6f 2e 74 79 70 65 69 6e 66 6f 2e 73 79 6d 6c 69  o.typeinfo.symli
40d0: 6e 6b 2e 73 6f 75 72 63 65 2c 20 73 74 72 6c 65  nk.source, strle
40e0: 6e 28 70 61 74 68 69 6e 66 6f 2e 74 79 70 65 69  n(pathinfo.typei
40f0: 6e 66 6f 2e 73 79 6d 6c 69 6e 6b 2e 73 6f 75 72  nfo.symlink.sour
4100: 63 65 29 20 2b 20 31 29 3b 0a 0a 09 72 65 74 75  ce) + 1);...retu
4110: 72 6e 28 30 29 3b 0a 7d 0a 0a 73 74 61 74 69 63  rn(0);.}..static
4120: 20 69 6e 74 20 61 70 70 66 73 5f 66 75 73 65 5f   int appfs_fuse_
4130: 67 65 74 61 74 74 72 28 63 6f 6e 73 74 20 63 68  getattr(const ch
4140: 61 72 20 2a 70 61 74 68 2c 20 73 74 72 75 63 74  ar *path, struct
4150: 20 73 74 61 74 20 2a 73 74 62 75 66 29 20 7b 0a   stat *stbuf) {.
4160: 09 73 74 72 75 63 74 20 61 70 70 66 73 5f 70 61  .struct appfs_pa
4170: 74 68 69 6e 66 6f 20 70 61 74 68 69 6e 66 6f 3b  thinfo pathinfo;
4180: 0a 09 69 6e 74 20 72 65 74 76 61 6c 3b 0a 0a 09  ..int retval;...
4190: 72 65 74 76 61 6c 20 3d 20 30 3b 0a 0a 09 41 50  retval = 0;...AP
41a0: 50 46 53 5f 44 45 42 55 47 28 22 45 6e 74 65 72  PFS_DEBUG("Enter
41b0: 20 28 70 61 74 68 20 3d 20 25 73 2c 20 2e 2e 2e   (path = %s, ...
41c0: 29 22 2c 20 70 61 74 68 29 3b 0a 0a 09 70 61 74  )", path);...pat
41d0: 68 69 6e 66 6f 2e 74 79 70 65 20 3d 20 41 50 50  hinfo.type = APP
41e0: 46 53 5f 50 41 54 48 54 59 50 45 5f 49 4e 56 41  FS_PATHTYPE_INVA
41f0: 4c 49 44 3b 0a 0a 09 72 65 74 76 61 6c 20 3d 20  LID;...retval = 
4200: 61 70 70 66 73 5f 67 65 74 5f 70 61 74 68 5f 69  appfs_get_path_i
4210: 6e 66 6f 28 70 61 74 68 2c 20 26 70 61 74 68 69  nfo(path, &pathi
4220: 6e 66 6f 29 3b 0a 09 69 66 20 28 72 65 74 76 61  nfo);..if (retva
4230: 6c 20 21 3d 20 30 29 20 7b 0a 09 09 72 65 74 75  l != 0) {...retu
4240: 72 6e 28 72 65 74 76 61 6c 29 3b 0a 09 7d 0a 0a  rn(retval);..}..
4250: 09 6d 65 6d 73 65 74 28 73 74 62 75 66 2c 20 30  .memset(stbuf, 0
4260: 2c 20 73 69 7a 65 6f 66 28 73 74 72 75 63 74 20  , sizeof(struct 
4270: 73 74 61 74 29 29 3b 0a 0a 09 73 74 62 75 66 2d  stat));...stbuf-
4280: 3e 73 74 5f 6d 74 69 6d 65 20 3d 20 70 61 74 68  >st_mtime = path
4290: 69 6e 66 6f 2e 74 69 6d 65 3b 0a 09 73 74 62 75  info.time;..stbu
42a0: 66 2d 3e 73 74 5f 63 74 69 6d 65 20 3d 20 70 61  f->st_ctime = pa
42b0: 74 68 69 6e 66 6f 2e 74 69 6d 65 3b 0a 09 73 74  thinfo.time;..st
42c0: 62 75 66 2d 3e 73 74 5f 61 74 69 6d 65 20 3d 20  buf->st_atime = 
42d0: 70 61 74 68 69 6e 66 6f 2e 74 69 6d 65 3b 0a 09  pathinfo.time;..
42e0: 73 74 62 75 66 2d 3e 73 74 5f 69 6e 6f 20 20 20  stbuf->st_ino   
42f0: 3d 20 70 61 74 68 69 6e 66 6f 2e 69 6e 6f 64 65  = pathinfo.inode
4300: 3b 0a 09 73 74 62 75 66 2d 3e 73 74 5f 6d 6f 64  ;..stbuf->st_mod
4310: 65 20 20 3d 20 30 3b 0a 09 73 74 62 75 66 2d 3e  e  = 0;..stbuf->
4320: 73 74 5f 75 69 64 20 20 20 3d 20 61 70 70 66 73  st_uid   = appfs
4330: 5f 67 65 74 5f 66 73 75 69 64 28 29 3b 0a 09 73  _get_fsuid();..s
4340: 74 62 75 66 2d 3e 73 74 5f 67 69 64 20 20 20 3d  tbuf->st_gid   =
4350: 20 61 70 70 66 73 5f 67 65 74 5f 66 73 67 69 64   appfs_get_fsgid
4360: 28 29 3b 0a 0a 09 73 77 69 74 63 68 20 28 70 61  ();...switch (pa
4370: 74 68 69 6e 66 6f 2e 74 79 70 65 29 20 7b 0a 09  thinfo.type) {..
4380: 09 63 61 73 65 20 41 50 50 46 53 5f 50 41 54 48  .case APPFS_PATH
4390: 54 59 50 45 5f 44 49 52 45 43 54 4f 52 59 3a 0a  TYPE_DIRECTORY:.
43a0: 09 09 09 73 74 62 75 66 2d 3e 73 74 5f 6d 6f 64  ...stbuf->st_mod
43b0: 65 20 3d 20 53 5f 49 46 44 49 52 20 7c 20 30 35  e = S_IFDIR | 05
43c0: 35 35 3b 0a 09 09 09 73 74 62 75 66 2d 3e 73 74  55;....stbuf->st
43d0: 5f 6e 6c 69 6e 6b 20 3d 20 32 20 2b 20 70 61 74  _nlink = 2 + pat
43e0: 68 69 6e 66 6f 2e 74 79 70 65 69 6e 66 6f 2e 64  hinfo.typeinfo.d
43f0: 69 72 2e 63 68 69 6c 64 63 6f 75 6e 74 3b 0a 09  ir.childcount;..
4400: 09 09 62 72 65 61 6b 3b 0a 09 09 63 61 73 65 20  ..break;...case 
4410: 41 50 50 46 53 5f 50 41 54 48 54 59 50 45 5f 46  APPFS_PATHTYPE_F
4420: 49 4c 45 3a 0a 09 09 09 69 66 20 28 70 61 74 68  ILE:....if (path
4430: 69 6e 66 6f 2e 74 79 70 65 69 6e 66 6f 2e 66 69  info.typeinfo.fi
4440: 6c 65 2e 65 78 65 63 75 74 61 62 6c 65 29 20 7b  le.executable) {
4450: 0a 09 09 09 09 73 74 62 75 66 2d 3e 73 74 5f 6d  .....stbuf->st_m
4460: 6f 64 65 20 3d 20 53 5f 49 46 52 45 47 20 7c 20  ode = S_IFREG | 
4470: 30 35 35 35 3b 0a 09 09 09 7d 20 65 6c 73 65 20  0555;....} else 
4480: 7b 0a 09 09 09 09 73 74 62 75 66 2d 3e 73 74 5f  {.....stbuf->st_
4490: 6d 6f 64 65 20 3d 20 53 5f 49 46 52 45 47 20 7c  mode = S_IFREG |
44a0: 20 30 34 34 34 3b 0a 09 09 09 7d 0a 0a 09 09 09   0444;....}.....
44b0: 73 74 62 75 66 2d 3e 73 74 5f 6e 6c 69 6e 6b 20  stbuf->st_nlink 
44c0: 3d 20 31 3b 0a 09 09 09 73 74 62 75 66 2d 3e 73  = 1;....stbuf->s
44d0: 74 5f 73 69 7a 65 20 3d 20 70 61 74 68 69 6e 66  t_size = pathinf
44e0: 6f 2e 74 79 70 65 69 6e 66 6f 2e 66 69 6c 65 2e  o.typeinfo.file.
44f0: 73 69 7a 65 3b 0a 09 09 09 62 72 65 61 6b 3b 0a  size;....break;.
4500: 09 09 63 61 73 65 20 41 50 50 46 53 5f 50 41 54  ..case APPFS_PAT
4510: 48 54 59 50 45 5f 53 59 4d 4c 49 4e 4b 3a 0a 09  HTYPE_SYMLINK:..
4520: 09 09 73 74 62 75 66 2d 3e 73 74 5f 6d 6f 64 65  ..stbuf->st_mode
4530: 20 3d 20 53 5f 49 46 4c 4e 4b 20 7c 20 30 35 35   = S_IFLNK | 055
4540: 35 3b 0a 09 09 09 73 74 62 75 66 2d 3e 73 74 5f  5;....stbuf->st_
4550: 6e 6c 69 6e 6b 20 3d 20 31 3b 0a 09 09 09 73 74  nlink = 1;....st
4560: 62 75 66 2d 3e 73 74 5f 73 69 7a 65 20 3d 20 70  buf->st_size = p
4570: 61 74 68 69 6e 66 6f 2e 74 79 70 65 69 6e 66 6f  athinfo.typeinfo
4580: 2e 73 79 6d 6c 69 6e 6b 2e 73 69 7a 65 3b 0a 09  .symlink.size;..
4590: 09 09 62 72 65 61 6b 3b 0a 09 09 63 61 73 65 20  ..break;...case 
45a0: 41 50 50 46 53 5f 50 41 54 48 54 59 50 45 5f 53  APPFS_PATHTYPE_S
45b0: 4f 43 4b 45 54 3a 0a 09 09 09 73 74 62 75 66 2d  OCKET:....stbuf-
45c0: 3e 73 74 5f 6d 6f 64 65 20 3d 20 53 5f 49 46 53  >st_mode = S_IFS
45d0: 4f 43 4b 20 7c 20 30 35 35 35 3b 0a 09 09 09 73  OCK | 0555;....s
45e0: 74 62 75 66 2d 3e 73 74 5f 6e 6c 69 6e 6b 20 3d  tbuf->st_nlink =
45f0: 20 31 3b 0a 09 09 09 73 74 62 75 66 2d 3e 73 74   1;....stbuf->st
4600: 5f 73 69 7a 65 20 3d 20 30 3b 0a 09 09 09 62 72  _size = 0;....br
4610: 65 61 6b 3b 0a 09 09 63 61 73 65 20 41 50 50 46  eak;...case APPF
4620: 53 5f 50 41 54 48 54 59 50 45 5f 46 49 46 4f 3a  S_PATHTYPE_FIFO:
4630: 0a 09 09 09 73 74 62 75 66 2d 3e 73 74 5f 6d 6f  ....stbuf->st_mo
4640: 64 65 20 3d 20 53 5f 49 46 49 46 4f 20 7c 20 30  de = S_IFIFO | 0
4650: 35 35 35 3b 0a 09 09 09 73 74 62 75 66 2d 3e 73  555;....stbuf->s
4660: 74 5f 6e 6c 69 6e 6b 20 3d 20 31 3b 0a 09 09 09  t_nlink = 1;....
4670: 73 74 62 75 66 2d 3e 73 74 5f 73 69 7a 65 20 3d  stbuf->st_size =
4680: 20 30 3b 0a 09 09 09 62 72 65 61 6b 3b 0a 09 09   0;....break;...
4690: 63 61 73 65 20 41 50 50 46 53 5f 50 41 54 48 54  case APPFS_PATHT
46a0: 59 50 45 5f 49 4e 56 41 4c 49 44 3a 0a 09 09 09  YPE_INVALID:....
46b0: 72 65 74 76 61 6c 20 3d 20 2d 45 4e 4f 45 4e 54  retval = -ENOENT
46c0: 3b 0a 0a 09 09 09 62 72 65 61 6b 3b 0a 09 7d 0a  ;.....break;..}.
46d0: 0a 09 69 66 20 28 70 61 74 68 69 6e 66 6f 2e 70  ..if (pathinfo.p
46e0: 61 63 6b 61 67 65 64 29 20 7b 0a 09 09 73 74 62  ackaged) {...stb
46f0: 75 66 2d 3e 73 74 5f 6d 6f 64 65 20 7c 3d 20 30  uf->st_mode |= 0
4700: 32 32 32 3b 0a 09 7d 0a 0a 09 72 65 74 75 72 6e  222;..}...return
4710: 28 72 65 74 76 61 6c 29 3b 0a 7d 0a 0a 73 74 61  (retval);.}..sta
4720: 74 69 63 20 69 6e 74 20 61 70 70 66 73 5f 66 75  tic int appfs_fu
4730: 73 65 5f 72 65 61 64 64 69 72 28 63 6f 6e 73 74  se_readdir(const
4740: 20 63 68 61 72 20 2a 70 61 74 68 2c 20 76 6f 69   char *path, voi
4750: 64 20 2a 62 75 66 2c 20 66 75 73 65 5f 66 69 6c  d *buf, fuse_fil
4760: 6c 5f 64 69 72 5f 74 20 66 69 6c 6c 65 72 2c 20  l_dir_t filler, 
4770: 6f 66 66 5f 74 20 6f 66 66 73 65 74 2c 20 73 74  off_t offset, st
4780: 72 75 63 74 20 66 75 73 65 5f 66 69 6c 65 5f 69  ruct fuse_file_i
4790: 6e 66 6f 20 2a 66 69 29 20 7b 0a 09 54 63 6c 5f  nfo *fi) {..Tcl_
47a0: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 3b 0a  Interp *interp;.
47b0: 09 54 63 6c 5f 4f 62 6a 20 2a 2a 63 68 69 6c 64  .Tcl_Obj **child
47c0: 72 65 6e 3b 0a 09 69 6e 74 20 63 68 69 6c 64 72  ren;..int childr
47d0: 65 6e 5f 63 6f 75 6e 74 2c 20 69 64 78 3b 0a 09  en_count, idx;..
47e0: 69 6e 74 20 74 63 6c 5f 72 65 74 3b 0a 0a 09 41  int tcl_ret;...A
47f0: 50 50 46 53 5f 44 45 42 55 47 28 22 45 6e 74 65  PPFS_DEBUG("Ente
4800: 72 20 28 70 61 74 68 20 3d 20 25 73 2c 20 2e 2e  r (path = %s, ..
4810: 2e 29 22 2c 20 70 61 74 68 29 3b 0a 0a 09 69 6e  .)", path);...in
4820: 74 65 72 70 20 3d 20 61 70 70 66 73 5f 54 63 6c  terp = appfs_Tcl
4830: 49 6e 74 65 72 70 28 29 3b 0a 09 69 66 20 28 69  Interp();..if (i
4840: 6e 74 65 72 70 20 3d 3d 20 4e 55 4c 4c 29 20 7b  nterp == NULL) {
4850: 0a 09 09 72 65 74 75 72 6e 28 30 29 3b 0a 09 7d  ...return(0);..}
4860: 0a 0a 09 66 69 6c 6c 65 72 28 62 75 66 2c 20 22  ...filler(buf, "
4870: 2e 22 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 09 66  .", NULL, 0);..f
4880: 69 6c 6c 65 72 28 62 75 66 2c 20 22 2e 2e 22 2c  iller(buf, "..",
4890: 20 4e 55 4c 4c 2c 20 30 29 3b 0a 0a 09 61 70 70   NULL, 0);...app
48a0: 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65 72  fs_simulate_user
48b0: 5f 66 73 5f 65 6e 74 65 72 28 29 3b 0a 0a 09 74  _fs_enter();...t
48c0: 63 6c 5f 72 65 74 20 3d 20 61 70 70 66 73 5f 54  cl_ret = appfs_T
48d0: 63 6c 5f 45 76 61 6c 28 69 6e 74 65 72 70 2c 20  cl_Eval(interp, 
48e0: 32 2c 20 22 3a 3a 61 70 70 66 73 3a 3a 67 65 74  2, "::appfs::get
48f0: 63 68 69 6c 64 72 65 6e 22 2c 20 70 61 74 68 29  children", path)
4900: 3b 0a 0a 09 61 70 70 66 73 5f 73 69 6d 75 6c 61  ;...appfs_simula
4910: 74 65 5f 75 73 65 72 5f 66 73 5f 6c 65 61 76 65  te_user_fs_leave
4920: 28 29 3b 0a 0a 09 69 66 20 28 74 63 6c 5f 72 65  ();...if (tcl_re
4930: 74 20 21 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09  t != TCL_OK) {..
4940: 09 41 50 50 46 53 5f 44 45 42 55 47 28 22 3a 3a  .APPFS_DEBUG("::
4950: 61 70 70 66 73 3a 3a 67 65 74 63 68 69 6c 64 72  appfs::getchildr
4960: 65 6e 28 25 73 29 20 66 61 69 6c 65 64 2e 22 2c  en(%s) failed.",
4970: 20 70 61 74 68 29 3b 0a 09 09 41 50 50 46 53 5f   path);...APPFS_
4980: 44 45 42 55 47 28 22 54 63 6c 20 45 72 72 6f 72  DEBUG("Tcl Error
4990: 20 69 73 3a 20 25 73 22 2c 20 54 63 6c 5f 47 65   is: %s", Tcl_Ge
49a0: 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69 6e  tStringResult(in
49b0: 74 65 72 70 29 29 3b 0a 0a 09 09 72 65 74 75 72  terp));....retur
49c0: 6e 28 30 29 3b 0a 09 7d 0a 0a 09 74 63 6c 5f 72  n(0);..}...tcl_r
49d0: 65 74 20 3d 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  et = Tcl_ListObj
49e0: 47 65 74 45 6c 65 6d 65 6e 74 73 28 69 6e 74 65  GetElements(inte
49f0: 72 70 2c 20 54 63 6c 5f 47 65 74 4f 62 6a 52 65  rp, Tcl_GetObjRe
4a00: 73 75 6c 74 28 69 6e 74 65 72 70 29 2c 20 26 63  sult(interp), &c
4a10: 68 69 6c 64 72 65 6e 5f 63 6f 75 6e 74 2c 20 26  hildren_count, &
4a20: 63 68 69 6c 64 72 65 6e 29 3b 0a 09 69 66 20 28  children);..if (
4a30: 74 63 6c 5f 72 65 74 20 21 3d 20 54 43 4c 5f 4f  tcl_ret != TCL_O
4a40: 4b 29 20 7b 0a 09 09 41 50 50 46 53 5f 44 45 42  K) {...APPFS_DEB
4a50: 55 47 28 22 50 61 72 73 69 6e 67 20 6c 69 73 74  UG("Parsing list
4a60: 20 6f 66 20 63 68 69 6c 64 72 65 6e 20 6f 6e 20   of children on 
4a70: 70 61 74 68 20 25 73 20 66 61 69 6c 65 64 2e 22  path %s failed."
4a80: 2c 20 70 61 74 68 29 3b 0a 09 09 41 50 50 46 53  , path);...APPFS
4a90: 5f 44 45 42 55 47 28 22 54 63 6c 20 45 72 72 6f  _DEBUG("Tcl Erro
4aa0: 72 20 69 73 3a 20 25 73 22 2c 20 54 63 6c 5f 47  r is: %s", Tcl_G
4ab0: 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69  etStringResult(i
4ac0: 6e 74 65 72 70 29 29 3b 0a 0a 09 09 72 65 74 75  nterp));....retu
4ad0: 72 6e 28 30 29 3b 0a 09 7d 0a 0a 09 66 6f 72 20  rn(0);..}...for 
4ae0: 28 69 64 78 20 3d 20 30 3b 20 69 64 78 20 3c 20  (idx = 0; idx < 
4af0: 63 68 69 6c 64 72 65 6e 5f 63 6f 75 6e 74 3b 20  children_count; 
4b00: 69 64 78 2b 2b 29 20 7b 0a 09 09 66 69 6c 6c 65  idx++) {...fille
4b10: 72 28 62 75 66 2c 20 54 63 6c 5f 47 65 74 53 74  r(buf, Tcl_GetSt
4b20: 72 69 6e 67 28 63 68 69 6c 64 72 65 6e 5b 69 64  ring(children[id
4b30: 78 5d 29 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 09  x]), NULL, 0);..
4b40: 7d 0a 0a 09 72 65 74 75 72 6e 28 30 29 3b 0a 7d  }...return(0);.}
4b50: 0a 0a 73 74 61 74 69 63 20 69 6e 74 20 61 70 70  ..static int app
4b60: 66 73 5f 66 75 73 65 5f 6f 70 65 6e 28 63 6f 6e  fs_fuse_open(con
4b70: 73 74 20 63 68 61 72 20 2a 70 61 74 68 2c 20 73  st char *path, s
4b80: 74 72 75 63 74 20 66 75 73 65 5f 66 69 6c 65 5f  truct fuse_file_
4b90: 69 6e 66 6f 20 2a 66 69 29 20 7b 0a 09 54 63 6c  info *fi) {..Tcl
4ba0: 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 3b  _Interp *interp;
4bb0: 0a 09 73 74 72 75 63 74 20 61 70 70 66 73 5f 70  ..struct appfs_p
4bc0: 61 74 68 69 6e 66 6f 20 70 61 74 68 69 6e 66 6f  athinfo pathinfo
4bd0: 3b 0a 09 63 6f 6e 73 74 20 63 68 61 72 20 2a 72  ;..const char *r
4be0: 65 61 6c 5f 70 61 74 68 2c 20 2a 6d 6f 64 65 3b  eal_path, *mode;
4bf0: 0a 09 69 6e 74 20 67 70 69 5f 72 65 74 2c 20 74  ..int gpi_ret, t
4c00: 63 6c 5f 72 65 74 3b 0a 09 69 6e 74 20 66 68 3b  cl_ret;..int fh;
4c10: 0a 0a 09 41 50 50 46 53 5f 44 45 42 55 47 28 22  ...APPFS_DEBUG("
4c20: 45 6e 74 65 72 20 28 70 61 74 68 20 3d 20 25 73  Enter (path = %s
4c30: 2c 20 2e 2e 2e 29 22 2c 20 70 61 74 68 29 3b 0a  , ...)", path);.
4c40: 0a 09 67 70 69 5f 72 65 74 20 3d 20 61 70 70 66  ..gpi_ret = appf
4c50: 73 5f 67 65 74 5f 70 61 74 68 5f 69 6e 66 6f 28  s_get_path_info(
4c60: 70 61 74 68 2c 20 26 70 61 74 68 69 6e 66 6f 29  path, &pathinfo)
4c70: 3b 0a 0a 09 69 66 20 28 28 66 69 2d 3e 66 6c 61  ;...if ((fi->fla
4c80: 67 73 20 26 20 28 4f 5f 57 52 4f 4e 4c 59 7c 4f  gs & (O_WRONLY|O
4c90: 5f 43 52 45 41 54 29 29 20 3d 3d 20 28 4f 5f 43  _CREAT)) == (O_C
4ca0: 52 45 41 54 7c 4f 5f 57 52 4f 4e 4c 59 29 29 20  REAT|O_WRONLY)) 
4cb0: 7b 0a 09 09 2f 2a 20 54 68 65 20 66 69 6c 65 20  {.../* The file 
4cc0: 77 69 6c 6c 20 62 65 20 63 72 65 61 74 65 64 20  will be created 
4cd0: 69 66 20 69 74 20 64 6f 65 73 20 6e 6f 74 20 65  if it does not e
4ce0: 78 69 73 74 20 2a 2f 0a 09 09 69 66 20 28 67 70  xist */...if (gp
4cf0: 69 5f 72 65 74 20 21 3d 20 30 20 26 26 20 67 70  i_ret != 0 && gp
4d00: 69 5f 72 65 74 20 21 3d 20 2d 45 4e 4f 45 4e 54  i_ret != -ENOENT
4d10: 29 20 7b 0a 09 09 09 72 65 74 75 72 6e 28 67 70  ) {....return(gp
4d20: 69 5f 72 65 74 29 3b 0a 09 09 7d 0a 0a 09 09 6d  i_ret);...}....m
4d30: 6f 64 65 20 3d 20 22 63 72 65 61 74 65 22 3b 0a  ode = "create";.
4d40: 09 7d 20 65 6c 73 65 20 7b 0a 09 09 2f 2a 20 54  .} else {.../* T
4d50: 68 65 20 66 69 6c 65 20 6d 75 73 74 20 61 6c 72  he file must alr
4d60: 65 61 64 79 20 65 78 69 73 74 20 2a 2f 0a 09 09  eady exist */...
4d70: 69 66 20 28 67 70 69 5f 72 65 74 20 21 3d 20 30  if (gpi_ret != 0
4d80: 29 20 7b 0a 09 09 09 72 65 74 75 72 6e 28 67 70  ) {....return(gp
4d90: 69 5f 72 65 74 29 3b 0a 09 09 7d 0a 0a 09 09 6d  i_ret);...}....m
4da0: 6f 64 65 20 3d 20 22 22 3b 0a 0a 09 09 69 66 20  ode = "";....if 
4db0: 28 28 66 69 2d 3e 66 6c 61 67 73 20 26 20 4f 5f  ((fi->flags & O_
4dc0: 57 52 4f 4e 4c 59 29 20 3d 3d 20 4f 5f 57 52 4f  WRONLY) == O_WRO
4dd0: 4e 4c 59 29 20 7b 0a 09 09 09 6d 6f 64 65 20 3d  NLY) {....mode =
4de0: 20 22 77 72 69 74 65 22 3b 0a 09 09 7d 0a 09 7d   "write";...}..}
4df0: 0a 0a 09 69 66 20 28 70 61 74 68 69 6e 66 6f 2e  ...if (pathinfo.
4e00: 74 79 70 65 20 3d 3d 20 41 50 50 46 53 5f 50 41  type == APPFS_PA
4e10: 54 48 54 59 50 45 5f 44 49 52 45 43 54 4f 52 59  THTYPE_DIRECTORY
4e20: 29 20 7b 0a 09 09 72 65 74 75 72 6e 28 2d 45 49  ) {...return(-EI
4e30: 53 44 49 52 29 3b 0a 09 7d 0a 0a 09 69 6e 74 65  SDIR);..}...inte
4e40: 72 70 20 3d 20 61 70 70 66 73 5f 54 63 6c 49 6e  rp = appfs_TclIn
4e50: 74 65 72 70 28 29 3b 0a 09 69 66 20 28 69 6e 74  terp();..if (int
4e60: 65 72 70 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09  erp == NULL) {..
4e70: 09 72 65 74 75 72 6e 28 2d 45 49 4f 29 3b 0a 09  .return(-EIO);..
4e80: 7d 0a 0a 09 61 70 70 66 73 5f 73 69 6d 75 6c 61  }...appfs_simula
4e90: 74 65 5f 75 73 65 72 5f 66 73 5f 65 6e 74 65 72  te_user_fs_enter
4ea0: 28 29 3b 0a 0a 09 74 63 6c 5f 72 65 74 20 3d 20  ();...tcl_ret = 
4eb0: 61 70 70 66 73 5f 54 63 6c 5f 45 76 61 6c 28 69  appfs_Tcl_Eval(i
4ec0: 6e 74 65 72 70 2c 20 33 2c 20 22 3a 3a 61 70 70  nterp, 3, "::app
4ed0: 66 73 3a 3a 6f 70 65 6e 70 61 74 68 22 2c 20 70  fs::openpath", p
4ee0: 61 74 68 2c 20 6d 6f 64 65 29 3b 0a 09 69 66 20  ath, mode);..if 
4ef0: 28 74 63 6c 5f 72 65 74 20 21 3d 20 54 43 4c 5f  (tcl_ret != TCL_
4f00: 4f 4b 29 20 7b 0a 09 09 61 70 70 66 73 5f 73 69  OK) {...appfs_si
4f10: 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f 6c  mulate_user_fs_l
4f20: 65 61 76 65 28 29 3b 0a 0a 09 09 41 50 50 46 53  eave();....APPFS
4f30: 5f 44 45 42 55 47 28 22 3a 3a 61 70 70 66 73 3a  _DEBUG("::appfs:
4f40: 3a 6f 70 65 6e 70 61 74 68 28 25 73 2c 20 25 73  :openpath(%s, %s
4f50: 29 20 66 61 69 6c 65 64 2e 22 2c 20 70 61 74 68  ) failed.", path
4f60: 2c 20 6d 6f 64 65 29 3b 0a 09 09 41 50 50 46 53  , mode);...APPFS
4f70: 5f 44 45 42 55 47 28 22 54 63 6c 20 45 72 72 6f  _DEBUG("Tcl Erro
4f80: 72 20 69 73 3a 20 25 73 22 2c 20 54 63 6c 5f 47  r is: %s", Tcl_G
4f90: 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69  etStringResult(i
4fa0: 6e 74 65 72 70 29 29 3b 0a 0a 09 09 72 65 74 75  nterp));....retu
4fb0: 72 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a 09 72  rn(-EIO);..}...r
4fc0: 65 61 6c 5f 70 61 74 68 20 3d 20 54 63 6c 5f 47  eal_path = Tcl_G
4fd0: 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69  etStringResult(i
4fe0: 6e 74 65 72 70 29 3b 0a 09 69 66 20 28 72 65 61  nterp);..if (rea
4ff0: 6c 5f 70 61 74 68 20 3d 3d 20 4e 55 4c 4c 29 20  l_path == NULL) 
5000: 7b 0a 09 09 61 70 70 66 73 5f 73 69 6d 75 6c 61  {...appfs_simula
5010: 74 65 5f 75 73 65 72 5f 66 73 5f 6c 65 61 76 65  te_user_fs_leave
5020: 28 29 3b 0a 0a 09 09 72 65 74 75 72 6e 28 2d 45  ();....return(-E
5030: 49 4f 29 3b 0a 09 7d 0a 0a 09 41 50 50 46 53 5f  IO);..}...APPFS_
5040: 44 45 42 55 47 28 22 54 72 61 6e 73 6c 61 74 65  DEBUG("Translate
5050: 64 20 72 65 71 75 65 73 74 20 74 6f 20 6f 70 65  d request to ope
5060: 6e 20 25 73 20 74 6f 20 6f 70 65 6e 69 6e 67 20  n %s to opening 
5070: 25 73 20 28 6d 6f 64 65 20 3d 20 5c 22 25 73 5c  %s (mode = \"%s\
5080: 22 29 22 2c 20 70 61 74 68 2c 20 72 65 61 6c 5f  ")", path, real_
5090: 70 61 74 68 2c 20 6d 6f 64 65 29 3b 0a 0a 09 66  path, mode);...f
50a0: 68 20 3d 20 6f 70 65 6e 28 72 65 61 6c 5f 70 61  h = open(real_pa
50b0: 74 68 2c 20 66 69 2d 3e 66 6c 61 67 73 2c 20 30  th, fi->flags, 0
50c0: 36 30 30 29 3b 0a 0a 09 61 70 70 66 73 5f 73 69  600);...appfs_si
50d0: 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f 6c  mulate_user_fs_l
50e0: 65 61 76 65 28 29 3b 0a 0a 09 69 66 20 28 66 68  eave();...if (fh
50f0: 20 3c 20 30 29 20 7b 0a 09 09 72 65 74 75 72 6e   < 0) {...return
5100: 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a 09 66 69 2d  (-EIO);..}...fi-
5110: 3e 66 68 20 3d 20 66 68 3b 0a 0a 09 72 65 74 75  >fh = fh;...retu
5120: 72 6e 28 30 29 3b 0a 7d 0a 0a 73 74 61 74 69 63  rn(0);.}..static
5130: 20 69 6e 74 20 61 70 70 66 73 5f 66 75 73 65 5f   int appfs_fuse_
5140: 63 6c 6f 73 65 28 63 6f 6e 73 74 20 63 68 61 72  close(const char
5150: 20 2a 70 61 74 68 2c 20 73 74 72 75 63 74 20 66   *path, struct f
5160: 75 73 65 5f 66 69 6c 65 5f 69 6e 66 6f 20 2a 66  use_file_info *f
5170: 69 29 20 7b 0a 09 69 6e 74 20 63 6c 6f 73 65 5f  i) {..int close_
5180: 72 65 74 3b 0a 0a 09 63 6c 6f 73 65 5f 72 65 74  ret;...close_ret
5190: 20 3d 20 63 6c 6f 73 65 28 66 69 2d 3e 66 68 29   = close(fi->fh)
51a0: 3b 0a 09 69 66 20 28 63 6c 6f 73 65 5f 72 65 74  ;..if (close_ret
51b0: 20 21 3d 20 30 29 20 7b 0a 09 09 72 65 74 75 72   != 0) {...retur
51c0: 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a 09 72 65  n(-EIO);..}...re
51d0: 74 75 72 6e 28 30 29 3b 0a 7d 0a 0a 73 74 61 74  turn(0);.}..stat
51e0: 69 63 20 69 6e 74 20 61 70 70 66 73 5f 66 75 73  ic int appfs_fus
51f0: 65 5f 72 65 61 64 28 63 6f 6e 73 74 20 63 68 61  e_read(const cha
5200: 72 20 2a 70 61 74 68 2c 20 63 68 61 72 20 2a 62  r *path, char *b
5210: 75 66 2c 20 73 69 7a 65 5f 74 20 73 69 7a 65 2c  uf, size_t size,
5220: 20 6f 66 66 5f 74 20 6f 66 66 73 65 74 2c 20 73   off_t offset, s
5230: 74 72 75 63 74 20 66 75 73 65 5f 66 69 6c 65 5f  truct fuse_file_
5240: 69 6e 66 6f 20 2a 66 69 29 20 7b 0a 09 6f 66 66  info *fi) {..off
5250: 5f 74 20 6c 73 65 65 6b 5f 72 65 74 3b 0a 09 73  _t lseek_ret;..s
5260: 73 69 7a 65 5f 74 20 72 65 61 64 5f 72 65 74 3b  size_t read_ret;
5270: 0a 0a 09 41 50 50 46 53 5f 44 45 42 55 47 28 22  ...APPFS_DEBUG("
5280: 45 6e 74 65 72 20 28 70 61 74 68 20 3d 20 25 73  Enter (path = %s
5290: 2c 20 2e 2e 2e 29 22 2c 20 70 61 74 68 29 3b 0a  , ...)", path);.
52a0: 0a 09 6c 73 65 65 6b 5f 72 65 74 20 3d 20 6c 73  ..lseek_ret = ls
52b0: 65 65 6b 28 66 69 2d 3e 66 68 2c 20 6f 66 66 73  eek(fi->fh, offs
52c0: 65 74 2c 20 53 45 45 4b 5f 53 45 54 29 3b 0a 09  et, SEEK_SET);..
52d0: 69 66 20 28 6c 73 65 65 6b 5f 72 65 74 20 21 3d  if (lseek_ret !=
52e0: 20 6f 66 66 73 65 74 29 20 7b 0a 09 09 72 65 74   offset) {...ret
52f0: 75 72 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a 09  urn(-EIO);..}...
5300: 72 65 61 64 5f 72 65 74 20 3d 20 72 65 61 64 28  read_ret = read(
5310: 66 69 2d 3e 66 68 2c 20 62 75 66 2c 20 73 69 7a  fi->fh, buf, siz
5320: 65 29 3b 0a 0a 09 72 65 74 75 72 6e 28 72 65 61  e);...return(rea
5330: 64 5f 72 65 74 29 3b 0a 7d 0a 0a 73 74 61 74 69  d_ret);.}..stati
5340: 63 20 69 6e 74 20 61 70 70 66 73 5f 66 75 73 65  c int appfs_fuse
5350: 5f 77 72 69 74 65 28 63 6f 6e 73 74 20 63 68 61  _write(const cha
5360: 72 20 2a 70 61 74 68 2c 20 63 6f 6e 73 74 20 63  r *path, const c
5370: 68 61 72 20 2a 62 75 66 2c 20 73 69 7a 65 5f 74  har *buf, size_t
5380: 20 73 69 7a 65 2c 20 6f 66 66 5f 74 20 6f 66 66   size, off_t off
5390: 73 65 74 2c 20 73 74 72 75 63 74 20 66 75 73 65  set, struct fuse
53a0: 5f 66 69 6c 65 5f 69 6e 66 6f 20 2a 66 69 29 20  _file_info *fi) 
53b0: 7b 0a 09 6f 66 66 5f 74 20 6c 73 65 65 6b 5f 72  {..off_t lseek_r
53c0: 65 74 3b 0a 09 73 73 69 7a 65 5f 74 20 77 72 69  et;..ssize_t wri
53d0: 74 65 5f 72 65 74 3b 0a 0a 09 41 50 50 46 53 5f  te_ret;...APPFS_
53e0: 44 45 42 55 47 28 22 45 6e 74 65 72 20 28 70 61  DEBUG("Enter (pa
53f0: 74 68 20 3d 20 25 73 2c 20 2e 2e 2e 29 22 2c 20  th = %s, ...)", 
5400: 70 61 74 68 29 3b 0a 0a 09 6c 73 65 65 6b 5f 72  path);...lseek_r
5410: 65 74 20 3d 20 6c 73 65 65 6b 28 66 69 2d 3e 66  et = lseek(fi->f
5420: 68 2c 20 6f 66 66 73 65 74 2c 20 53 45 45 4b 5f  h, offset, SEEK_
5430: 53 45 54 29 3b 0a 09 69 66 20 28 6c 73 65 65 6b  SET);..if (lseek
5440: 5f 72 65 74 20 21 3d 20 6f 66 66 73 65 74 29 20  _ret != offset) 
5450: 7b 0a 09 09 72 65 74 75 72 6e 28 2d 45 49 4f 29  {...return(-EIO)
5460: 3b 0a 09 7d 0a 0a 09 77 72 69 74 65 5f 72 65 74  ;..}...write_ret
5470: 20 3d 20 77 72 69 74 65 28 66 69 2d 3e 66 68 2c   = write(fi->fh,
5480: 20 62 75 66 2c 20 73 69 7a 65 29 3b 0a 0a 09 72   buf, size);...r
5490: 65 74 75 72 6e 28 77 72 69 74 65 5f 72 65 74 29  eturn(write_ret)
54a0: 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e 74 20  ;.}..static int 
54b0: 61 70 70 66 73 5f 66 75 73 65 5f 6d 6b 6e 6f 64  appfs_fuse_mknod
54c0: 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 70 61 74  (const char *pat
54d0: 68 2c 20 6d 6f 64 65 5f 74 20 6d 6f 64 65 2c 20  h, mode_t mode, 
54e0: 64 65 76 5f 74 20 64 65 76 69 63 65 29 20 7b 0a  dev_t device) {.
54f0: 09 63 68 61 72 20 2a 72 65 61 6c 5f 70 61 74 68  .char *real_path
5500: 3b 0a 09 69 6e 74 20 6d 6b 6e 6f 64 5f 72 65 74  ;..int mknod_ret
5510: 3b 0a 0a 09 41 50 50 46 53 5f 44 45 42 55 47 28  ;...APPFS_DEBUG(
5520: 22 45 6e 74 65 72 20 28 70 61 74 68 20 3d 20 25  "Enter (path = %
5530: 73 2c 20 2e 2e 2e 29 22 2c 20 70 61 74 68 29 3b  s, ...)", path);
5540: 0a 0a 09 69 66 20 28 28 6d 6f 64 65 20 26 20 53  ...if ((mode & S
5550: 5f 49 46 43 48 52 29 20 3d 3d 20 53 5f 49 46 43  _IFCHR) == S_IFC
5560: 48 52 29 20 7b 0a 09 09 72 65 74 75 72 6e 28 2d  HR) {...return(-
5570: 45 50 45 52 4d 29 3b 0a 09 7d 0a 0a 09 69 66 20  EPERM);..}...if 
5580: 28 28 6d 6f 64 65 20 26 20 53 5f 49 46 42 4c 4b  ((mode & S_IFBLK
5590: 29 20 3d 3d 20 53 5f 49 46 42 4c 4b 29 20 7b 0a  ) == S_IFBLK) {.
55a0: 09 09 72 65 74 75 72 6e 28 2d 45 50 45 52 4d 29  ..return(-EPERM)
55b0: 3b 0a 09 7d 0a 0a 09 61 70 70 66 73 5f 73 69 6d  ;..}...appfs_sim
55c0: 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f 65 6e  ulate_user_fs_en
55d0: 74 65 72 28 29 3b 0a 0a 09 72 65 61 6c 5f 70 61  ter();...real_pa
55e0: 74 68 20 3d 20 61 70 70 66 73 5f 70 72 65 70 61  th = appfs_prepa
55f0: 72 65 5f 74 6f 5f 63 72 65 61 74 65 28 70 61 74  re_to_create(pat
5600: 68 29 3b 0a 09 69 66 20 28 72 65 61 6c 5f 70 61  h);..if (real_pa
5610: 74 68 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09  th == NULL) {...
5620: 61 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75  appfs_simulate_u
5630: 73 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a  ser_fs_leave();.
5640: 0a 09 09 72 65 74 75 72 6e 28 2d 45 49 4f 29 3b  ...return(-EIO);
5650: 0a 09 7d 0a 0a 09 6d 6b 6e 6f 64 5f 72 65 74 20  ..}...mknod_ret 
5660: 3d 20 6d 6b 6e 6f 64 28 72 65 61 6c 5f 70 61 74  = mknod(real_pat
5670: 68 2c 20 6d 6f 64 65 2c 20 64 65 76 69 63 65 29  h, mode, device)
5680: 3b 0a 0a 09 61 70 70 66 73 5f 73 69 6d 75 6c 61  ;...appfs_simula
5690: 74 65 5f 75 73 65 72 5f 66 73 5f 6c 65 61 76 65  te_user_fs_leave
56a0: 28 29 3b 0a 0a 09 66 72 65 65 28 72 65 61 6c 5f  ();...free(real_
56b0: 70 61 74 68 29 3b 0a 0a 09 69 66 20 28 6d 6b 6e  path);...if (mkn
56c0: 6f 64 5f 72 65 74 20 21 3d 20 30 29 20 7b 0a 09  od_ret != 0) {..
56d0: 09 72 65 74 75 72 6e 28 65 72 72 6e 6f 20 2a 20  .return(errno * 
56e0: 2d 31 29 3b 0a 09 7d 0a 0a 09 72 65 74 75 72 6e  -1);..}...return
56f0: 28 30 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69  (0);.}..static i
5700: 6e 74 20 61 70 70 66 73 5f 66 75 73 65 5f 63 72  nt appfs_fuse_cr
5710: 65 61 74 65 28 63 6f 6e 73 74 20 63 68 61 72 20  eate(const char 
5720: 2a 70 61 74 68 2c 20 6d 6f 64 65 5f 74 20 6d 6f  *path, mode_t mo
5730: 64 65 2c 20 73 74 72 75 63 74 20 66 75 73 65 5f  de, struct fuse_
5740: 66 69 6c 65 5f 69 6e 66 6f 20 2a 66 69 29 20 7b  file_info *fi) {
5750: 0a 09 63 68 61 72 20 2a 72 65 61 6c 5f 70 61 74  ..char *real_pat
5760: 68 3b 0a 09 69 6e 74 20 66 64 3b 0a 0a 09 41 50  h;..int fd;...AP
5770: 50 46 53 5f 44 45 42 55 47 28 22 45 6e 74 65 72  PFS_DEBUG("Enter
5780: 20 28 70 61 74 68 20 3d 20 25 73 2c 20 2e 2e 2e   (path = %s, ...
5790: 29 22 2c 20 70 61 74 68 29 3b 0a 0a 09 69 66 20  )", path);...if 
57a0: 28 28 6d 6f 64 65 20 26 20 53 5f 49 46 43 48 52  ((mode & S_IFCHR
57b0: 29 20 3d 3d 20 53 5f 49 46 43 48 52 29 20 7b 0a  ) == S_IFCHR) {.
57c0: 09 09 72 65 74 75 72 6e 28 2d 45 50 45 52 4d 29  ..return(-EPERM)
57d0: 3b 0a 09 7d 0a 0a 09 69 66 20 28 28 6d 6f 64 65  ;..}...if ((mode
57e0: 20 26 20 53 5f 49 46 42 4c 4b 29 20 3d 3d 20 53   & S_IFBLK) == S
57f0: 5f 49 46 42 4c 4b 29 20 7b 0a 09 09 72 65 74 75  _IFBLK) {...retu
5800: 72 6e 28 2d 45 50 45 52 4d 29 3b 0a 09 7d 0a 0a  rn(-EPERM);..}..
5810: 09 61 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f  .appfs_simulate_
5820: 75 73 65 72 5f 66 73 5f 65 6e 74 65 72 28 29 3b  user_fs_enter();
5830: 0a 0a 09 72 65 61 6c 5f 70 61 74 68 20 3d 20 61  ...real_path = a
5840: 70 70 66 73 5f 70 72 65 70 61 72 65 5f 74 6f 5f  ppfs_prepare_to_
5850: 63 72 65 61 74 65 28 70 61 74 68 29 3b 0a 09 69  create(path);..i
5860: 66 20 28 72 65 61 6c 5f 70 61 74 68 20 3d 3d 20  f (real_path == 
5870: 4e 55 4c 4c 29 20 7b 0a 09 09 61 70 70 66 73 5f  NULL) {...appfs_
5880: 73 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73  simulate_user_fs
5890: 5f 6c 65 61 76 65 28 29 3b 0a 0a 09 09 72 65 74  _leave();....ret
58a0: 75 72 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a 09  urn(-EIO);..}...
58b0: 66 64 20 3d 20 63 72 65 61 74 28 72 65 61 6c 5f  fd = creat(real_
58c0: 70 61 74 68 2c 20 6d 6f 64 65 29 3b 0a 0a 09 61  path, mode);...a
58d0: 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73  ppfs_simulate_us
58e0: 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a 0a  er_fs_leave();..
58f0: 09 66 72 65 65 28 72 65 61 6c 5f 70 61 74 68 29  .free(real_path)
5900: 3b 0a 0a 09 69 66 20 28 66 64 20 3c 20 30 29 20  ;...if (fd < 0) 
5910: 7b 0a 09 09 72 65 74 75 72 6e 28 65 72 72 6e 6f  {...return(errno
5920: 20 2a 20 2d 31 29 3b 0a 09 7d 0a 0a 09 66 69 2d   * -1);..}...fi-
5930: 3e 66 68 20 3d 20 66 64 3b 0a 0a 09 72 65 74 75  >fh = fd;...retu
5940: 72 6e 28 30 29 3b 0a 7d 0a 0a 73 74 61 74 69 63  rn(0);.}..static
5950: 20 69 6e 74 20 61 70 70 66 73 5f 66 75 73 65 5f   int appfs_fuse_
5960: 74 72 75 6e 63 61 74 65 28 63 6f 6e 73 74 20 63  truncate(const c
5970: 68 61 72 20 2a 70 61 74 68 2c 20 6f 66 66 5f 74  har *path, off_t
5980: 20 73 69 7a 65 29 20 7b 0a 09 63 68 61 72 20 2a   size) {..char *
5990: 72 65 61 6c 5f 70 61 74 68 3b 0a 09 69 6e 74 20  real_path;..int 
59a0: 74 72 75 6e 63 61 74 65 5f 72 65 74 3b 0a 0a 09  truncate_ret;...
59b0: 41 50 50 46 53 5f 44 45 42 55 47 28 22 45 6e 74  APPFS_DEBUG("Ent
59c0: 65 72 20 28 70 61 74 68 20 3d 20 25 73 2c 20 2e  er (path = %s, .
59d0: 2e 2e 29 22 2c 20 70 61 74 68 29 3b 0a 0a 09 72  ..)", path);...r
59e0: 65 61 6c 5f 70 61 74 68 20 3d 20 61 70 70 66 73  eal_path = appfs
59f0: 5f 6c 6f 63 61 6c 70 61 74 68 28 70 61 74 68 29  _localpath(path)
5a00: 3b 0a 09 69 66 20 28 72 65 61 6c 5f 70 61 74 68  ;..if (real_path
5a10: 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 72 65   == NULL) {...re
5a20: 74 75 72 6e 28 2d 45 49 4f 29 3b 0a 09 7d 0a 0a  turn(-EIO);..}..
5a30: 09 61 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f  .appfs_simulate_
5a40: 75 73 65 72 5f 66 73 5f 65 6e 74 65 72 28 29 3b  user_fs_enter();
5a50: 0a 0a 09 74 72 75 6e 63 61 74 65 5f 72 65 74 20  ...truncate_ret 
5a60: 3d 20 74 72 75 6e 63 61 74 65 28 72 65 61 6c 5f  = truncate(real_
5a70: 70 61 74 68 2c 20 73 69 7a 65 29 3b 0a 0a 09 61  path, size);...a
5a80: 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73  ppfs_simulate_us
5a90: 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a 0a  er_fs_leave();..
5aa0: 09 66 72 65 65 28 72 65 61 6c 5f 70 61 74 68 29  .free(real_path)
5ab0: 3b 0a 0a 09 69 66 20 28 74 72 75 6e 63 61 74 65  ;...if (truncate
5ac0: 5f 72 65 74 20 21 3d 20 30 29 20 7b 0a 09 09 72  _ret != 0) {...r
5ad0: 65 74 75 72 6e 28 65 72 72 6e 6f 20 2a 20 2d 31  eturn(errno * -1
5ae0: 29 3b 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 28 30  );..}...return(0
5af0: 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e 74  );.}..static int
5b00: 20 61 70 70 66 73 5f 66 75 73 65 5f 75 6e 6c 69   appfs_fuse_unli
5b10: 6e 6b 5f 72 6d 64 69 72 28 63 6f 6e 73 74 20 63  nk_rmdir(const c
5b20: 68 61 72 20 2a 70 61 74 68 29 20 7b 0a 09 54 63  har *path) {..Tc
5b30: 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70  l_Interp *interp
5b40: 3b 0a 09 69 6e 74 20 74 63 6c 5f 72 65 74 3b 0a  ;..int tcl_ret;.
5b50: 0a 09 41 50 50 46 53 5f 44 45 42 55 47 28 22 45  ..APPFS_DEBUG("E
5b60: 6e 74 65 72 20 28 70 61 74 68 20 3d 20 25 73 2c  nter (path = %s,
5b70: 20 2e 2e 2e 29 22 2c 20 70 61 74 68 29 3b 0a 0a   ...)", path);..
5b80: 09 69 6e 74 65 72 70 20 3d 20 61 70 70 66 73 5f  .interp = appfs_
5b90: 54 63 6c 49 6e 74 65 72 70 28 29 3b 0a 09 69 66  TclInterp();..if
5ba0: 20 28 69 6e 74 65 72 70 20 3d 3d 20 4e 55 4c 4c   (interp == NULL
5bb0: 29 20 7b 0a 09 09 72 65 74 75 72 6e 28 2d 45 49  ) {...return(-EI
5bc0: 4f 29 3b 0a 09 7d 0a 0a 09 61 70 70 66 73 5f 73  O);..}...appfs_s
5bd0: 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f  imulate_user_fs_
5be0: 65 6e 74 65 72 28 29 3b 0a 0a 09 74 63 6c 5f 72  enter();...tcl_r
5bf0: 65 74 20 3d 20 61 70 70 66 73 5f 54 63 6c 5f 45  et = appfs_Tcl_E
5c00: 76 61 6c 28 69 6e 74 65 72 70 2c 20 32 2c 20 22  val(interp, 2, "
5c10: 3a 3a 61 70 70 66 73 3a 3a 75 6e 6c 69 6e 6b 70  ::appfs::unlinkp
5c20: 61 74 68 22 2c 20 70 61 74 68 29 3b 0a 0a 09 61  ath", path);...a
5c30: 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73  ppfs_simulate_us
5c40: 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a 0a  er_fs_leave();..
5c50: 09 69 66 20 28 74 63 6c 5f 72 65 74 20 21 3d 20  .if (tcl_ret != 
5c60: 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09 41 50 50 46  TCL_OK) {...APPF
5c70: 53 5f 44 45 42 55 47 28 22 3a 3a 61 70 70 66 73  S_DEBUG("::appfs
5c80: 3a 3a 75 6e 6c 69 6e 6b 70 61 74 68 28 25 73 29  ::unlinkpath(%s)
5c90: 20 66 61 69 6c 65 64 2e 22 2c 20 70 61 74 68 29   failed.", path)
5ca0: 3b 0a 09 09 41 50 50 46 53 5f 44 45 42 55 47 28  ;...APPFS_DEBUG(
5cb0: 22 54 63 6c 20 45 72 72 6f 72 20 69 73 3a 20 25  "Tcl Error is: %
5cc0: 73 22 2c 20 54 63 6c 5f 47 65 74 53 74 72 69 6e  s", Tcl_GetStrin
5cd0: 67 52 65 73 75 6c 74 28 69 6e 74 65 72 70 29 29  gResult(interp))
5ce0: 3b 0a 0a 09 09 72 65 74 75 72 6e 28 2d 45 49 4f  ;....return(-EIO
5cf0: 29 3b 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 28 30  );..}...return(0
5d00: 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e 74  );.}..static int
5d10: 20 61 70 70 66 73 5f 66 75 73 65 5f 6d 6b 64 69   appfs_fuse_mkdi
5d20: 72 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 70 61  r(const char *pa
5d30: 74 68 2c 20 6d 6f 64 65 5f 74 20 6d 6f 64 65 29  th, mode_t mode)
5d40: 20 7b 0a 09 63 68 61 72 20 2a 72 65 61 6c 5f 70   {..char *real_p
5d50: 61 74 68 3b 0a 09 69 6e 74 20 6d 6b 64 69 72 5f  ath;..int mkdir_
5d60: 72 65 74 3b 0a 0a 09 41 50 50 46 53 5f 44 45 42  ret;...APPFS_DEB
5d70: 55 47 28 22 45 6e 74 65 72 20 28 70 61 74 68 20  UG("Enter (path 
5d80: 3d 20 25 73 2c 20 2e 2e 2e 29 22 2c 20 70 61 74  = %s, ...)", pat
5d90: 68 29 3b 0a 0a 09 61 70 70 66 73 5f 73 69 6d 75  h);...appfs_simu
5da0: 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f 65 6e 74  late_user_fs_ent
5db0: 65 72 28 29 3b 0a 0a 09 72 65 61 6c 5f 70 61 74  er();...real_pat
5dc0: 68 20 3d 20 61 70 70 66 73 5f 70 72 65 70 61 72  h = appfs_prepar
5dd0: 65 5f 74 6f 5f 63 72 65 61 74 65 28 70 61 74 68  e_to_create(path
5de0: 29 3b 0a 09 69 66 20 28 72 65 61 6c 5f 70 61 74  );..if (real_pat
5df0: 68 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 61  h == NULL) {...a
5e00: 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73  ppfs_simulate_us
5e10: 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a 0a  er_fs_leave();..
5e20: 09 09 72 65 74 75 72 6e 28 2d 45 49 4f 29 3b 0a  ..return(-EIO);.
5e30: 09 7d 0a 0a 09 6d 6b 64 69 72 5f 72 65 74 20 3d  .}...mkdir_ret =
5e40: 20 6d 6b 64 69 72 28 72 65 61 6c 5f 70 61 74 68   mkdir(real_path
5e50: 2c 20 6d 6f 64 65 29 3b 0a 0a 09 61 70 70 66 73  , mode);...appfs
5e60: 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66  _simulate_user_f
5e70: 73 5f 6c 65 61 76 65 28 29 3b 0a 0a 09 66 72 65  s_leave();...fre
5e80: 65 28 72 65 61 6c 5f 70 61 74 68 29 3b 0a 0a 09  e(real_path);...
5e90: 69 66 20 28 6d 6b 64 69 72 5f 72 65 74 20 21 3d  if (mkdir_ret !=
5ea0: 20 30 29 20 7b 0a 09 09 69 66 20 28 65 72 72 6e   0) {...if (errn
5eb0: 6f 20 21 3d 20 45 45 58 49 53 54 29 20 7b 0a 09  o != EEXIST) {..
5ec0: 09 09 72 65 74 75 72 6e 28 65 72 72 6e 6f 20 2a  ..return(errno *
5ed0: 20 2d 31 29 3b 0a 09 09 7d 0a 09 7d 0a 0a 09 72   -1);...}..}...r
5ee0: 65 74 75 72 6e 28 30 29 3b 0a 7d 0a 0a 73 74 61  eturn(0);.}..sta
5ef0: 74 69 63 20 69 6e 74 20 61 70 70 66 73 5f 66 75  tic int appfs_fu
5f00: 73 65 5f 63 68 6d 6f 64 28 63 6f 6e 73 74 20 63  se_chmod(const c
5f10: 68 61 72 20 2a 70 61 74 68 2c 20 6d 6f 64 65 5f  har *path, mode_
5f20: 74 20 6d 6f 64 65 29 20 7b 0a 09 54 63 6c 5f 49  t mode) {..Tcl_I
5f30: 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 3b 0a 09  nterp *interp;..
5f40: 63 6f 6e 73 74 20 63 68 61 72 20 2a 72 65 61 6c  const char *real
5f50: 5f 70 61 74 68 3b 0a 09 69 6e 74 20 74 63 6c 5f  _path;..int tcl_
5f60: 72 65 74 2c 20 63 68 6d 6f 64 5f 72 65 74 3b 0a  ret, chmod_ret;.
5f70: 0a 09 41 50 50 46 53 5f 44 45 42 55 47 28 22 45  ..APPFS_DEBUG("E
5f80: 6e 74 65 72 20 28 70 61 74 68 20 3d 20 25 73 2c  nter (path = %s,
5f90: 20 2e 2e 2e 29 22 2c 20 70 61 74 68 29 3b 0a 0a   ...)", path);..
5fa0: 09 69 6e 74 65 72 70 20 3d 20 61 70 70 66 73 5f  .interp = appfs_
5fb0: 54 63 6c 49 6e 74 65 72 70 28 29 3b 0a 09 69 66  TclInterp();..if
5fc0: 20 28 69 6e 74 65 72 70 20 3d 3d 20 4e 55 4c 4c   (interp == NULL
5fd0: 29 20 7b 0a 09 09 72 65 74 75 72 6e 28 2d 45 49  ) {...return(-EI
5fe0: 4f 29 3b 0a 09 7d 0a 0a 09 61 70 70 66 73 5f 73  O);..}...appfs_s
5ff0: 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f  imulate_user_fs_
6000: 65 6e 74 65 72 28 29 3b 0a 0a 09 74 63 6c 5f 72  enter();...tcl_r
6010: 65 74 20 3d 20 61 70 70 66 73 5f 54 63 6c 5f 45  et = appfs_Tcl_E
6020: 76 61 6c 28 69 6e 74 65 72 70 2c 20 33 2c 20 22  val(interp, 3, "
6030: 3a 3a 61 70 70 66 73 3a 3a 6f 70 65 6e 70 61 74  ::appfs::openpat
6040: 68 22 2c 20 70 61 74 68 2c 20 22 77 72 69 74 65  h", path, "write
6050: 22 29 3b 0a 09 69 66 20 28 74 63 6c 5f 72 65 74  ");..if (tcl_ret
6060: 20 21 3d 20 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09   != TCL_OK) {...
6070: 61 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75  appfs_simulate_u
6080: 73 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a  ser_fs_leave();.
6090: 0a 09 09 41 50 50 46 53 5f 44 45 42 55 47 28 22  ...APPFS_DEBUG("
60a0: 3a 3a 61 70 70 66 73 3a 3a 6f 70 65 6e 70 61 74  ::appfs::openpat
60b0: 68 28 25 73 2c 20 25 73 29 20 66 61 69 6c 65 64  h(%s, %s) failed
60c0: 2e 22 2c 20 70 61 74 68 2c 20 22 77 72 69 74 65  .", path, "write
60d0: 22 29 3b 0a 09 09 41 50 50 46 53 5f 44 45 42 55  ");...APPFS_DEBU
60e0: 47 28 22 54 63 6c 20 45 72 72 6f 72 20 69 73 3a  G("Tcl Error is:
60f0: 20 25 73 22 2c 20 54 63 6c 5f 47 65 74 53 74 72   %s", Tcl_GetStr
6100: 69 6e 67 52 65 73 75 6c 74 28 69 6e 74 65 72 70  ingResult(interp
6110: 29 29 3b 0a 0a 09 09 72 65 74 75 72 6e 28 2d 45  ));....return(-E
6120: 49 4f 29 3b 0a 09 7d 0a 0a 09 72 65 61 6c 5f 70  IO);..}...real_p
6130: 61 74 68 20 3d 20 54 63 6c 5f 47 65 74 53 74 72  ath = Tcl_GetStr
6140: 69 6e 67 52 65 73 75 6c 74 28 69 6e 74 65 72 70  ingResult(interp
6150: 29 3b 0a 09 69 66 20 28 72 65 61 6c 5f 70 61 74  );..if (real_pat
6160: 68 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 61  h == NULL) {...a
6170: 70 70 66 73 5f 73 69 6d 75 6c 61 74 65 5f 75 73  ppfs_simulate_us
6180: 65 72 5f 66 73 5f 6c 65 61 76 65 28 29 3b 0a 0a  er_fs_leave();..
6190: 09 09 72 65 74 75 72 6e 28 2d 45 49 4f 29 3b 0a  ..return(-EIO);.
61a0: 09 7d 0a 0a 09 63 68 6d 6f 64 5f 72 65 74 20 3d  .}...chmod_ret =
61b0: 20 63 68 6d 6f 64 28 72 65 61 6c 5f 70 61 74 68   chmod(real_path
61c0: 2c 20 6d 6f 64 65 29 3b 0a 0a 09 61 70 70 66 73  , mode);...appfs
61d0: 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66  _simulate_user_f
61e0: 73 5f 6c 65 61 76 65 28 29 3b 0a 0a 09 72 65 74  s_leave();...ret
61f0: 75 72 6e 28 63 68 6d 6f 64 5f 72 65 74 29 3b 0a  urn(chmod_ret);.
6200: 7d 0a 0a 2f 2a 0a 20 2a 20 53 51 4c 69 74 65 33  }../*. * SQLite3
6210: 20 6d 6f 64 65 3a 20 45 78 65 63 75 74 65 20 72   mode: Execute r
6220: 61 77 20 53 51 4c 20 61 6e 64 20 72 65 74 75 72  aw SQL and retur
6230: 6e 20 73 75 63 63 65 73 73 20 6f 72 20 66 61 69  n success or fai
6240: 6c 75 72 65 0a 20 2a 2f 0a 73 74 61 74 69 63 20  lure. */.static 
6250: 69 6e 74 20 61 70 70 66 73 5f 73 71 6c 69 74 65  int appfs_sqlite
6260: 33 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 73 71  3(const char *sq
6270: 6c 29 20 7b 0a 09 54 63 6c 5f 49 6e 74 65 72 70  l) {..Tcl_Interp
6280: 20 2a 69 6e 74 65 72 70 3b 0a 09 63 6f 6e 73 74   *interp;..const
6290: 20 63 68 61 72 20 2a 73 71 6c 5f 72 65 74 3b 0a   char *sql_ret;.
62a0: 09 69 6e 74 20 74 63 6c 5f 72 65 74 3b 0a 0a 09  .int tcl_ret;...
62b0: 69 6e 74 65 72 70 20 3d 20 61 70 70 66 73 5f 63  interp = appfs_c
62c0: 72 65 61 74 65 5f 54 63 6c 49 6e 74 65 72 70 28  reate_TclInterp(
62d0: 4e 55 4c 4c 29 3b 0a 09 69 66 20 28 69 6e 74 65  NULL);..if (inte
62e0: 72 70 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09  rp == NULL) {...
62f0: 66 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c 20  fprintf(stderr, 
6300: 22 55 6e 61 62 6c 65 20 74 6f 20 63 72 65 61 74  "Unable to creat
6310: 65 20 61 20 54 63 6c 20 69 6e 74 65 72 70 72 65  e a Tcl interpre
6320: 74 65 72 2e 20 20 41 62 6f 72 74 69 6e 67 2e 5c  ter.  Aborting.\
6330: 6e 22 29 3b 0a 0a 09 09 72 65 74 75 72 6e 28 31  n");....return(1
6340: 29 3b 0a 09 7d 0a 0a 09 74 63 6c 5f 72 65 74 20  );..}...tcl_ret 
6350: 3d 20 61 70 70 66 73 5f 54 63 6c 5f 45 76 61 6c  = appfs_Tcl_Eval
6360: 28 69 6e 74 65 72 70 2c 20 35 2c 20 22 3a 3a 61  (interp, 5, "::a
6370: 70 70 66 73 3a 3a 64 62 22 2c 20 22 65 76 61 6c  ppfs::db", "eval
6380: 22 2c 20 73 71 6c 2c 20 22 72 6f 77 22 2c 20 22  ", sql, "row", "
6390: 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69  unset -nocomplai
63a0: 6e 20 72 6f 77 28 2a 29 3b 20 70 61 72 72 61 79  n row(*); parray
63b0: 20 72 6f 77 3b 20 70 75 74 73 20 5c 22 2d 2d 2d   row; puts \"---
63c0: 2d 5c 22 22 29 3b 0a 09 73 71 6c 5f 72 65 74 20  -\"");..sql_ret 
63d0: 3d 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67 52  = Tcl_GetStringR
63e0: 65 73 75 6c 74 28 69 6e 74 65 72 70 29 3b 0a 0a  esult(interp);..
63f0: 09 69 66 20 28 74 63 6c 5f 72 65 74 20 21 3d 20  .if (tcl_ret != 
6400: 54 43 4c 5f 4f 4b 29 20 7b 0a 09 09 66 70 72 69  TCL_OK) {...fpri
6410: 6e 74 66 28 73 74 64 65 72 72 2c 20 22 5b 65 72  ntf(stderr, "[er
6420: 72 6f 72 5d 20 25 73 5c 6e 22 2c 20 73 71 6c 5f  ror] %s\n", sql_
6430: 72 65 74 29 3b 0a 0a 09 09 72 65 74 75 72 6e 28  ret);....return(
6440: 31 29 3b 0a 09 7d 0a 0a 09 69 66 20 28 73 71 6c  1);..}...if (sql
6450: 5f 72 65 74 20 26 26 20 73 71 6c 5f 72 65 74 5b  _ret && sql_ret[
6460: 30 5d 20 21 3d 20 27 5c 30 27 29 20 7b 0a 09 09  0] != '\0') {...
6470: 70 72 69 6e 74 66 28 22 25 73 5c 6e 22 2c 20 73  printf("%s\n", s
6480: 71 6c 5f 72 65 74 29 3b 0a 09 7d 0a 0a 09 72 65  ql_ret);..}...re
6490: 74 75 72 6e 28 30 29 3b 0a 7d 0a 0a 2f 2a 0a 20  turn(0);.}../*. 
64a0: 2a 20 54 63 6c 20 6d 6f 64 65 3a 20 45 78 65 63  * Tcl mode: Exec
64b0: 75 74 65 20 72 61 77 20 54 63 6c 20 61 6e 64 20  ute raw Tcl and 
64c0: 72 65 74 75 72 6e 20 73 75 63 63 65 73 73 20 6f  return success o
64d0: 72 20 66 61 69 6c 75 72 65 0a 20 2a 2f 0a 73 74  r failure. */.st
64e0: 61 74 69 63 20 69 6e 74 20 61 70 70 66 73 5f 74  atic int appfs_t
64f0: 63 6c 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 74  cl(const char *t
6500: 63 6c 29 20 7b 0a 09 54 63 6c 5f 49 6e 74 65 72  cl) {..Tcl_Inter
6510: 70 20 2a 69 6e 74 65 72 70 3b 0a 09 63 6f 6e 73  p *interp;..cons
6520: 74 20 63 68 61 72 20 2a 74 63 6c 5f 72 65 73 75  t char *tcl_resu
6530: 6c 74 3b 0a 09 69 6e 74 20 74 63 6c 5f 72 65 74  lt;..int tcl_ret
6540: 3b 0a 0a 09 69 6e 74 65 72 70 20 3d 20 61 70 70  ;...interp = app
6550: 66 73 5f 63 72 65 61 74 65 5f 54 63 6c 49 6e 74  fs_create_TclInt
6560: 65 72 70 28 4e 55 4c 4c 29 3b 0a 09 69 66 20 28  erp(NULL);..if (
6570: 69 6e 74 65 72 70 20 3d 3d 20 4e 55 4c 4c 29 20  interp == NULL) 
6580: 7b 0a 09 09 66 70 72 69 6e 74 66 28 73 74 64 65  {...fprintf(stde
6590: 72 72 2c 20 22 55 6e 61 62 6c 65 20 74 6f 20 63  rr, "Unable to c
65a0: 72 65 61 74 65 20 61 20 54 63 6c 20 69 6e 74 65  reate a Tcl inte
65b0: 72 70 72 65 74 65 72 2e 20 20 41 62 6f 72 74 69  rpreter.  Aborti
65c0: 6e 67 2e 5c 6e 22 29 3b 0a 0a 09 09 72 65 74 75  ng.\n");....retu
65d0: 72 6e 28 31 29 3b 0a 09 7d 0a 0a 09 74 63 6c 5f  rn(1);..}...tcl_
65e0: 72 65 74 20 3d 20 54 63 6c 5f 45 76 61 6c 28 69  ret = Tcl_Eval(i
65f0: 6e 74 65 72 70 2c 20 74 63 6c 29 3b 0a 09 74 63  nterp, tcl);..tc
6600: 6c 5f 72 65 73 75 6c 74 20 3d 20 54 63 6c 5f 47  l_result = Tcl_G
6610: 65 74 53 74 72 69 6e 67 52 65 73 75 6c 74 28 69  etStringResult(i
6620: 6e 74 65 72 70 29 3b 0a 0a 09 69 66 20 28 74 63  nterp);...if (tc
6630: 6c 5f 72 65 74 20 21 3d 20 54 43 4c 5f 4f 4b 29  l_ret != TCL_OK)
6640: 20 7b 0a 09 09 66 70 72 69 6e 74 66 28 73 74 64   {...fprintf(std
6650: 65 72 72 2c 20 22 5b 65 72 72 6f 72 5d 20 25 73  err, "[error] %s
6660: 5c 6e 22 2c 20 74 63 6c 5f 72 65 73 75 6c 74 29  \n", tcl_result)
6670: 3b 0a 0a 09 09 72 65 74 75 72 6e 28 31 29 3b 0a  ;....return(1);.
6680: 09 7d 0a 0a 09 69 66 20 28 74 63 6c 5f 72 65 73  .}...if (tcl_res
6690: 75 6c 74 20 26 26 20 74 63 6c 5f 72 65 73 75 6c  ult && tcl_resul
66a0: 74 5b 30 5d 20 21 3d 20 27 5c 30 27 29 20 7b 0a  t[0] != '\0') {.
66b0: 09 09 70 72 69 6e 74 66 28 22 25 73 5c 6e 22 2c  ..printf("%s\n",
66c0: 20 74 63 6c 5f 72 65 73 75 6c 74 29 3b 0a 09 7d   tcl_result);..}
66d0: 0a 0a 09 72 65 74 75 72 6e 28 30 29 3b 0a 7d 0a  ...return(0);.}.
66e0: 0a 2f 2a 0a 20 2a 20 41 70 70 46 53 64 20 50 61  ./*. * AppFSd Pa
66f0: 63 6b 61 67 65 20 66 6f 72 20 54 63 6c 3a 0a 20  ckage for Tcl:. 
6700: 2a 20 20 20 20 20 20 20 20 20 42 72 69 64 67 65  *         Bridge
6710: 20 66 6f 72 20 49 2f 4f 20 6f 70 65 72 61 74 69   for I/O operati
6720: 6f 6e 73 20 74 6f 20 72 65 71 75 65 73 74 20 69  ons to request i
6730: 6e 66 6f 72 6d 61 74 69 6f 6e 20 61 62 6f 75 74  nformation about
6740: 20 74 68 65 20 63 75 72 72 65 6e 74 0a 20 2a 20   the current. * 
6750: 20 20 20 20 20 20 20 20 74 72 61 6e 73 61 63 74          transact
6760: 69 6f 6e 0a 20 2a 2f 0a 73 74 61 74 69 63 20 69  ion. */.static i
6770: 6e 74 20 41 70 70 66 73 64 5f 49 6e 69 74 28 54  nt Appfsd_Init(T
6780: 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72  cl_Interp *inter
6790: 70 29 20 7b 0a 23 69 66 64 65 66 20 55 53 45 5f  p) {.#ifdef USE_
67a0: 54 43 4c 5f 53 54 55 42 53 0a 09 69 66 20 28 54  TCL_STUBS..if (T
67b0: 63 6c 5f 49 6e 69 74 53 74 75 62 73 28 69 6e 74  cl_InitStubs(int
67c0: 65 72 70 2c 20 54 43 4c 5f 56 45 52 53 49 4f 4e  erp, TCL_VERSION
67d0: 2c 20 30 29 20 3d 3d 20 30 4c 29 20 7b 0a 09 09  , 0) == 0L) {...
67e0: 72 65 74 75 72 6e 28 54 43 4c 5f 45 52 52 4f 52  return(TCL_ERROR
67f0: 29 3b 0a 09 7d 0a 23 65 6e 64 69 66 0a 0a 09 54  );..}.#endif...T
6800: 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43 6f 6d 6d  cl_CreateObjComm
6810: 61 6e 64 28 69 6e 74 65 72 70 2c 20 22 61 70 70  and(interp, "app
6820: 66 73 64 3a 3a 67 65 74 5f 68 6f 6d 65 64 69 72  fsd::get_homedir
6830: 22 2c 20 74 63 6c 5f 61 70 70 66 73 5f 67 65 74  ", tcl_appfs_get
6840: 5f 68 6f 6d 65 64 69 72 2c 20 4e 55 4c 4c 2c 20  _homedir, NULL, 
6850: 4e 55 4c 4c 29 3b 0a 09 54 63 6c 5f 43 72 65 61  NULL);..Tcl_Crea
6860: 74 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74  teObjCommand(int
6870: 65 72 70 2c 20 22 61 70 70 66 73 64 3a 3a 73 69  erp, "appfsd::si
6880: 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f 65  mulate_user_fs_e
6890: 6e 74 65 72 22 2c 20 74 63 6c 5f 61 70 70 66 73  nter", tcl_appfs
68a0: 5f 73 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66  _simulate_user_f
68b0: 73 5f 65 6e 74 65 72 2c 20 4e 55 4c 4c 2c 20 4e  s_enter, NULL, N
68c0: 55 4c 4c 29 3b 0a 09 54 63 6c 5f 43 72 65 61 74  ULL);..Tcl_Creat
68d0: 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74 65  eObjCommand(inte
68e0: 72 70 2c 20 22 61 70 70 66 73 64 3a 3a 73 69 6d  rp, "appfsd::sim
68f0: 75 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f 6c 65  ulate_user_fs_le
6900: 61 76 65 22 2c 20 74 63 6c 5f 61 70 70 66 73 5f  ave", tcl_appfs_
6910: 73 69 6d 75 6c 61 74 65 5f 75 73 65 72 5f 66 73  simulate_user_fs
6920: 5f 6c 65 61 76 65 2c 20 4e 55 4c 4c 2c 20 4e 55  _leave, NULL, NU
6930: 4c 4c 29 3b 0a 0a 09 54 63 6c 5f 50 6b 67 50 72  LL);...Tcl_PkgPr
6940: 6f 76 69 64 65 28 69 6e 74 65 72 70 2c 20 22 61  ovide(interp, "a
6950: 70 70 66 73 64 22 2c 20 22 31 2e 30 22 29 3b 0a  ppfsd", "1.0");.
6960: 0a 09 72 65 74 75 72 6e 28 54 43 4c 5f 4f 4b 29  ..return(TCL_OK)
6970: 3b 0a 7d 0a 0a 2f 2a 0a 20 2a 20 46 55 53 45 20  ;.}../*. * FUSE 
6980: 6f 70 65 72 61 74 69 6f 6e 73 20 73 74 72 75 63  operations struc
6990: 74 75 72 65 0a 20 2a 2f 0a 73 74 61 74 69 63 20  ture. */.static 
69a0: 73 74 72 75 63 74 20 66 75 73 65 5f 6f 70 65 72  struct fuse_oper
69b0: 61 74 69 6f 6e 73 20 61 70 70 66 73 5f 6f 70 65  ations appfs_ope
69c0: 72 61 74 69 6f 6e 73 20 3d 20 7b 0a 09 2e 67 65  rations = {...ge
69d0: 74 61 74 74 72 20 20 20 3d 20 61 70 70 66 73 5f  tattr   = appfs_
69e0: 66 75 73 65 5f 67 65 74 61 74 74 72 2c 0a 09 2e  fuse_getattr,...
69f0: 72 65 61 64 64 69 72 20 20 20 3d 20 61 70 70 66  readdir   = appf
6a00: 73 5f 66 75 73 65 5f 72 65 61 64 64 69 72 2c 0a  s_fuse_readdir,.
6a10: 09 2e 72 65 61 64 6c 69 6e 6b 20 20 3d 20 61 70  ..readlink  = ap
6a20: 70 66 73 5f 66 75 73 65 5f 72 65 61 64 6c 69 6e  pfs_fuse_readlin
6a30: 6b 2c 0a 09 2e 6f 70 65 6e 20 20 20 20 20 20 3d  k,...open      =
6a40: 20 61 70 70 66 73 5f 66 75 73 65 5f 6f 70 65 6e   appfs_fuse_open
6a50: 2c 0a 09 2e 72 65 6c 65 61 73 65 20 20 20 3d 20  ,...release   = 
6a60: 61 70 70 66 73 5f 66 75 73 65 5f 63 6c 6f 73 65  appfs_fuse_close
6a70: 2c 0a 09 2e 72 65 61 64 20 20 20 20 20 20 3d 20  ,...read      = 
6a80: 61 70 70 66 73 5f 66 75 73 65 5f 72 65 61 64 2c  appfs_fuse_read,
6a90: 0a 09 2e 77 72 69 74 65 20 20 20 20 20 3d 20 61  ...write     = a
6aa0: 70 70 66 73 5f 66 75 73 65 5f 77 72 69 74 65 2c  ppfs_fuse_write,
6ab0: 0a 09 2e 6d 6b 6e 6f 64 20 20 20 20 20 3d 20 61  ...mknod     = a
6ac0: 70 70 66 73 5f 66 75 73 65 5f 6d 6b 6e 6f 64 2c  ppfs_fuse_mknod,
6ad0: 0a 09 2e 63 72 65 61 74 65 20 20 20 20 3d 20 61  ...create    = a
6ae0: 70 70 66 73 5f 66 75 73 65 5f 63 72 65 61 74 65  ppfs_fuse_create
6af0: 2c 0a 09 2e 74 72 75 6e 63 61 74 65 20 20 3d 20  ,...truncate  = 
6b00: 61 70 70 66 73 5f 66 75 73 65 5f 74 72 75 6e 63  appfs_fuse_trunc
6b10: 61 74 65 2c 0a 09 2e 75 6e 6c 69 6e 6b 20 20 20  ate,...unlink   
6b20: 20 3d 20 61 70 70 66 73 5f 66 75 73 65 5f 75 6e   = appfs_fuse_un
6b30: 6c 69 6e 6b 5f 72 6d 64 69 72 2c 0a 09 2e 72 6d  link_rmdir,...rm
6b40: 64 69 72 20 20 20 20 20 3d 20 61 70 70 66 73 5f  dir     = appfs_
6b50: 66 75 73 65 5f 75 6e 6c 69 6e 6b 5f 72 6d 64 69  fuse_unlink_rmdi
6b60: 72 2c 0a 09 2e 6d 6b 64 69 72 20 20 20 20 20 3d  r,...mkdir     =
6b70: 20 61 70 70 66 73 5f 66 75 73 65 5f 6d 6b 64 69   appfs_fuse_mkdi
6b80: 72 2c 0a 09 2e 63 68 6d 6f 64 20 20 20 20 20 3d  r,...chmod     =
6b90: 20 61 70 70 66 73 5f 66 75 73 65 5f 63 68 6d 6f   appfs_fuse_chmo
6ba0: 64 2c 0a 7d 3b 0a 0a 2f 2a 0a 20 2a 20 46 55 53  d,.};../*. * FUS
6bb0: 45 20 6f 70 74 69 6f 6e 20 70 61 72 73 69 6e 67  E option parsing
6bc0: 20 63 61 6c 6c 62 61 63 6b 0a 20 2a 2f 0a 73 74   callback. */.st
6bd0: 61 74 69 63 20 69 6e 74 20 61 70 70 66 73 5f 66  atic int appfs_f
6be0: 75 73 65 5f 6f 70 74 5f 63 62 28 76 6f 69 64 20  use_opt_cb(void 
6bf0: 2a 64 61 74 61 2c 20 63 6f 6e 73 74 20 63 68 61  *data, const cha
6c00: 72 20 2a 61 72 67 2c 20 69 6e 74 20 6b 65 79 2c  r *arg, int key,
6c10: 20 73 74 72 75 63 74 20 66 75 73 65 5f 61 72 67   struct fuse_arg
6c20: 73 20 2a 6f 75 74 61 72 67 73 29 20 7b 0a 09 73  s *outargs) {..s
6c30: 74 61 74 69 63 20 69 6e 74 20 73 65 65 6e 5f 63  tatic int seen_c
6c40: 61 63 68 65 64 69 72 20 3d 20 30 3b 0a 0a 09 69  achedir = 0;...i
6c50: 66 20 28 6b 65 79 20 3d 3d 20 46 55 53 45 5f 4f  f (key == FUSE_O
6c60: 50 54 5f 4b 45 59 5f 4e 4f 4e 4f 50 54 20 26 26  PT_KEY_NONOPT &&
6c70: 20 73 65 65 6e 5f 63 61 63 68 65 64 69 72 20 3d   seen_cachedir =
6c80: 3d 20 30 29 20 7b 0a 09 09 73 65 65 6e 5f 63 61  = 0) {...seen_ca
6c90: 63 68 65 64 69 72 20 3d 20 31 3b 0a 0a 09 09 61  chedir = 1;....a
6ca0: 70 70 66 73 5f 63 61 63 68 65 64 69 72 20 3d 20  ppfs_cachedir = 
6cb0: 73 74 72 64 75 70 28 61 72 67 29 3b 0a 0a 09 09  strdup(arg);....
6cc0: 72 65 74 75 72 6e 28 30 29 3b 0a 09 7d 0a 0a 09  return(0);..}...
6cd0: 72 65 74 75 72 6e 28 31 29 3b 0a 7d 0a 0a 2f 2a  return(1);.}../*
6ce0: 0a 20 2a 20 45 6e 74 72 79 20 70 6f 69 6e 74 20  . * Entry point 
6cf0: 69 6e 74 6f 20 74 68 69 73 20 70 72 6f 67 72 61  into this progra
6d00: 6d 2e 0a 20 2a 2f 0a 69 6e 74 20 6d 61 69 6e 28  m.. */.int main(
6d10: 69 6e 74 20 61 72 67 63 2c 20 63 68 61 72 20 2a  int argc, char *
6d20: 2a 61 72 67 76 29 20 7b 0a 09 54 63 6c 5f 49 6e  *argv) {..Tcl_In
6d30: 74 65 72 70 20 2a 74 65 73 74 5f 69 6e 74 65 72  terp *test_inter
6d40: 70 3b 0a 09 63 68 61 72 20 2a 74 65 73 74 5f 69  p;..char *test_i
6d50: 6e 74 65 72 70 5f 65 72 72 6f 72 3b 0a 09 73 74  nterp_error;..st
6d60: 72 75 63 74 20 66 75 73 65 5f 61 72 67 73 20 61  ruct fuse_args a
6d70: 72 67 73 20 3d 20 46 55 53 45 5f 41 52 47 53 5f  rgs = FUSE_ARGS_
6d80: 49 4e 49 54 28 61 72 67 63 2c 20 61 72 67 76 29  INIT(argc, argv)
6d90: 3b 0a 09 69 6e 74 20 70 74 68 72 65 61 64 5f 72  ;..int pthread_r
6da0: 65 74 3b 0a 0a 09 2f 2a 0a 09 20 2a 20 53 6b 69  et;.../*.. * Ski
6db0: 70 20 70 61 73 73 65 64 20 70 72 6f 67 72 61 6d  p passed program
6dc0: 20 6e 61 6d 65 0a 09 20 2a 2f 0a 09 69 66 20 28   name.. */..if (
6dd0: 61 72 67 63 20 3d 3d 20 30 20 7c 7c 20 61 72 67  argc == 0 || arg
6de0: 76 20 3d 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 72  v == NULL) {...r
6df0: 65 74 75 72 6e 28 31 29 3b 0a 09 7d 0a 09 61 72  eturn(1);..}..ar
6e00: 67 63 2d 2d 3b 0a 09 61 72 67 76 2b 2b 3b 0a 0a  gc--;..argv++;..
6e10: 09 2f 2a 0a 09 20 2a 20 53 65 74 20 67 6c 6f 62  ./*.. * Set glob
6e20: 61 6c 20 76 61 72 69 61 62 6c 65 73 2c 20 74 68  al variables, th
6e30: 65 73 65 20 73 68 6f 75 6c 64 20 62 65 20 63 6f  ese should be co
6e40: 6e 66 69 67 75 72 61 74 69 6f 6e 20 6f 70 74 69  nfiguration opti
6e50: 6f 6e 73 2e 0a 09 20 2a 2f 0a 09 61 70 70 66 73  ons... */..appfs
6e60: 5f 63 61 63 68 65 64 69 72 20 3d 20 41 50 50 46  _cachedir = APPF
6e70: 53 5f 43 41 43 48 45 44 49 52 3b 0a 0a 09 2f 2a  S_CACHEDIR;.../*
6e80: 0a 09 20 2a 20 53 65 74 20 67 6c 6f 62 61 6c 20  .. * Set global 
6e90: 76 61 72 69 61 62 6c 65 20 66 6f 72 20 22 62 6f  variable for "bo
6ea0: 6f 74 20 74 69 6d 65 22 20 74 6f 20 73 65 74 20  ot time" to set 
6eb0: 61 20 74 69 6d 65 20 6f 6e 20 64 69 72 65 63 74  a time on direct
6ec0: 6f 72 69 65 73 0a 09 20 2a 20 74 68 61 74 20 77  ories.. * that w
6ed0: 65 20 66 61 6b 65 2e 0a 09 20 2a 2f 0a 09 61 70  e fake... */..ap
6ee0: 70 66 73 5f 62 6f 6f 74 74 69 6d 65 20 3d 20 74  pfs_boottime = t
6ef0: 69 6d 65 28 4e 55 4c 4c 29 3b 0a 0a 09 2f 2a 0a  ime(NULL);.../*.
6f00: 09 20 2a 20 52 65 67 69 73 74 65 72 20 22 73 68  . * Register "sh
6f10: 61 31 22 20 61 6e 64 20 22 61 70 70 66 73 64 22  a1" and "appfsd"
6f20: 20 70 61 63 6b 61 67 65 20 77 69 74 68 20 6c 69   package with li
6f30: 62 74 63 6c 20 73 6f 20 74 68 61 74 20 61 6e 79  btcl so that any
6f40: 20 6e 65 77 0a 09 20 2a 20 69 6e 74 65 72 70 72   new.. * interpr
6f50: 65 74 65 72 73 20 63 72 65 61 74 65 64 20 28 77  eters created (w
6f60: 68 69 63 68 20 61 72 65 20 64 6f 6e 65 20 64 79  hich are done dy
6f70: 6e 61 6d 69 63 61 6c 6c 79 20 62 79 20 46 55 53  namically by FUS
6f80: 45 29 20 63 61 6e 20 68 61 76 65 0a 09 20 2a 20  E) can have.. * 
6f90: 74 68 65 20 61 70 70 72 6f 70 72 69 61 74 65 20  the appropriate 
6fa0: 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e 20 64 6f  configuration do
6fb0: 6e 65 20 61 75 74 6f 6d 61 74 69 63 61 6c 6c 79  ne automatically
6fc0: 2e 0a 09 20 2a 2f 0a 09 54 63 6c 5f 53 74 61 74  ... */..Tcl_Stat
6fd0: 69 63 50 61 63 6b 61 67 65 28 4e 55 4c 4c 2c 20  icPackage(NULL, 
6fe0: 22 73 68 61 31 22 2c 20 53 68 61 31 5f 49 6e 69  "sha1", Sha1_Ini
6ff0: 74 2c 20 4e 55 4c 4c 29 3b 0a 09 54 63 6c 5f 53  t, NULL);..Tcl_S
7000: 74 61 74 69 63 50 61 63 6b 61 67 65 28 4e 55 4c  taticPackage(NUL
7010: 4c 2c 20 22 61 70 70 66 73 64 22 2c 20 41 70 70  L, "appfsd", App
7020: 66 73 64 5f 49 6e 69 74 2c 20 4e 55 4c 4c 29 3b  fsd_Init, NULL);
7030: 0a 0a 09 2f 2a 0a 09 20 2a 20 43 72 65 61 74 65  .../*.. * Create
7040: 20 61 20 74 68 72 65 61 64 2d 73 70 65 63 69 66   a thread-specif
7050: 69 63 2d 64 61 74 61 20 28 54 53 44 29 20 6b 65  ic-data (TSD) ke
7060: 79 20 66 6f 72 20 65 61 63 68 20 74 68 72 65 61  y for each threa
7070: 64 20 74 6f 20 72 65 66 65 72 0a 09 20 2a 20 74  d to refer.. * t
7080: 6f 20 69 74 73 20 6f 77 6e 20 54 63 6c 20 69 6e  o its own Tcl in
7090: 74 65 72 70 72 65 74 65 72 2e 20 20 54 63 6c 20  terpreter.  Tcl 
70a0: 69 6e 74 65 72 70 72 65 74 65 72 73 20 6d 75 73  interpreters mus
70b0: 74 20 62 65 20 75 6e 69 71 75 65 20 70 65 72 0a  t be unique per.
70c0: 09 20 2a 20 74 68 72 65 61 64 20 61 6e 64 20 6e  . * thread and n
70d0: 65 77 20 74 68 72 65 61 64 73 20 61 72 65 20 64  ew threads are d
70e0: 79 6e 61 6d 69 63 61 6c 6c 79 20 63 72 65 61 74  ynamically creat
70f0: 65 64 20 62 79 20 46 55 53 45 2e 0a 09 20 2a 2f  ed by FUSE... */
7100: 0a 09 70 74 68 72 65 61 64 5f 72 65 74 20 3d 20  ..pthread_ret = 
7110: 70 74 68 72 65 61 64 5f 6b 65 79 5f 63 72 65 61  pthread_key_crea
7120: 74 65 28 26 69 6e 74 65 72 70 4b 65 79 2c 20 4e  te(&interpKey, N
7130: 55 4c 4c 29 3b 0a 09 69 66 20 28 70 74 68 72 65  ULL);..if (pthre
7140: 61 64 5f 72 65 74 20 21 3d 20 30 29 20 7b 0a 09  ad_ret != 0) {..
7150: 09 66 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c  .fprintf(stderr,
7160: 20 22 55 6e 61 62 6c 65 20 74 6f 20 63 72 65 61   "Unable to crea
7170: 74 65 20 54 53 44 20 6b 65 79 20 66 6f 72 20 54  te TSD key for T
7180: 63 6c 2e 20 20 41 62 6f 72 74 69 6e 67 2e 5c 6e  cl.  Aborting.\n
7190: 22 29 3b 0a 0a 09 09 72 65 74 75 72 6e 28 31 29  ");....return(1)
71a0: 3b 0a 09 7d 0a 0a 09 2f 2a 0a 09 20 2a 20 4d 61  ;..}.../*.. * Ma
71b0: 6e 75 61 6c 6c 79 20 73 70 65 63 69 66 79 20 63  nually specify c
71c0: 61 63 68 65 20 64 69 72 65 63 74 6f 72 79 2c 20  ache directory, 
71d0: 77 69 74 68 6f 75 74 20 46 55 53 45 20 63 61 6c  without FUSE cal
71e0: 6c 62 61 63 6b 0a 09 20 2a 20 54 68 69 73 20 6f  lback.. * This o
71f0: 70 74 69 6f 6e 20 6f 6e 6c 79 20 77 6f 72 6b 73  ption only works
7200: 20 77 68 65 6e 20 6e 6f 74 20 75 73 69 6e 67 20   when not using 
7210: 46 55 53 45 2c 20 73 69 6e 63 65 20 77 65 0a 09  FUSE, since we..
7220: 20 2a 20 64 6f 20 6e 6f 74 20 70 72 6f 63 65 73   * do not proces
7230: 73 20 69 74 20 77 69 74 68 20 46 55 53 45 73 20  s it with FUSEs 
7240: 6f 70 74 69 6f 6e 20 70 72 6f 63 65 73 73 69 6e  option processin
7250: 67 2e 0a 09 20 2a 2f 0a 09 69 66 20 28 61 72 67  g... */..if (arg
7260: 63 20 3e 3d 20 32 29 20 7b 0a 09 09 69 66 20 28  c >= 2) {...if (
7270: 73 74 72 63 6d 70 28 61 72 67 76 5b 30 5d 2c 20  strcmp(argv[0], 
7280: 22 2d 2d 63 61 63 68 65 64 69 72 22 29 20 3d 3d  "--cachedir") ==
7290: 20 30 29 20 7b 0a 09 09 09 61 70 70 66 73 5f 63   0) {....appfs_c
72a0: 61 63 68 65 64 69 72 20 3d 20 73 74 72 64 75 70  achedir = strdup
72b0: 28 61 72 67 76 5b 31 5d 29 3b 0a 0a 09 09 09 61  (argv[1]);.....a
72c0: 72 67 63 20 2d 3d 20 32 3b 0a 09 09 09 61 72 67  rgc -= 2;....arg
72d0: 76 20 2b 3d 20 32 3b 0a 09 09 7d 0a 09 7d 0a 0a  v += 2;...}..}..
72e0: 09 2f 2a 0a 09 20 2a 20 53 51 4c 69 74 65 33 20  ./*.. * SQLite3 
72f0: 6d 6f 64 65 2c 20 66 6f 72 20 72 75 6e 6e 69 6e  mode, for runnin
7300: 67 20 72 61 77 20 53 51 4c 20 61 67 61 69 6e 73  g raw SQL agains
7310: 74 20 74 68 65 20 63 61 63 68 65 20 64 61 74 61  t the cache data
7320: 62 61 73 65 0a 09 20 2a 2f 0a 09 69 66 20 28 61  base.. */..if (a
7330: 72 67 63 20 3d 3d 20 32 20 26 26 20 73 74 72 63  rgc == 2 && strc
7340: 6d 70 28 61 72 67 76 5b 30 5d 2c 20 22 2d 2d 73  mp(argv[0], "--s
7350: 71 6c 69 74 65 33 22 29 20 3d 3d 20 30 29 20 7b  qlite3") == 0) {
7360: 0a 09 09 72 65 74 75 72 6e 28 61 70 70 66 73 5f  ...return(appfs_
7370: 73 71 6c 69 74 65 33 28 61 72 67 76 5b 31 5d 29  sqlite3(argv[1])
7380: 29 3b 0a 09 7d 0a 0a 09 2f 2a 0a 09 20 2a 20 54  );..}.../*.. * T
7390: 63 6c 20 6d 6f 64 65 2c 20 66 6f 72 20 72 75 6e  cl mode, for run
73a0: 6e 69 6e 67 20 72 61 77 20 54 63 6c 20 69 6e 20  ning raw Tcl in 
73b0: 74 68 65 20 73 61 6d 65 20 65 6e 76 69 72 6f 6e  the same environ
73c0: 6d 65 6e 74 20 41 70 70 46 53 64 20 77 6f 75 6c  ment AppFSd woul
73d0: 64 0a 09 20 2a 20 72 75 6e 20 63 6f 64 65 2e 0a  d.. * run code..
73e0: 09 20 2a 2f 0a 09 69 66 20 28 61 72 67 63 20 3d  . */..if (argc =
73f0: 3d 20 32 20 26 26 20 73 74 72 63 6d 70 28 61 72  = 2 && strcmp(ar
7400: 67 76 5b 30 5d 2c 20 22 2d 2d 74 63 6c 22 29 20  gv[0], "--tcl") 
7410: 3d 3d 20 30 29 20 7b 0a 09 09 72 65 74 75 72 6e  == 0) {...return
7420: 28 61 70 70 66 73 5f 74 63 6c 28 61 72 67 76 5b  (appfs_tcl(argv[
7430: 31 5d 29 29 3b 0a 09 7d 0a 0a 09 2f 2a 0a 09 20  1]));..}.../*.. 
7440: 2a 20 43 72 65 61 74 65 20 61 20 54 63 6c 20 69  * Create a Tcl i
7450: 6e 74 65 72 70 72 65 74 65 72 20 6a 75 73 74 20  nterpreter just 
7460: 74 6f 20 76 65 72 69 66 79 20 74 68 61 74 20 74  to verify that t
7470: 68 69 6e 67 73 20 61 72 65 20 69 6e 20 77 6f 72  hings are in wor
7480: 6b 69 6e 67 20 0a 09 20 2a 20 6f 72 64 65 72 20  king .. * order 
7490: 62 65 66 6f 72 65 20 77 65 20 62 65 63 6f 6d 65  before we become
74a0: 20 61 20 64 61 65 6d 6f 6e 2e 0a 09 20 2a 2f 0a   a daemon... */.
74b0: 09 74 65 73 74 5f 69 6e 74 65 72 70 20 3d 20 61  .test_interp = a
74c0: 70 70 66 73 5f 63 72 65 61 74 65 5f 54 63 6c 49  ppfs_create_TclI
74d0: 6e 74 65 72 70 28 26 74 65 73 74 5f 69 6e 74 65  nterp(&test_inte
74e0: 72 70 5f 65 72 72 6f 72 29 3b 0a 09 69 66 20 28  rp_error);..if (
74f0: 74 65 73 74 5f 69 6e 74 65 72 70 20 3d 3d 20 4e  test_interp == N
7500: 55 4c 4c 29 20 7b 0a 09 09 69 66 20 28 74 65 73  ULL) {...if (tes
7510: 74 5f 69 6e 74 65 72 70 5f 65 72 72 6f 72 20 3d  t_interp_error =
7520: 3d 20 4e 55 4c 4c 29 20 7b 0a 09 09 09 74 65 73  = NULL) {....tes
7530: 74 5f 69 6e 74 65 72 70 5f 65 72 72 6f 72 20 3d  t_interp_error =
7540: 20 22 55 6e 6b 6e 6f 77 6e 20 65 72 72 6f 72 22   "Unknown error"
7550: 3b 0a 09 09 7d 0a 0a 09 09 66 70 72 69 6e 74 66  ;...}....fprintf
7560: 28 73 74 64 65 72 72 2c 20 22 55 6e 61 62 6c 65  (stderr, "Unable
7570: 20 74 6f 20 69 6e 69 74 69 61 6c 69 7a 65 20 54   to initialize T
7580: 63 6c 20 69 6e 74 65 72 70 72 65 74 65 72 20 66  cl interpreter f
7590: 6f 72 20 41 70 70 46 53 64 3a 5c 6e 22 29 3b 0a  or AppFSd:\n");.
75a0: 09 09 66 70 72 69 6e 74 66 28 73 74 64 65 72 72  ..fprintf(stderr
75b0: 2c 20 22 25 73 5c 6e 22 2c 20 74 65 73 74 5f 69  , "%s\n", test_i
75c0: 6e 74 65 72 70 5f 65 72 72 6f 72 29 3b 0a 0a 09  nterp_error);...
75d0: 09 72 65 74 75 72 6e 28 31 29 3b 0a 09 7d 0a 09  .return(1);..}..
75e0: 54 63 6c 5f 44 65 6c 65 74 65 49 6e 74 65 72 70  Tcl_DeleteInterp
75f0: 28 74 65 73 74 5f 69 6e 74 65 72 70 29 3b 0a 0a  (test_interp);..
7600: 09 2f 2a 0a 09 20 2a 20 41 64 64 20 46 55 53 45  ./*.. * Add FUSE
7610: 20 61 72 67 75 6d 65 6e 74 73 20 77 68 69 63 68   arguments which
7620: 20 77 65 20 61 6c 77 61 79 73 20 73 75 70 70 6c   we always suppl
7630: 79 0a 09 20 2a 2f 0a 09 66 75 73 65 5f 6f 70 74  y.. */..fuse_opt
7640: 5f 70 61 72 73 65 28 26 61 72 67 73 2c 20 4e 55  _parse(&args, NU
7650: 4c 4c 2c 20 4e 55 4c 4c 2c 20 61 70 70 66 73 5f  LL, NULL, appfs_
7660: 66 75 73 65 5f 6f 70 74 5f 63 62 29 3b 0a 09 66  fuse_opt_cb);..f
7670: 75 73 65 5f 6f 70 74 5f 61 64 64 5f 61 72 67 28  use_opt_add_arg(
7680: 26 61 72 67 73 2c 20 22 2d 6f 64 65 66 61 75 6c  &args, "-odefaul
7690: 74 5f 70 65 72 6d 69 73 73 69 6f 6e 73 2c 66 73  t_permissions,fs
76a0: 6e 61 6d 65 3d 61 70 70 66 73 2c 73 75 62 74 79  name=appfs,subty
76b0: 70 65 3d 61 70 70 66 73 64 2c 75 73 65 5f 69 6e  pe=appfsd,use_in
76c0: 6f 2c 6b 65 72 6e 65 6c 5f 63 61 63 68 65 2c 65  o,kernel_cache,e
76d0: 6e 74 72 79 5f 74 69 6d 65 6f 75 74 3d 36 30 2c  ntry_timeout=60,
76e0: 61 74 74 72 5f 74 69 6d 65 6f 75 74 3d 33 36 30  attr_timeout=360
76f0: 30 2c 69 6e 74 72 2c 62 69 67 5f 77 72 69 74 65  0,intr,big_write
7700: 73 22 29 3b 0a 0a 09 69 66 20 28 67 65 74 75 69  s");...if (getui
7710: 64 28 29 20 3d 3d 20 30 29 20 7b 0a 09 09 66 75  d() == 0) {...fu
7720: 73 65 5f 6f 70 74 5f 70 61 72 73 65 28 26 61 72  se_opt_parse(&ar
7730: 67 73 2c 20 4e 55 4c 4c 2c 20 4e 55 4c 4c 2c 20  gs, NULL, NULL, 
7740: 4e 55 4c 4c 29 3b 0a 09 09 66 75 73 65 5f 6f 70  NULL);...fuse_op
7750: 74 5f 61 64 64 5f 61 72 67 28 26 61 72 67 73 2c  t_add_arg(&args,
7760: 20 22 2d 6f 61 6c 6c 6f 77 5f 6f 74 68 65 72 22   "-oallow_other"
7770: 29 3b 0a 09 7d 0a 0a 09 2f 2a 0a 09 20 2a 20 45  );..}.../*.. * E
7780: 6e 74 65 72 20 74 68 65 20 46 55 53 45 20 6d 61  nter the FUSE ma
7790: 69 6e 20 6c 6f 6f 70 20 2d 2d 20 74 68 69 73 20  in loop -- this 
77a0: 77 69 6c 6c 20 70 72 6f 63 65 73 73 20 61 6e 79  will process any
77b0: 20 61 72 67 75 6d 65 6e 74 73 0a 09 20 2a 20 61   arguments.. * a
77c0: 6e 64 20 73 74 61 72 74 20 73 65 72 76 69 63 69  nd start servici
77d0: 6e 67 20 72 65 71 75 65 73 74 73 2e 0a 09 20 2a  ng requests... *
77e0: 2f 0a 09 61 70 70 66 73 5f 66 75 73 65 5f 73 74  /..appfs_fuse_st
77f0: 61 72 74 65 64 20 3d 20 31 3b 0a 09 72 65 74 75  arted = 1;..retu
7800: 72 6e 28 66 75 73 65 5f 6d 61 69 6e 28 61 72 67  rn(fuse_main(arg
7810: 73 2e 61 72 67 63 2c 20 61 72 67 73 2e 61 72 67  s.argc, args.arg
7820: 76 2c 20 26 61 70 70 66 73 5f 6f 70 65 72 61 74  v, &appfs_operat
7830: 69 6f 6e 73 2c 20 4e 55 4c 4c 29 29 3b 0a 7d 0a  ions, NULL));.}.
7840: 20 0a                                             .