Пример #1
0
int mmount(device *d,const char *targ,unsigned mntops,const void *data){
	char name[PATH_MAX + 1];
	char *rname;

	if(d == NULL || targ == NULL){ // mntops may be NULL
		diag("Provided NULL arguments\n");
		return -1;
	}
	if(!d->mnttype){
		diag("%s does not have a filesystem signature\n",d->name);
		return -1;
	}
	if(strcmp(d->mnttype,"zfs") == 0){
		return mount_zfs(d,targ,mntops,data);
	}
	if(mnttype_aggregablep(d->mnttype)){
		diag("not a mountable filesystem: %s \n",d->mnttype);
		return -1;
	}
	if(growlight_target){
		if(strncmp(targ,growlight_target,strlen(growlight_target)) == 0){
			if(make_parent_directories(targ)){
				diag("Couldn't make parents of %s\n",targ);
			}
		}
	}
	if((rname = realpath(targ,NULL)) == NULL){
		diag("Couldn't canonicalize %s (%s)\n",targ,strerror(errno));
		return -1;
	}
	if(string_included_p(&d->mnt,rname)){
		diag("%s is already mounted at %s\n",d->name,targ);
		free(rname);
		return -1;
	}
	if(growlight_target){
		if(strncmp(rname,growlight_target,strlen(growlight_target)) == 0){
			if(make_parent_directories(rname)){
				diag("Couldn't make parents of %s\n",rname);
			}
		}
	}
	snprintf(name,sizeof(name),"/dev/%s",d->name);
	// Use the original path for the actual mount
	if(mount(name,targ,d->mnttype,mntops,data)){
		diag("Error mounting %s (%u) at %s (%s?)\n",
				name,mntops,targ,strerror(errno));
		free(rname);
		return -1;
	}
	diag("Mounted %s at %s\n",d->name,targ);
	free(rname);
	return 0;
}
Пример #2
0
void FilesystemKVS::make_parent_directories(const std::string &path) {
  size_t lastDirDelim= path.rfind('/');
  if (lastDirDelim == std::string::npos) throw std::runtime_error("make_parent_directories " + path);
  std::string subpath = path.substr(0, lastDirDelim);
  if (0 == mkdir(subpath.c_str(), 0777) || errno == EEXIST) return;
  
  if (errno == ENOENT) {
    make_parent_directories(subpath);
    if (0 == mkdir(subpath.c_str(), 0777) || errno == EEXIST) return;
  }

  throw std::runtime_error("make_parent_directories " + path);
}
Пример #3
0
/// \brief Set key to value
/// \param key
/// \param value
void FilesystemKVS::set(const std::string &key, const std::string &value) {
  std::string path = value_key_to_path(key); 
  FILE *out = fopen(path.c_str(), "wb");
  if (!out) {
    make_parent_directories(path);
    out = fopen(path.c_str(), "wb");
    if (!out) throw std::runtime_error("fopen " +  path);
  }
  if (value.size()) {
    if (1 != fwrite(&value[0], value.size(), 1, out)) {
      fclose(out);
      throw std::runtime_error("fwrite " + path);
    }
  }
  if (m_verbose) log_f("FilesystemKVS::set(%s) wrote %zd bytes to %s", key.c_str(), value.length(), path.c_str());
  fclose(out);
}
Пример #4
0
/// Lock key.  Do not call this directly;  instead, use KVSLocker to create a scoped lock.
/// \param key
///
/// Uses flock on file that contains value.
void *FilesystemKVS::lock(const std::string &key) {
  std::string path = value_key_to_path(key); 
  FILE *f = fopen(path.c_str(), "ab");
  if (!f) {
    make_parent_directories(path);
    f = fopen(path.c_str(), "a");
    if (!f) throw std::runtime_error("fopen " +  path);
  }
  int fd= fileno(f);
  if (m_verbose) log_f("FilesystemKVS::lock(%s) about to lock %s (fd=%d)", key.c_str(), path.c_str(), fd);
  if (-1 == flock(fd, LOCK_EX)) {
    fclose(f);
    throw std::runtime_error("flock " + path);
  }
  if (m_verbose) log_f("FilesystemKVS::lock(%s) locked %s (fd=%d)", key.c_str(), path.c_str(), fd);
  return (void*)f;
}
Пример #5
0
int parse_mounts(const glightui *gui,const char *fn){
	char *mnt,*dev,*ops,*fs;
	off_t len,idx;
	char *map;
	int fd;

	if((map = map_virt_file(fn,&fd,&len)) == MAP_FAILED){
		return -1;
	}
	idx = 0;
	dev = mnt = fs = ops = NULL;
	while(idx < len){
		char buf[PATH_MAX + 1];
		struct statvfs vfs;
		struct stat st;
		device *d;
		char *rp;
		int r;

		free(dev); free(mnt); free(fs); free(ops);
		if((r = parse_mount(map + idx,len - idx,&dev,&mnt,&fs,&ops)) < 0){
			goto err;
		}
		idx += r;
		if(statvfs(mnt,&vfs)){
			int skip = 0;

			// We might have mounted a new target atop or above an
			// already existing one, in which case we'll need
			// possibly recreate the directory structure on the
			// newly-mounted filesystem.
			if(growlight_target){
				if(strncmp(mnt,growlight_target,strlen(growlight_target)) == 0){
					if(make_parent_directories(mnt) == 0){
						skip = 1;
					} // FIXME else remount? otherwise writes
					// go to new filesystem rather than old...?
				}
			}
			if(!skip){
				diag("Couldn't stat fs %s (%s?)\n",mnt,strerror(errno));
				r = -1;
				continue;
			}
		}
		if(*dev != '/'){ // have to get zfs's etc
			if(fstype_virt_p(fs)){
				continue;
			}
			if((d = lookup_device(dev)) == NULL){
				verbf("virtfs %s at %s\n",fs,mnt);
				continue;
			}
		}else{
			rp = dev;
			if(lstat(rp,&st) == 0){
				if(S_ISLNK(st.st_mode)){
					if((r = readlink(dev,buf,sizeof(buf))) < 0){
						diag("Couldn't deref %s (%s?)\n",dev,strerror(errno));
						continue;
					}
					if((size_t)r >= sizeof(buf)){
						diag("Name too long for %s (%d?)\n",dev,r);
						continue;
					}
					buf[r] = '\0';
					rp = buf;
				}
			}
			if((d = lookup_device(rp)) == NULL){
				continue;
			}
		}
		free(dev);
		dev = NULL;
		if(d->mnttype && strcmp(d->mnttype,fs)){
			diag("Already had mounttype for %s: %s (got %s)\n",
					d->name,d->mnttype,fs);
			free(d->mnttype);
			d->mnttype = NULL;
			free_stringlist(&d->mntops);
			free_stringlist(&d->mnt);
			d->mnttype = fs;
		}else{
			free(fs);
		}
		fs = NULL;
		if(add_string(&d->mnt,mnt)){
			goto err;
		}
		if(add_string(&d->mntops,ops)){
			goto err;
		}
		d->mntsize = (uintmax_t)vfs.f_bsize * vfs.f_blocks;
		if(d->layout == LAYOUT_PARTITION){
			d = d->partdev.parent;
		}
		d->uistate = gui->block_event(d,d->uistate);
		if(growlight_target){
			if(strcmp(mnt,growlight_target) == 0){
				mount_target();
			}
		}
	}
	free(mnt); free(fs); free(ops);
	mnt = fs = ops = NULL;
	munmap_virt(map,len);
	close(fd);
	return 0;

err:
	free(dev); free(mnt); free(fs); free(ops);
	munmap_virt(map,len);
	close(fd);
	return -1;
}