Diff

Differences From Artifact [1768754e26]:

To Artifact [69177869fa]:


    21     21    */
    22     22   #ifndef APPFS_CACHEDIR
    23     23   #define APPFS_CACHEDIR "/var/cache/appfs"
    24     24   #endif
    25     25   
    26     26   /* Debugging macros */
    27     27   #ifdef DEBUG
    28         -#define APPFS_DEBUG(x...) { fprintf(stderr, "[debug] %s:%i:%s: ", __FILE__, __LINE__, __func__); fprintf(stderr, x); fprintf(stderr, "\n"); }
           28  +int appfs_debug_fd = STDERR_FILENO;
           29  +#define APPFS_DEBUG(x...) { \
           30  +	char buf[8192]; \
           31  +	int bufoff = 0; \
           32  +	if (appfs_debug_fd == -1) { \
           33  +		appfs_debug_fd = open("/tmp/appfsd.log", O_WRONLY | O_APPEND | O_CREAT, 0600); \
           34  +	}; \
           35  +	bufoff = snprintf(buf, sizeof(buf), "[debug] [t=%llx] %s:%i:%s: ", (unsigned long long) pthread_self(), __FILE__, __LINE__, __func__); \
           36  +	if (bufoff < sizeof(buf)) { \
           37  +		bufoff += snprintf(buf + bufoff, sizeof(buf) - bufoff, x); \
           38  +	}; \
           39  +	if (bufoff < sizeof(buf)) { \
           40  +		bufoff += snprintf(buf + bufoff, sizeof(buf) - bufoff, "\n");\
           41  +	} \
           42  +	if (bufoff > sizeof(buf)) { \
           43  +		bufoff = sizeof(buf); \
           44  +	}; \
           45  +	write(appfs_debug_fd, buf, bufoff); \
           46  +}
    29     47   #else
    30     48   #define APPFS_DEBUG(x...) /**/
    31     49   #endif
    32     50   
    33     51   /*
    34     52    * SHA1 Tcl Package initializer, from sha1.o
    35     53    */
................................................................................
    59     77   /*
    60     78    * Handle unthreaded Tcl
    61     79    */
    62     80   pthread_mutex_t appfs_tcl_big_global_lock = PTHREAD_MUTEX_INITIALIZER;
    63     81   #define appfs_call_libtcl_enter pthread_mutex_lock(&appfs_tcl_big_global_lock);
    64     82   #define appfs_call_libtcl_exit pthread_mutex_unlock(&appfs_tcl_big_global_lock);
    65     83   #else
           84  +#warning Using a Threaded Tcl interpreter may cause memory leaks
    66     85   #define appfs_call_libtcl_enter /**/
    67     86   #define appfs_call_libtcl_exit /**/
    68     87   #endif
    69     88   #define appfs_call_libtcl(x...) appfs_call_libtcl_enter x appfs_call_libtcl_exit
    70     89   
    71     90   /*
    72     91    * Global variables for AppFS Tcl Interpreter restarting
................................................................................
   377    396   
   378    397   	thread_interp_reset_key = global_interp_reset_key;
   379    398   
   380    399   	if (interp == NULL) {
   381    400   		interp = appfs_create_TclInterp(NULL);
   382    401   
   383    402   		if (interp == NULL) {
          403  +			APPFS_DEBUG("Create interp failed, returningin failure.");
          404  +
   384    405   			return(NULL);
   385    406   		}
   386    407   
   387    408   		pthread_ret = pthread_setspecific(interpKey, interp);
   388    409   		if (pthread_ret != 0) {
   389    410   			APPFS_DEBUG("pthread_setspecific() failed.  Terminating Tcl interpreter.");
   390    411   
................................................................................
   405    426   	Tcl_Obj **objv;
   406    427   	const char *arg;
   407    428   	va_list argp;
   408    429   	int retval;
   409    430   	int i;
   410    431   
   411    432   	if (interp == NULL) {
          433  +		APPFS_DEBUG("Invalid interpreter passed in, returning in failure.");
          434  +
   412    435   		return(TCL_ERROR);
   413    436   	}
   414    437   
   415    438   	objv = (void *) ckalloc(sizeof(*objv) * objc);
   416    439   
   417    440   	appfs_call_libtcl(
   418    441   		objv[0] = Tcl_NewStringObj(cmd, -1);
................................................................................
   474    497   		return(getuid());
   475    498   	}
   476    499   
   477    500   	ctx = fuse_get_context();
   478    501   	if (ctx == NULL) {
   479    502   		/* Unable to lookup user for some reason */
   480    503   		/* Return an unprivileged user ID */
          504  +		APPFS_DEBUG("Unable to lookup user for some reason, returninng user ID of 1");
          505  +
   481    506   		return(1);
   482    507   	}
   483    508   
   484    509   	return(ctx->uid);
   485    510   }
   486    511   
   487    512   /*
................................................................................
   496    521   		return(getgid());
   497    522   	}
   498    523   
   499    524   	ctx = fuse_get_context();
   500    525   	if (ctx == NULL) {
   501    526   		/* Unable to lookup user for some reason */
   502    527   		/* Return an unprivileged user ID */
          528  +		APPFS_DEBUG("Unable to lookup group for some reason, returninng group ID of 1");
          529  +
   503    530   		return(1);
   504    531   	}
   505    532   
   506    533   	return(ctx->gid);
   507    534   }
   508    535   
   509    536   static void appfs_simulate_user_fs_enter(void) {
................................................................................
   670    697   
   671    698   	pthread_ret = pthread_mutex_unlock(&appfs_path_info_cache_mutex);
   672    699   	if (pthread_ret != 0) {
   673    700   		APPFS_DEBUG("Unable to unlock path_info cache mutex !");
   674    701   
   675    702   		return;
   676    703   	}
          704  +
   677    705   	return;
   678    706   }
   679    707   
   680    708   static void appfs_get_path_info_cache_rm(const char *path, uid_t uid) {
   681    709   	unsigned int hash_idx;
   682    710   	int pthread_ret;
   683    711   
................................................................................
   773    801   	retval = 0;
   774    802   
   775    803   	fsuid = appfs_get_fsuid();
   776    804   
   777    805   	cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo);
   778    806   	if (cache_ret == 0) {
   779    807   		if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) {
          808  +			APPFS_DEBUG("Returning from cache: does not exist \"%s\"", path);
          809  +
   780    810   			return(-ENOENT);
   781    811   		}
   782    812   
   783    813   		if (pathinfo->type == APPFS_PATHTYPE_INVALID) {
          814  +			APPFS_DEBUG("Returning from cache: invalid object \"%s\"", path);
          815  +
   784    816   			return(-EIO);
   785    817   		}
   786    818   
   787    819   		return(0);
   788    820   	}
   789    821   
   790    822   	interp = appfs_TclInterp();
   791    823   	if (interp == NULL) {
          824  +		APPFS_DEBUG("error: Unable to get an interpreter");
          825  +
   792    826   		return(-EIO);
   793    827   	}
   794    828   
   795    829   	appfs_call_libtcl(Tcl_Preserve(interp);)
   796    830   
   797    831   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path);
   798    832   	if (tcl_ret != TCL_OK) {
................................................................................
   842    876   
   843    877   		appfs_call_libtcl(Tcl_Release(interp);)
   844    878   
   845    879   		return(-EIO);
   846    880   	}
   847    881   
   848    882   	if (attr_value == NULL) {
          883  +		APPFS_DEBUG("error: Unable to get type for \"%s\" from Tcl", path);
          884  +
   849    885   		appfs_call_libtcl(Tcl_Release(interp);)
   850    886   
   851    887   		return(-EIO);
   852    888   	}
   853    889   
   854    890   	pathinfo->packaged = 0;
   855    891   	pathinfo->inode = appfs_get_path_inode(path);
................................................................................
   935    971   		}
   936    972   
   937    973   		Tcl_Release(interp);
   938    974   	)
   939    975   
   940    976   	if (retval == 0) {
   941    977   		appfs_get_path_info_cache_add(path, fsuid, pathinfo);
          978  +	} else {
          979  +		APPFS_DEBUG("error: Invalid type for \"%s\" from Tcl", path);
   942    980   	}
   943    981   
   944    982   	return(retval);
   945    983   }
   946    984   
   947    985   static char *appfs_prepare_to_create(const char *path) {
   948    986   	Tcl_Interp *interp;
................................................................................
  1091   1129   	}
  1092   1130   #endif
  1093   1131   
  1094   1132   	pathinfo.type = APPFS_PATHTYPE_INVALID;
  1095   1133   
  1096   1134   	retval = appfs_get_path_info(path, &pathinfo);
  1097   1135   	if (retval != 0) {
         1136  +		if (retval == -ENOENT) {
         1137  +			APPFS_DEBUG("get_path_info returned ENOENT, returning it as well.");
         1138  +		} else {
         1139  +			APPFS_DEBUG("error: get_path_info failed");
         1140  +		}
         1141  +
  1098   1142   		return(retval);
  1099   1143   	}
  1100   1144   
  1101   1145   	memset(stbuf, 0, sizeof(struct stat));
  1102   1146   
  1103   1147   	stbuf->st_mtime = pathinfo.time;
  1104   1148   	stbuf->st_ctime = pathinfo.time;
................................................................................
  1161   1205   	int children_count, idx;
  1162   1206   	int tcl_ret;
  1163   1207   
  1164   1208   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1165   1209   
  1166   1210   	interp = appfs_TclInterp();
  1167   1211   	if (interp == NULL) {
         1212  +		APPFS_DEBUG("error: Unable to get an interpreter");
         1213  +
  1168   1214   		return(0);
  1169   1215   	}
  1170   1216   
  1171   1217   	appfs_call_libtcl(Tcl_Preserve(interp);)
  1172   1218   
  1173   1219   	filler(buf, ".", NULL, 0);
  1174   1220   	filler(buf, "..", NULL, 0);
................................................................................
  1220   1266   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1221   1267   
  1222   1268   	gpi_ret = appfs_get_path_info(path, &pathinfo);
  1223   1269   
  1224   1270   	if ((fi->flags & (O_WRONLY|O_CREAT)) == (O_CREAT|O_WRONLY)) {
  1225   1271   		/* The file will be created if it does not exist */
  1226   1272   		if (gpi_ret != 0 && gpi_ret != -ENOENT) {
         1273  +			APPFS_DEBUG("error: get_path_info failed");
         1274  +
  1227   1275   			return(gpi_ret);
  1228   1276   		}
  1229   1277   
  1230   1278   		mode = "create";
  1231   1279   
  1232   1280   		/*
  1233   1281   		 * We have to clear the cache here so that the number of
  1234   1282   		 * links gets maintained on the parent directory
  1235   1283   		 */
  1236   1284   		appfs_get_path_info_cache_flush(appfs_get_fsuid(), -1);
  1237   1285   	} else {
  1238   1286   		/* The file must already exist */
  1239   1287   		if (gpi_ret != 0) {
         1288  +			APPFS_DEBUG("error: get_path_info failed");
         1289  +
  1240   1290   			return(gpi_ret);
  1241   1291   		}
  1242   1292   
  1243   1293   		mode = "";
  1244   1294   
  1245   1295   		if ((fi->flags & O_WRONLY) == O_WRONLY) {
  1246   1296   			mode = "write";
  1247   1297   		}
  1248   1298   	}
  1249   1299   
  1250   1300   	if (pathinfo.type == APPFS_PATHTYPE_DIRECTORY) {
         1301  +		APPFS_DEBUG("error: Asked to open a directory.");
         1302  +
  1251   1303   		return(-EISDIR);
  1252   1304   	}
  1253   1305   
  1254   1306   	interp = appfs_TclInterp();
  1255   1307   	if (interp == NULL) {
         1308  +		APPFS_DEBUG("error: Unable to get an interpreter");
         1309  +
  1256   1310   		return(-EIO);
  1257   1311   	}
  1258   1312   
  1259   1313   	appfs_call_libtcl(Tcl_Preserve(interp);)
  1260   1314   
  1261   1315   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode);
  1262   1316   	if (tcl_ret != TCL_OK) {
................................................................................
  1273   1327   	appfs_call_libtcl(
  1274   1328   		real_path = Tcl_GetStringResult(interp);
  1275   1329   	)
  1276   1330   
  1277   1331   	appfs_call_libtcl(Tcl_Release(interp);)
  1278   1332   
  1279   1333   	if (real_path == NULL) {
         1334  +		APPFS_DEBUG("error: real_path was NULL.")
         1335  +
  1280   1336   		return(-EIO);
  1281   1337   	}
  1282   1338   
  1283   1339   	APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode);
  1284   1340   
  1285   1341   	fh = open(real_path, fi->flags, 0600);
  1286   1342   
  1287   1343   	if (fh < 0) {
  1288         -		return(-EIO);
         1344  +		APPFS_DEBUG("error: open failed");
         1345  +
         1346  +		return(errno * -1);
  1289   1347   	}
  1290   1348   
  1291   1349   	fi->fh = fh;
  1292   1350   
  1293   1351   	return(0);
  1294   1352   }
  1295   1353   
................................................................................
  1296   1354   static int appfs_fuse_close(const char *path, struct fuse_file_info *fi) {
  1297   1355   	int close_ret;
  1298   1356   
  1299   1357   	appfs_get_path_info_cache_rm(path, appfs_get_fsuid());
  1300   1358   
  1301   1359   	close_ret = close(fi->fh);
  1302   1360   	if (close_ret != 0) {
  1303         -		return(-EIO);
         1361  +		APPFS_DEBUG("error: close failed");
         1362  +
         1363  +		return(errno * -1);
  1304   1364   	}
  1305   1365   
  1306   1366   	return(0);
  1307   1367   }
  1308   1368   
  1309   1369   static int appfs_fuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
  1310         -	off_t lseek_ret;
  1311   1370   	ssize_t read_ret;
         1371  +	int retval;
  1312   1372   
  1313         -	APPFS_DEBUG("Enter (path = %s, ...)", path);
         1373  +	APPFS_DEBUG("Enter (path = %s, buf, %lli, %lli, fd=%lli)", path, (long long) size, (long long) offset, (long long) fi->fh);
  1314   1374   
  1315         -	lseek_ret = lseek(fi->fh, offset, SEEK_SET);
  1316         -	if (lseek_ret != offset) {
  1317         -		return(-EIO);
         1375  +	retval = 0;
         1376  +
         1377  +	while (size != 0) {
         1378  +		read_ret = pread(fi->fh, buf, size, offset);
         1379  +
         1380  +		if (read_ret < 0) {
         1381  +			APPFS_DEBUG("error: read failed");
         1382  +
         1383  +			return(errno * -1);
         1384  +		}
         1385  +
         1386  +		if (read_ret == 0) {
         1387  +			break;
         1388  +		}
         1389  +
         1390  +		size -= read_ret;
         1391  +		buf  += read_ret;
         1392  +		offset += read_ret;
         1393  +		retval += read_ret;
  1318   1394   	}
  1319   1395   
  1320         -	read_ret = read(fi->fh, buf, size);
         1396  +	if (size != 0) {
         1397  +		APPFS_DEBUG("error: incomplete read (this is an error because FUSE will request the exact length of the file)");
  1321   1398   
  1322         -	return(read_ret);
         1399  +		return(0);
         1400  +	}
         1401  +
         1402  +	APPFS_DEBUG("Returning: %i", retval);
         1403  +
         1404  +	return(retval);
  1323   1405   }
  1324   1406   
  1325   1407   static int appfs_fuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
  1326         -	off_t lseek_ret;
  1327   1408   	ssize_t write_ret;
         1409  +	int retval;
  1328   1410   
  1329   1411   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1330   1412   
  1331   1413   	appfs_get_path_info_cache_rm(path, appfs_get_fsuid());
  1332   1414   
  1333         -	lseek_ret = lseek(fi->fh, offset, SEEK_SET);
  1334         -	if (lseek_ret != offset) {
  1335         -		return(-EIO);
         1415  +	retval = 0;
         1416  +
         1417  +	while (size != 0) {
         1418  +		write_ret = pwrite(fi->fh, buf, size, offset);
         1419  +
         1420  +		if (write_ret < 0) {
         1421  +			APPFS_DEBUG("error: write failed");
         1422  +
         1423  +			return(errno * -1);
         1424  +		}
         1425  +
         1426  +		if (write_ret == 0) {
         1427  +			break;
         1428  +		}
         1429  +
         1430  +		size -= write_ret;
         1431  +		buf  += write_ret;
         1432  +		offset += write_ret;
         1433  +		retval += write_ret;
  1336   1434   	}
  1337   1435   
  1338         -	write_ret = write(fi->fh, buf, size);
         1436  +	if (size != 0) {
         1437  +		APPFS_DEBUG("error: incomplete write");
         1438  +	}
  1339   1439   
  1340         -	return(write_ret);
         1440  +	return(retval);
  1341   1441   }
  1342   1442   
  1343   1443   static int appfs_fuse_mknod(const char *path, mode_t mode, dev_t device) {
  1344   1444   	char *real_path;
  1345   1445   	int mknod_ret;
  1346   1446   
  1347   1447   	APPFS_DEBUG("Enter (path = %s, ...)", path);
................................................................................
  1764   1864   
  1765   1865   	return;
  1766   1866   }
  1767   1867   
  1768   1868   /*
  1769   1869    * Terminate a thread
  1770   1870    */
  1771         -static void appfs_terminate_interp(void *_interp) {
         1871  +static void appfs_terminate_interp_and_thread(void *_interp) {
  1772   1872   	Tcl_Interp *interp;
  1773   1873   
  1774   1874   	APPFS_DEBUG("Called: _interp = %p", _interp);
  1775   1875   
  1776   1876   	if (_interp == NULL) {
  1777   1877   		APPFS_DEBUG("Terminating thread with no interpreter");
  1778   1878   
................................................................................
  1782   1882   	interp = _interp;
  1783   1883   
  1784   1884   	APPFS_DEBUG("Terminating interpreter due to thread termination");
  1785   1885   
  1786   1886   	appfs_call_libtcl(
  1787   1887   		Tcl_DeleteInterp(interp);
  1788   1888   	)
         1889  +
         1890  +	Tcl_FinalizeThread();
  1789   1891   
  1790   1892   	return;
  1791   1893   }
  1792   1894   
  1793   1895   /*
  1794   1896    * FUSE operations structure
  1795   1897    */
................................................................................
  1866   1968   	Tcl_StaticPackage(NULL, "appfsd", Appfsd_Init, NULL);
  1867   1969   
  1868   1970   	/*
  1869   1971   	 * Create a thread-specific-data (TSD) key for each thread to refer
  1870   1972   	 * to its own Tcl interpreter.  Tcl interpreters must be unique per
  1871   1973   	 * thread and new threads are dynamically created by FUSE.
  1872   1974   	 */
  1873         -	pthread_ret = pthread_key_create(&interpKey, appfs_terminate_interp);
         1975  +	pthread_ret = pthread_key_create(&interpKey, appfs_terminate_interp_and_thread);
  1874   1976   	if (pthread_ret != 0) {
  1875   1977   		fprintf(stderr, "Unable to create TSD key for Tcl.  Aborting.\n");
  1876   1978   
  1877   1979   		return(1);
  1878   1980   	}
  1879   1981   
  1880   1982   	/*