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; }
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); }
/// \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); }
/// 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; }
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; }