Check-in [d3bb0824ec]
Overview
Comment:More work towards getting the user multiplexing right
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tcl-ops
Files: files | file ages | folders
SHA1:d3bb0824ec6b5debb2b5c58a4e7c5060f7f73b4e
User & Date: rkeene on 2014-11-10 04:22:15
Other Links: manifest | tags
Context
2014-11-10
04:52
Added initial PKI support check-in: 9279433b2f user: rkeene tags: tcl-ops
04:22
More work towards getting the user multiplexing right check-in: d3bb0824ec user: rkeene tags: tcl-ops
03:34
Updated to cache last home directory looked up and to setfsuid()/setfsgid() before accessing the filesystem so that we may be the right user check-in: 63e41c262c user: rkeene tags: tcl-ops
Changes

Modified appfsd.c from [9cae19dbb7] to [d452ee8ca8].

429
430
431
432
433
434
435












436
437
438
439
440
441
442
...
467
468
469
470
471
472
473
474


475



476
477
478
479
480
481
482
...
555
556
557
558
559
560
561
562

563
564

565
566
567
568
569
570
571
...
705
706
707
708
709
710
711




712




713
714
715
716
717
718
719
...
734
735
736
737
738
739
740
741


742



743
744
745
746
747
748
749
....
1145
1146
1147
1148
1149
1150
1151


1152
1153
1154
1155
1156
1157
1158
		Tcl_IncrRefCount(last_homedir_obj);
	}

       	Tcl_SetObjResult(interp, homedir_obj);

        return(TCL_OK);
}













/*
 * Generate an inode for a given path.  The inode should be computed in such
 * a way that it is unlikely to be duplicated and remains the same for a given
 * file
 */
static long long appfs_get_path_inode(const char *path) {
................................................................................
	static __thread Tcl_Obj *attr_key_type = NULL, *attr_key_perms = NULL, *attr_key_size = NULL, *attr_key_time = NULL, *attr_key_source = NULL, *attr_key_childcount = NULL, *attr_key_packaged = NULL;
	int tcl_ret;

	interp = appfs_TclInterp();
	if (interp == NULL) {
		return(-EIO);
	}



	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path);



	if (tcl_ret != TCL_OK) {
		APPFS_DEBUG("::appfs::getattr(%s) failed.", path);
		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));

		return(-ENOENT);
	}

................................................................................
					pathinfo->typeinfo.symlink.size = attr_value_int;
					pathinfo->typeinfo.symlink.source[attr_value_int] = '\0';

					memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int);
				}
			}
			break;
		case 'p': /* pipe/fifo */

			break;
		case 'S': /* UNIX domain socket */

			break;
		default:
			return(-EIO);
	}

	Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value);
	if (attr_value != NULL) {
................................................................................
			break;
		case APPFS_PATHTYPE_SYMLINK:
			stbuf->st_mode = S_IFLNK | 0555;
			stbuf->st_nlink = 1;
			stbuf->st_size = pathinfo.typeinfo.symlink.size;
			break;
		case APPFS_PATHTYPE_SOCKET:




		case APPFS_PATHTYPE_FIFO:




		case APPFS_PATHTYPE_INVALID:
			retval = -ENOENT;

			break;
	}

	if (pathinfo.packaged) {
................................................................................
	interp = appfs_TclInterp();
	if (interp == NULL) {
		return(0);
	}

	filler(buf, ".", NULL, 0);
	filler(buf, "..", NULL, 0);



	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path);



	if (tcl_ret != TCL_OK) {
		APPFS_DEBUG("::appfs::getchildren(%s) failed.", path);
		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));

		return(0);
	}

................................................................................
#ifdef USE_TCL_STUBS
	if (Tcl_InitStubs(interp, TCL_VERSION, 0) == 0L) {
		return(TCL_ERROR);
	}
#endif

	Tcl_CreateObjCommand(interp, "appfsd::get_homedir", tcl_appfs_get_homedir, NULL, NULL);



	Tcl_PkgProvide(interp, "appfsd", "1.0");

	return(TCL_OK);
}

/*







>
>
>
>
>
>
>
>
>
>
>
>







 








>
>

>
>
>







 







|
>


>







 







>
>
>
>

>
>
>
>







 








>
>

>
>
>







 







>
>







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
...
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
....
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
		Tcl_IncrRefCount(last_homedir_obj);
	}

       	Tcl_SetObjResult(interp, homedir_obj);

        return(TCL_OK);
}

static int tcl_appfs_simulate_user_fs_enter(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	appfs_simulate_user_fs_enter();

	return(TCL_OK);
}

static int tcl_appfs_simulate_user_fs_leave(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	appfs_simulate_user_fs_leave();

	return(TCL_OK);
}

/*
 * Generate an inode for a given path.  The inode should be computed in such
 * a way that it is unlikely to be duplicated and remains the same for a given
 * file
 */
static long long appfs_get_path_inode(const char *path) {
................................................................................
	static __thread Tcl_Obj *attr_key_type = NULL, *attr_key_perms = NULL, *attr_key_size = NULL, *attr_key_time = NULL, *attr_key_source = NULL, *attr_key_childcount = NULL, *attr_key_packaged = NULL;
	int tcl_ret;

	interp = appfs_TclInterp();
	if (interp == NULL) {
		return(-EIO);
	}

	appfs_simulate_user_fs_enter();

	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path);

	appfs_simulate_user_fs_leave();

	if (tcl_ret != TCL_OK) {
		APPFS_DEBUG("::appfs::getattr(%s) failed.", path);
		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));

		return(-ENOENT);
	}

................................................................................
					pathinfo->typeinfo.symlink.size = attr_value_int;
					pathinfo->typeinfo.symlink.source[attr_value_int] = '\0';

					memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int);
				}
			}
			break;
		case 'F': /* pipe/fifo */
			pathinfo->type = APPFS_PATHTYPE_FIFO;
			break;
		case 'S': /* UNIX domain socket */
			pathinfo->type = APPFS_PATHTYPE_SOCKET;
			break;
		default:
			return(-EIO);
	}

	Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value);
	if (attr_value != NULL) {
................................................................................
			break;
		case APPFS_PATHTYPE_SYMLINK:
			stbuf->st_mode = S_IFLNK | 0555;
			stbuf->st_nlink = 1;
			stbuf->st_size = pathinfo.typeinfo.symlink.size;
			break;
		case APPFS_PATHTYPE_SOCKET:
			stbuf->st_mode = S_IFSOCK | 0555;
			stbuf->st_nlink = 1;
			stbuf->st_size = 0;
			break;
		case APPFS_PATHTYPE_FIFO:
			stbuf->st_mode = S_IFIFO | 0555;
			stbuf->st_nlink = 1;
			stbuf->st_size = 0;
			break;
		case APPFS_PATHTYPE_INVALID:
			retval = -ENOENT;

			break;
	}

	if (pathinfo.packaged) {
................................................................................
	interp = appfs_TclInterp();
	if (interp == NULL) {
		return(0);
	}

	filler(buf, ".", NULL, 0);
	filler(buf, "..", NULL, 0);

	appfs_simulate_user_fs_enter();

	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path);

	appfs_simulate_user_fs_leave();

	if (tcl_ret != TCL_OK) {
		APPFS_DEBUG("::appfs::getchildren(%s) failed.", path);
		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));

		return(0);
	}

................................................................................
#ifdef USE_TCL_STUBS
	if (Tcl_InitStubs(interp, TCL_VERSION, 0) == 0L) {
		return(TCL_ERROR);
	}
#endif

	Tcl_CreateObjCommand(interp, "appfsd::get_homedir", tcl_appfs_get_homedir, NULL, NULL);
	Tcl_CreateObjCommand(interp, "appfsd::simulate_user_fs_enter", tcl_appfs_simulate_user_fs_enter, NULL, NULL);
	Tcl_CreateObjCommand(interp, "appfsd::simulate_user_fs_leave", tcl_appfs_simulate_user_fs_leave, NULL, NULL);

	Tcl_PkgProvide(interp, "appfsd", "1.0");

	return(TCL_OK);
}

/*

Modified appfsd.tcl from [3ec5e46dc5] to [af80dbf637].

155
156
157
158
159
160
161


162
163


164
165
166
167
168
169
170
...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
...
580
581
582
583
584
585
586








587
588
589
590
591
592
593
...
720
721
722
723
724
725
726
727
728
729
730


731

732
733
734
735

736
737
738
739
740
741


742
743

744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
		# Create indexes
		db eval {CREATE INDEX IF NOT EXISTS sites_index ON sites (hostname);}
		db eval {CREATE INDEX IF NOT EXISTS packages_index ON packages (hostname, package, version, os, cpuArch);}
		db eval {CREATE INDEX IF NOT EXISTS files_index ON files (package_sha1, file_name, file_directory);}
	}

	proc download {hostname hash {method sha1}} {


		set url [_construct_url $hostname $hash $method]
		set file [_cachefile $url $hash]



		if {![file exists $file]} {
			return -code error "Unable to fetch (file does not exist: $file)"
		}

		return $file
	}
................................................................................
						set remove [string range $file 0 end-15]
						set idx [lsearch -exact $retval $remove]
						if {$idx != -1} {
							set retval [lreplace $retval $idx $idx]
						}
					}

					foreach file [glob -nocomplain -tails -directory $dir -types {d f l} {{.,}*}] {
						if {$file == "." || $file == ".."} {
							continue
						}

						if {$file == ".APPFS.WHITEOUT"} {
							continue
						}
................................................................................
									set retval(perms) ""
								}
							}
							"link" {
								set retval(type) "symlink"
								set retval(source) [file readlink $localpath]
							}








						}
					} err
				} else {
					if {![file exists $whiteoutpath]} {
						set retval(is_remotefile) 1

						set work [split $pathinfo(file) "/"]
................................................................................

		if {![info exists pathattrs(packaged)]} {
			return -code error "invalid type"
		}

		set localpath $pathattrs(localpath)

		set whiteout 0
		set isdirectory 0
		if {[info exists pathattrs(is_localfile)]} {
			if {[file isdirectory $localpath]} {


				set whiteout 1


				set isdirectory 1
				set children [getchildren $path]
			}

			file delete -force -- $localpath
		} elseif {[info exists pathattrs(is_remotefile)]} {
			if {$pathattrs(type) == "directory"} {
				set isdirectory 1
				set children [getchildren $path]
			}



			set whiteout 1

		} else {
			return -code error "Unknown if file is remote or local !?"
		}

		if {$isdirectory} {
			if {$children != [list]} {
				return -code error "Asked to delete non-empty directory"
			}
		}

		if {$whiteout} {
			set whiteoutfile $pathattrs(whiteoutpath)
			set whiteoutdir [file dirname $whiteoutfile]
			file mkdir $whiteoutdir
			close [open $whiteoutfile w]
		}
	}
}







>
>


>
>







 







|







 







>
>
>
>
>
>
>
>







 







<
<


>
>
|
>
|
<
<

>



<

|
>
>
|
<
>




<
<
<
<
<
<
<
|
|
|
|
|
|
<
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
...
732
733
734
735
736
737
738


739
740
741
742
743
744
745


746
747
748
749
750

751
752
753
754
755

756
757
758
759
760







761
762
763
764
765
766

		# Create indexes
		db eval {CREATE INDEX IF NOT EXISTS sites_index ON sites (hostname);}
		db eval {CREATE INDEX IF NOT EXISTS packages_index ON packages (hostname, package, version, os, cpuArch);}
		db eval {CREATE INDEX IF NOT EXISTS files_index ON files (package_sha1, file_name, file_directory);}
	}

	proc download {hostname hash {method sha1}} {
		::appfsd::simulate_user_fs_leave

		set url [_construct_url $hostname $hash $method]
		set file [_cachefile $url $hash]

		::appfsd::simulate_user_fs_enter

		if {![file exists $file]} {
			return -code error "Unable to fetch (file does not exist: $file)"
		}

		return $file
	}
................................................................................
						set remove [string range $file 0 end-15]
						set idx [lsearch -exact $retval $remove]
						if {$idx != -1} {
							set retval [lreplace $retval $idx $idx]
						}
					}

					foreach file [glob -nocomplain -tails -directory $dir -types {d f l p s} {{.,}*}] {
						if {$file == "." || $file == ".."} {
							continue
						}

						if {$file == ".APPFS.WHITEOUT"} {
							continue
						}
................................................................................
									set retval(perms) ""
								}
							}
							"link" {
								set retval(type) "symlink"
								set retval(source) [file readlink $localpath]
							}
							"fifo" {
								# Capitalized so that the first char is unique
								set retval(type) "Fifo"
							}
							"socket" {
								# Capitalized so that the first char is unique
								set retval(type) "Socket"
							}
						}
					} err
				} else {
					if {![file exists $whiteoutpath]} {
						set retval(is_remotefile) 1

						set work [split $pathinfo(file) "/"]
................................................................................

		if {![info exists pathattrs(packaged)]} {
			return -code error "invalid type"
		}

		set localpath $pathattrs(localpath)



		if {[info exists pathattrs(is_localfile)]} {
			if {[file isdirectory $localpath]} {
				set children [getchildren $path]

				if {[llength $children] != 0} {
					return -code error "Asked to delete non-empty directory"
				}


			}

			file delete -force -- $localpath
		} elseif {[info exists pathattrs(is_remotefile)]} {
			if {$pathattrs(type) == "directory"} {

				set children [getchildren $path]

				if {[llength $children] != 0} {
					return -code error "Asked to delete non-empty directory"
				}

			}
		} else {
			return -code error "Unknown if file is remote or local !?"
		}








		set whiteoutfile $pathattrs(whiteoutpath)
		set whiteoutdir [file dirname $whiteoutfile]
		file mkdir $whiteoutdir
		close [open $whiteoutfile w]
	}
}