Check-in [9562d42ae1]
Overview
Comment:Simplified user fsuid switching
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tcl-ops
Files: files | file ages | folders
SHA1:9562d42ae16a47710167fb08a08de9f0802d5d2a
User & Date: rkeene on 2014-11-10 05:30:53
Other Links: manifest | tags
Context
2014-11-10
05:38
Updated to compute number of children for each type of node so that things like "find" work reliably check-in: 9e96bce564 user: rkeene tags: tcl-ops
05:30
Simplified user fsuid switching check-in: 9562d42ae1 user: rkeene tags: tcl-ops
05:02
Minor re-ordering so that FUSE things can be "near" each other check-in: f4e6b62dfb user: rkeene tags: tcl-ops
Changes

Modified appfsd.c from [405b834b47] to [1dcdd9bb28].

   499    499   	int tcl_ret;
   500    500   
   501    501   	interp = appfs_TclInterp();
   502    502   	if (interp == NULL) {
   503    503   		return(-EIO);
   504    504   	}
   505    505   
   506         -	appfs_simulate_user_fs_enter();
   507         -
   508    506   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path);
   509         -
   510         -	appfs_simulate_user_fs_leave();
   511         -
   512    507   	if (tcl_ret != TCL_OK) {
   513    508   		APPFS_DEBUG("::appfs::getattr(%s) failed.", path);
   514    509   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
   515    510   
   516    511   		return(-ENOENT);
   517    512   	}
   518    513   
................................................................................
   781    776   	if (interp == NULL) {
   782    777   		return(0);
   783    778   	}
   784    779   
   785    780   	filler(buf, ".", NULL, 0);
   786    781   	filler(buf, "..", NULL, 0);
   787    782   
   788         -	appfs_simulate_user_fs_enter();
   789         -
   790    783   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path);
   791         -
   792         -	appfs_simulate_user_fs_leave();
   793         -
   794    784   	if (tcl_ret != TCL_OK) {
   795    785   		APPFS_DEBUG("::appfs::getchildren(%s) failed.", path);
   796    786   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
   797    787   
   798    788   		return(0);
   799    789   	}
   800    790   
................................................................................
   849    839   	}
   850    840   
   851    841   	interp = appfs_TclInterp();
   852    842   	if (interp == NULL) {
   853    843   		return(-EIO);
   854    844   	}
   855    845   
   856         -	appfs_simulate_user_fs_enter();
   857         -
   858    846   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode);
   859    847   	if (tcl_ret != TCL_OK) {
   860         -		appfs_simulate_user_fs_leave();
   861         -
   862    848   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, mode);
   863    849   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
   864    850   
   865    851   		return(-EIO);
   866    852   	}
   867    853   
   868    854   	real_path = Tcl_GetStringResult(interp);
   869    855   	if (real_path == NULL) {
   870         -		appfs_simulate_user_fs_leave();
   871         -
   872    856   		return(-EIO);
   873    857   	}
   874    858   
   875    859   	APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode);
   876    860   
   877    861   	fh = open(real_path, fi->flags, 0600);
   878    862   
   879         -	appfs_simulate_user_fs_leave();
   880         -
   881    863   	if (fh < 0) {
   882    864   		return(-EIO);
   883    865   	}
   884    866   
   885    867   	fi->fh = fh;
   886    868   
   887    869   	return(0);
................................................................................
   940    922   		return(-EPERM);
   941    923   	}
   942    924   
   943    925   	if ((mode & S_IFBLK) == S_IFBLK) {
   944    926   		return(-EPERM);
   945    927   	}
   946    928   
   947         -	appfs_simulate_user_fs_enter();
   948         -
   949    929   	real_path = appfs_prepare_to_create(path);
   950    930   	if (real_path == NULL) {
   951         -		appfs_simulate_user_fs_leave();
   952         -
   953    931   		return(-EIO);
   954    932   	}
          933  +
          934  +	appfs_simulate_user_fs_enter();
   955    935   
   956    936   	mknod_ret = mknod(real_path, mode, device);
   957    937   
   958    938   	appfs_simulate_user_fs_leave();
   959    939   
   960    940   	free(real_path);
   961    941   
................................................................................
   976    956   		return(-EPERM);
   977    957   	}
   978    958   
   979    959   	if ((mode & S_IFBLK) == S_IFBLK) {
   980    960   		return(-EPERM);
   981    961   	}
   982    962   
   983         -	appfs_simulate_user_fs_enter();
   984         -
   985    963   	real_path = appfs_prepare_to_create(path);
   986    964   	if (real_path == NULL) {
   987         -		appfs_simulate_user_fs_leave();
   988         -
   989    965   		return(-EIO);
   990    966   	}
          967  +
          968  +	appfs_simulate_user_fs_enter();
   991    969   
   992    970   	fd = creat(real_path, mode);
   993    971   
   994    972   	appfs_simulate_user_fs_leave();
   995    973   
   996    974   	free(real_path);
   997    975   
................................................................................
  1037   1015   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1038   1016   
  1039   1017   	interp = appfs_TclInterp();
  1040   1018   	if (interp == NULL) {
  1041   1019   		return(-EIO);
  1042   1020   	}
  1043   1021   
  1044         -	appfs_simulate_user_fs_enter();
  1045         -
  1046   1022   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::unlinkpath", path);
  1047         -
  1048         -	appfs_simulate_user_fs_leave();
  1049         -
  1050   1023   	if (tcl_ret != TCL_OK) {
  1051   1024   		APPFS_DEBUG("::appfs::unlinkpath(%s) failed.", path);
  1052   1025   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
  1053   1026   
  1054   1027   		return(-EIO);
  1055   1028   	}
  1056   1029   
................................................................................
  1059   1032   
  1060   1033   static int appfs_fuse_mkdir(const char *path, mode_t mode) {
  1061   1034   	char *real_path;
  1062   1035   	int mkdir_ret;
  1063   1036   
  1064   1037   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1065   1038   
  1066         -	appfs_simulate_user_fs_enter();
  1067   1039   
  1068   1040   	real_path = appfs_prepare_to_create(path);
  1069   1041   	if (real_path == NULL) {
  1070         -		appfs_simulate_user_fs_leave();
  1071         -
  1072   1042   		return(-EIO);
  1073   1043   	}
         1044  +
         1045  +	appfs_simulate_user_fs_enter();
  1074   1046   
  1075   1047   	mkdir_ret = mkdir(real_path, mode);
  1076   1048   
  1077   1049   	appfs_simulate_user_fs_leave();
  1078   1050   
  1079   1051   	free(real_path);
  1080   1052   
................................................................................
  1095   1067   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1096   1068   
  1097   1069   	interp = appfs_TclInterp();
  1098   1070   	if (interp == NULL) {
  1099   1071   		return(-EIO);
  1100   1072   	}
  1101   1073   
  1102         -	appfs_simulate_user_fs_enter();
  1103         -
  1104   1074   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, "write");
  1105   1075   	if (tcl_ret != TCL_OK) {
  1106         -		appfs_simulate_user_fs_leave();
  1107         -
  1108   1076   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, "write");
  1109   1077   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
  1110   1078   
  1111   1079   		return(-EIO);
  1112   1080   	}
  1113   1081   
  1114   1082   	real_path = Tcl_GetStringResult(interp);
  1115   1083   	if (real_path == NULL) {
  1116         -		appfs_simulate_user_fs_leave();
  1117         -
  1118   1084   		return(-EIO);
  1119   1085   	}
         1086  +
         1087  +	appfs_simulate_user_fs_enter();
  1120   1088   
  1121   1089   	chmod_ret = chmod(real_path, mode);
  1122   1090   
  1123   1091   	appfs_simulate_user_fs_leave();
  1124   1092   
  1125   1093   	return(chmod_ret);
  1126   1094   }

Modified appfsd.tcl from [649eb3a6a1] to [969f157ddb].

   119    119   			"noarch" - "none" - "any" - "all" {
   120    120   				return "noarch"
   121    121   			}
   122    122   		}
   123    123   
   124    124   		return -code error "Unable to normalize CPU: $cpu"
   125    125   	}
          126  +
          127  +	proc _as_user {code} {
          128  +		::appfsd::simulate_user_fs_enter
          129  +
          130  +		set retcode [catch [list uplevel $code] retstr]
          131  +
          132  +		::appfsd::simulate_user_fs_leave
          133  +
          134  +		return -code $retcode $retstr
          135  +	}
   126    136   
   127    137   	proc init {} {
   128    138   		if {[info exists ::appfs::init_called]} {
   129    139   			return
   130    140   		}
   131    141   
   132    142   		# Force [parray] to be loaded
................................................................................
   156    166   		# Create indexes
   157    167   		db eval {CREATE INDEX IF NOT EXISTS sites_index ON sites (hostname);}
   158    168   		db eval {CREATE INDEX IF NOT EXISTS packages_index ON packages (hostname, package, version, os, cpuArch);}
   159    169   		db eval {CREATE INDEX IF NOT EXISTS files_index ON files (package_sha1, file_name, file_directory);}
   160    170   	}
   161    171   
   162    172   	proc download {hostname hash {method sha1}} {
   163         -		::appfsd::simulate_user_fs_leave
   164         -
   165    173   		set url [_construct_url $hostname $hash $method]
   166    174   		set file [_cachefile $url $hash]
   167    175   
   168         -		::appfsd::simulate_user_fs_enter
   169         -
   170    176   		if {![file exists $file]} {
   171    177   			return -code error "Unable to fetch (file does not exist: $file)"
   172    178   		}
   173    179   
   174    180   		return $file
   175    181   	}
   176    182   
................................................................................
   464    470   				catch {
   465    471   					::appfs::getpkgmanifest $pathinfo(hostname) $pathinfo(package_sha1)
   466    472   				}
   467    473   
   468    474   				set retval [::appfs::db eval {SELECT DISTINCT file_name FROM files WHERE package_sha1 = $pathinfo(package_sha1) AND file_directory = $pathinfo(file);}]
   469    475   
   470    476   				if {[info exists pathinfo(package)] && [info exists pathinfo(hostname)] && [info exists pathinfo(file)]} {
   471         -					set dir [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)]
   472         -					set whiteoutdir [string range [_whiteoutpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)] 0 end-15]
          477  +					_as_user {
          478  +						set dir [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)]
          479  +						set whiteoutdir [string range [_whiteoutpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)] 0 end-15]
   473    480   
   474         -					foreach file [glob -nocomplain -tails -directory $whiteoutdir {{.,}*.APPFS.WHITEOUT}] {
   475         -						set remove [string range $file 0 end-15]
   476         -						set idx [lsearch -exact $retval $remove]
   477         -						if {$idx != -1} {
   478         -							set retval [lreplace $retval $idx $idx]
   479         -						}
   480         -					}
   481         -
   482         -					foreach file [glob -nocomplain -tails -directory $dir -types {d f l p s} {{.,}*}] {
   483         -						if {$file == "." || $file == ".."} {
   484         -							continue
          481  +						foreach file [glob -nocomplain -tails -directory $whiteoutdir {{.,}*.APPFS.WHITEOUT}] {
          482  +							set remove [string range $file 0 end-15]
          483  +							set idx [lsearch -exact $retval $remove]
          484  +							if {$idx != -1} {
          485  +								set retval [lreplace $retval $idx $idx]
          486  +							}
   485    487   						}
   486    488   
   487         -						if {$file == ".APPFS.WHITEOUT"} {
   488         -							continue
          489  +						foreach file [glob -nocomplain -tails -directory $dir -types {d f l p s} {{.,}*}] {
          490  +							if {$file == "." || $file == ".."} {
          491  +								continue
          492  +							}
          493  +
          494  +							if {$file == ".APPFS.WHITEOUT"} {
          495  +								continue
          496  +							}
          497  +
          498  +							if {[lsearch -exact $retval $file] != -1} {
          499  +								continue
          500  +							}
          501  +
          502  +							lappend retval $file
   489    503   						}
   490         -
   491         -						if {[lsearch -exact $retval $file] != -1} {
   492         -							continue
   493         -						}
   494         -
   495         -						lappend retval $file
   496    504   					}
   497    505   				}
   498    506   
   499    507   				return $retval
   500    508   			}
   501    509   		}
   502    510   
................................................................................
   511    519   			::appfs::getindex $pathinfo(hostname)
   512    520   			::appfs::getpkgmanifest $pathinfo(hostname) $pathinfo(package_sha1)
   513    521   		}
   514    522   
   515    523   		switch -- $pathinfo(_type) {
   516    524   			"toplevel" {
   517    525   				set retval(type) directory
   518         -				set retval(childcount) 2;
          526  +				set retval(childcount) 2
   519    527   			}
   520    528   			"sites" {
   521    529   				set check [::appfs::db onecolumn {SELECT 1 FROM packages WHERE hostname = $pathinfo(hostname);}]
   522    530   				if {$check == "1"} {
   523    531   					set retval(type) directory
   524    532   					set retval(childcount) 2;
   525    533   				}
................................................................................
   564    572   
   565    573   				set retval(localpath) $localpath
   566    574   				set retval(whiteoutpath) $whiteoutpath
   567    575   
   568    576   				if {[file exists $localpath]} {
   569    577   					set retval(is_localfile) 1
   570    578   					catch {
   571         -						file lstat $localpath localpathinfo
          579  +						_as_user {
          580  +							file lstat $localpath localpathinfo
          581  +						}
   572    582   						set retval(time) $localpathinfo(mtime)
   573    583   
   574    584   						switch -- $localpathinfo(type) {
   575    585   							"directory" {
   576    586   								set retval(type) "directory"
   577    587   								set retval(childcount) 2
   578    588   							}
   579    589   							"file" {
   580    590   								set retval(type) "file"
   581    591   								set retval(size) $localpathinfo(size)
   582         -								if {[file executable $localpath]} {
   583         -									set retval(perms) "x"
   584         -								} else {
   585         -									set retval(perms) ""
          592  +								_as_user {
          593  +									if {[file executable $localpath]} {
          594  +										set retval(perms) "x"
          595  +									} else {
          596  +										set retval(perms) ""
          597  +									}
   586    598   								}
   587    599   							}
   588    600   							"link" {
   589    601   								set retval(type) "symlink"
   590         -								set retval(source) [file readlink $localpath]
          602  +
          603  +								_as_user {
          604  +									set retval(source) [file readlink $localpath]
          605  +								}
   591    606   							}
   592    607   							"fifo" {
   593    608   								# Capitalized so that the first char is unique
   594    609   								set retval(type) "Fifo"
   595    610   							}
   596    611   							"socket" {
   597    612   								# Capitalized so that the first char is unique
................................................................................
   651    666   		if {$pkgpathinfo(file_sha1) == ""} {
   652    667   			return -code error "No such file or directory"
   653    668   		}
   654    669   
   655    670   		set localcachefile [download $pathinfo(hostname) $pkgpathinfo(file_sha1)]
   656    671   
   657    672   		if {$mode == "write"} {
   658         -			set tmplocalpath "${localpath}.[expr rand()][clock clicks]"
          673  +			_as_user {
          674  +				set tmplocalpath "${localpath}.[expr rand()][clock clicks]"
   659    675   
   660         -			set failed 0
   661         -			if {[catch {
   662         -				file mkdir [file dirname $localpath]
   663         -				file copy -force -- $localcachefile $tmplocalpath
          676  +				set failed 0
          677  +				if {[catch {
          678  +					file mkdir [file dirname $localpath]
          679  +					file copy -force -- $localcachefile $tmplocalpath
   664    680   
   665         -				if {$pkgpathinfo(perms) == "x"} {
   666         -					file attributes $tmplocalpath -permissions +x
          681  +					if {$pkgpathinfo(perms) == "x"} {
          682  +						file attributes $tmplocalpath -permissions +x
          683  +					}
          684  +
          685  +					file rename -force -- $tmplocalpath $localpath
          686  +				} err]} {
          687  +					set failed 1
   667    688   				}
   668         -
   669         -				file rename -force -- $tmplocalpath $localpath
   670         -			} err]} {
   671         -				set failed 1
   672         -			}
   673         -			catch {
   674         -				file delete -force -- $tmplocalpath
          689  +				catch {
          690  +					file delete -force -- $tmplocalpath
          691  +				}
   675    692   			}
   676    693   
   677    694   			if {$failed} {
   678    695   				return -code error $err
   679    696   			}
   680    697   
   681    698   			return $localpath
................................................................................
   719    736   			}
   720    737   		}
   721    738   
   722    739   		set filename [localpath $path]
   723    740   
   724    741   		set dirname [file dirname $filename]
   725    742   
   726         -		file mkdir $dirname
          743  +		_as_user {
          744  +			file mkdir $dirname
          745  +		}
   727    746   
   728    747   		return $filename
   729    748   	}
   730    749   
   731    750   	proc unlinkpath {path} {
   732    751   		array set pathattrs [exists $path]
   733    752   
................................................................................
   742    761   				set children [getchildren $path]
   743    762   
   744    763   				if {[llength $children] != 0} {
   745    764   					return -code error "Asked to delete non-empty directory"
   746    765   				}
   747    766   			}
   748    767   
   749         -			file delete -force -- $localpath
          768  +			_as_user {
          769  +				file delete -force -- $localpath
          770  +			}
   750    771   		} elseif {[info exists pathattrs(is_remotefile)]} {
   751    772   			if {$pathattrs(type) == "directory"} {
   752    773   				set children [getchildren $path]
   753    774   
   754    775   				if {[llength $children] != 0} {
   755    776   					return -code error "Asked to delete non-empty directory"
   756    777   				}
................................................................................
   757    778   			}
   758    779   		} else {
   759    780   			return -code error "Unknown if file is remote or local !?"
   760    781   		}
   761    782   
   762    783   		set whiteoutfile $pathattrs(whiteoutpath)
   763    784   		set whiteoutdir [file dirname $whiteoutfile]
   764         -		file mkdir $whiteoutdir
   765         -		close [open $whiteoutfile w]
          785  +
          786  +		_as_user {
          787  +			file mkdir $whiteoutdir
          788  +			close [open $whiteoutfile w]
          789  +		}
   766    790   	}
   767    791   }