490e0de548
Import libpuffs and our port of libpuffs. The port was done as part of GSoC 2011 FUSE project, done by Evgeniy Ivanov. The librefuse import did not require any porting efforts. Libpuffs has been modified to understand our VFS-FS protocol and translate between that and PUFFS. As an example that it works, fuse-ntfs-3g from pkgsrc can be compiled and used to mount ntfs partitions: mount -t ntfs-3g <device> <mountpoint> FUSE only works with the asynchronous version of VFS. See <docs/UPDATING> on how to run AVFS. This patch further includes some changes to mount(1) and mount(2) so it's possible to use file systems provided by pkgsrc (note: manual modifications to /etc/system.conf are still needed. There has been made an exception for fuse-ntfs-3g, so it already as an entry).
194 lines
4.3 KiB
C
194 lines
4.3 KiB
C
#include <sys/cdefs.h>
|
|
#include "namespace.h"
|
|
#include <lib.h>
|
|
|
|
#include <string.h>
|
|
#include <sys/mount.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include <minix/syslib.h>
|
|
#include <minix/rs.h>
|
|
#include <paths.h>
|
|
#include <unistd.h>
|
|
#define OK 0
|
|
|
|
#ifdef __weak_alias
|
|
__weak_alias(mount, _mount)
|
|
__weak_alias(umount, _umount)
|
|
__weak_alias(umount2, _umount2)
|
|
#endif
|
|
|
|
#define FSDEFAULT "mfs"
|
|
|
|
static char fspath[] = "/sbin/:/usr/pkg/bin/"; /* Must include trailing '/' */
|
|
|
|
PRIVATE int rs_down(char *label)
|
|
{
|
|
char cmd[200];
|
|
if(strlen(_PATH_SERVICE)+strlen(label)+50 >= sizeof(cmd))
|
|
return -1;
|
|
sprintf(cmd, _PATH_SERVICE " down '%s'", label);
|
|
return system(cmd);
|
|
}
|
|
|
|
PUBLIC int mount(special, name, mountflags, type, args)
|
|
char *name, *special, *type, *args;
|
|
int mountflags;
|
|
{
|
|
int r;
|
|
message m;
|
|
struct stat statbuf;
|
|
char label[16];
|
|
char path[PATH_MAX];
|
|
char cmd[200];
|
|
char *p;
|
|
int reuse = 0;
|
|
int use_existing = 0;
|
|
|
|
/* Default values. */
|
|
if (type == NULL) type = __UNCONST(FSDEFAULT);
|
|
if (args == NULL) args = __UNCONST("");
|
|
reuse = 0;
|
|
memset(path, '\0', sizeof(path));
|
|
|
|
/* Check mount flags */
|
|
if(mountflags & MS_REUSE) {
|
|
reuse = 1;
|
|
mountflags &= ~MS_REUSE; /* Temporary: turn off to not confuse VFS */
|
|
}
|
|
|
|
if(mountflags & MS_EXISTING) {
|
|
use_existing = 1;
|
|
mountflags &= ~MS_EXISTING; /* Temporary: turn off to not confuse VFS */
|
|
}
|
|
|
|
/* Make a label for the file system process. This label must be unique and
|
|
* may currently not exceed 16 characters including terminating null. For
|
|
* requests with an associated block device, we use the last path component
|
|
* name of the block special file (truncated to 12 characters, which is
|
|
* hopefully enough). For requests with no associated block device, we use
|
|
* the device number and inode of the mount point, in hexadecimal form.
|
|
*/
|
|
if (!use_existing) {
|
|
if (special) {
|
|
p = strrchr(special, '/');
|
|
p = p ? p + 1 : special;
|
|
if (strchr(p, '\'')) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
sprintf(label, "fs_%.12s", p);
|
|
} else {
|
|
if (stat(name, &statbuf) < 0) return -1;
|
|
sprintf(label, "fs_%04x%llx", statbuf.st_dev, statbuf.st_ino);
|
|
}
|
|
} else {
|
|
/* label to long? */
|
|
if (strlen(type) < 16) {
|
|
sprintf(label, "%s", type);
|
|
} else {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Tell VFS that we are passing in a 16-byte label. */
|
|
mountflags |= MS_LABEL16;
|
|
|
|
/* Sanity check on user input. */
|
|
if(strchr(args, '\'')) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
/* start the fs-server if not using existing one */
|
|
if (!use_existing) {
|
|
/* See if the given type is even remotely valid. */
|
|
|
|
char *testpath;
|
|
testpath = strtok(fspath, ":");
|
|
|
|
do {
|
|
if (strlen(testpath) + strlen(type) >= sizeof(path)) {
|
|
errno = E2BIG;
|
|
return(-1);
|
|
}
|
|
|
|
strcpy(path, testpath);
|
|
strcat(path, type);
|
|
|
|
if (access(path, F_OK) == 0) break;
|
|
|
|
} while ((testpath = strtok(NULL, ":")) != NULL);
|
|
|
|
if (testpath == NULL) {
|
|
/* We were not able to find type somewhere in "fspath" */
|
|
errno = EINVAL;
|
|
return(-1);
|
|
}
|
|
|
|
if (strlen(_PATH_SERVICE) + strlen(path) + strlen(label) +
|
|
strlen(args) + 50 >= sizeof(cmd)) {
|
|
errno = E2BIG;
|
|
return -1;
|
|
}
|
|
|
|
sprintf(cmd, _PATH_SERVICE " %sup %s -label '%s' -args '%s %s %s%s'",
|
|
reuse ? "-r ": "", path, label, special, name,
|
|
args[0] ? "-o " : "", args);
|
|
|
|
if ((r = system(cmd)) != 0) {
|
|
fprintf(stderr, "mount: couldn't run %s\n", cmd);
|
|
errno = r;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Now perform mount(). */
|
|
m.m1_i1 = special ? strlen(special) + 1 : 0;
|
|
m.m1_i2 = strlen(name) + 1;
|
|
m.m1_i3 = mountflags;
|
|
m.m1_p1 = special;
|
|
m.m1_p2 = name;
|
|
m.m1_p3 = label;
|
|
r = _syscall(VFS_PROC_NR, MOUNT, &m);
|
|
|
|
if (r != OK && !use_existing) {
|
|
/* If mount() failed, tell RS to shutdown FS process.
|
|
* No error check - won't do anything with this error anyway.
|
|
*/
|
|
rs_down(label);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
PUBLIC int umount(name)
|
|
_CONST char *name;
|
|
{
|
|
return umount2(name, 0);
|
|
}
|
|
|
|
PUBLIC int umount2(name, flags)
|
|
_CONST char *name;
|
|
int flags;
|
|
{
|
|
message m;
|
|
int r;
|
|
|
|
|
|
_loadname(name, &m);
|
|
r = _syscall(VFS_PROC_NR, UMOUNT, &m);
|
|
|
|
/* don't shut down the driver when exist flag is set */
|
|
if (!(flags & MS_EXISTING)) {
|
|
if (r == OK) {
|
|
/* VFS returns the label of the unmounted file system in the reply.
|
|
* As of writing, the size of the m3_ca1 field is 16 bytes.
|
|
*/
|
|
rs_down(m.m3_ca1);
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|