Пример #1
0
static bool remount_partition(int fd, const char* dir) {
    if (!directory_exists(dir)) {
        return true;
    }
    std::string dev = find_mount(dir);
    if (dev.empty()) {
        return true;
    }
    if (!make_block_device_writable(dev)) {
        WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n",
                   dir, dev.c_str(), strerror(errno));
        return false;
    }
    if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) {
        WriteFdFmt(fd, "remount of %s failed: %s\n", dir, strerror(errno));
        return false;
    }
    return true;
}
Пример #2
0
int cat_file(char *pathname) {

    char *mybuf, file[3];
    int n, fd, size;
    MOUNT *mnt;

    strcat(pathname, " RD");
    fd = open_file(pathname);
    mnt=(MOUNT *)find_mount(running->cwd->dev);
    size=mnt->blksize;
    mybuf=malloc(size+1);

    while(n=myread(fd, mybuf, size)) {
        mybuf[n]=0;
        myprintf("%s", mybuf);
    }
    sprintf(file, "%d", fd);
    close_file(file);
    free(mybuf);
}
Пример #3
0
int chmod_file(char *cmd) {
    int newMod, ino, dev;
    char path[1024], mod[10];
    MINODE *mip;
    MOUNT *mnt;

    sscanf(cmd, "%s %s", mod, path);
    newMod=strtol(mod, NULL, 0);
    dev=running->cwd->dev;
    ino=getino(&dev, path);
    if (ino==0) {
        printf(RED "invalid path\n" RESET);
        return -1;
    }
    mip=iget(dev, ino);
    mip->inode.i_mode=newMod;
    mip->dirty=true;
    mnt=(MOUNT *)find_mount(dev);
    sync_mount_atime(mnt);
    iput(mip);
}
Пример #4
0
int chown(char *cmd) {
    int newOwner, ino, dev;
    char path[1024], own[10];
    MINODE *mip;
    MOUNT *mnt;

    sscanf(cmd, "%s %s", own, path);
    newOwner=atoi(own);
    dev=running->cwd->dev;
    ino=getino(&dev, path);
    if(ino==0) {
        printf(RED "invalid path\n" RESET);
        return -1;
    }
    mip=iget(dev, ino);
    mip->inode.i_uid=newOwner;
    mip->dirty=true;
    mnt=(MOUNT *)find_mount(dev);
    sync_mount_atime(mnt);
    iput(mip);
    return;
}
Пример #5
0
/**
 * \brief Open the given directory
 *
 * \param path Fully-qualified absolute path to directory
 * \param dhandle Return handle, if call succeeds
 *
 * This call fails if the path does not exist or is not a directory.
 */
errval_t vfs_opendir(const char *path, vfs_handle_t *dhandle)
{
    const char *relpath = NULL;

    // locate mount point
    struct vfs_mount *m = find_mount(path, &relpath);
    if (m == NULL) {
        return FS_ERR_NOTFOUND;
    }

    // call fs ops func
    assert(m->ops->opendir != NULL);
    errval_t ret = m->ops->opendir(m->st, relpath, dhandle);

    // update handle with mount pointer
    if (err_is_ok(ret)) {
        struct vfs_handle *h = *dhandle;
        h->mount = m;
    }

    return ret;
}
Пример #6
0
Файл: fs.c Проект: jaw0/osj5
FILE *
fopen(const char *name, const char *how){
    MountEntry *me;

    me = find_mount(name);
    if( me )
        name = basenameoffile(name);
#ifdef USE_PROC
    if( currproc && !me )
        me = currproc->cwd;
#endif
    if( !me )
        return 0;

    if( me->flags & MNTE_F_DEV )
        return me->fdev;

    if( me->fscf && me->fscf->open )
        return (me->fscf->open)(me, name, how);
    else
        return me->fdev;
}
Пример #7
0
status_t fs_make_dir(const char *path)
{
    char temppath[FS_MAX_PATH_LEN];

    strlcpy(temppath, path, sizeof(temppath));
    fs_normalize_path(temppath);

    const char *newpath;
    struct fs_mount *mount = find_mount(temppath, &newpath);
    if (!mount)
        return ERR_NOT_FOUND;

    if (!mount->api->mkdir) {
        put_mount(mount);
        return ERR_NOT_SUPPORTED;
    }

    status_t err = mount->api->mkdir(mount->cookie, newpath);

    put_mount(mount);

    return err;
}
Пример #8
0
/*
 * Mount a filesystem. Once we've found the device, call MOUNTFUNC to
 * set up the filesystem and hand back a struct fs.
 */
int
vfs_mount(const char *devname, int (*mountfunc)(struct device *dev, struct fs **fs_store)) {
    int ret;
    lock_vdev_list();
    vfs_dev_t *vdev;
    if ((ret = find_mount(devname, &vdev)) != 0) {
        goto out;
    }
    if (vdev->fs != NULL) {
        ret = -E_BUSY;
        goto out;
    }
    assert(vdev->devname != NULL && vdev->mountable);

    struct device *dev = vop_info(vdev->devnode, device);
    if ((ret = mountfunc(dev, &(vdev->fs))) == 0) {
        assert(vdev->fs != NULL);
        cprintf("vfs: mount %s.\n", vdev->devname);
    }

out:
    unlock_vdev_list();
    return ret;
}
Пример #9
0
int myread(int fd, char buffer[], int nbytes) {

    int i, size, lblk, *bno, *ibno, *dbno, start, remain, avil, file_size, offset, count=0;
    OFT *oftp;
    char *cq, *buf, *inbuf, *dinbuf, *readbuf;
    MINODE *mip;
    MOUNT *mnt;

    cq=buffer;

    if (fd < 0 || fd >NFD) {
        printf(RED"Invalid FD\n"RESET);
        return -1;
    }
    oftp=running->fd[fd];
    mip=oftp->ptr;
 
    mnt=find_mount(mip->dev);

    size=mnt->blksize;
    buf=malloc(size+1);
    inbuf=malloc(size+1);
    dinbuf=malloc(size+1);
    readbuf=malloc(size+1);

    offset=oftp->offset;
    file_size=oftp->ptr->inode.i_size;
    avil=file_size-offset;
    printf("* fd=%d, size=%d avil=%d nbytes=%d\n", fd, file_size, avil, nbytes);
    while(nbytes && avil) {
        lblk=(oftp->offset)/size;
        start=(oftp->offset)%size;
        if (lblk<12) {
            bno =&(mip->inode.i_block[lblk]);
        } else if (lblk>=12 && lblk<((size/4)+12)) {
            bget_block(mip->dev, mip->inode.i_block[12], buf, size);
            bno = (int *)buf+(lblk-12);
        } else if (lblk>=((size/4)+12) && lblk<(((size/4)*(size/4))+(size/4)+12)) {
            bget_block(mip->dev, mip->inode.i_block[13], buf, size);
            lblk=((lblk-12) - (size/4));
            ibno = (int *)buf + (lblk/size);
            bget_block(mip->dev, *ibno, inbuf, size);
            lblk%=(size/4);
            bno=(int *)inbuf + lblk;
        } else {
            bget_block(mip->dev, mip->inode.i_block[14], buf, size);
            lblk=((lblk-12) - ((size/4)*(size/4)+(size/4)));
            dbno=(int *)buf + (lblk/((size/4)*(size/4)));
            bget_block(mip->dev, *dbno, dinbuf, size);
            lblk%=((size/4)*(size/4));
            ibno=(int *)buf + lblk/(size);
            bget_block(mip->dev, *ibno, inbuf, size);
            lblk%=(size/4);
            bno=(int *)inbuf + lblk;
        }

        bget_block(mip->dev, *bno, readbuf, size);
        cp = readbuf + start;
        remain = size - start;
        if(avail >= size && remain == size && nbytes >= size) {
        strncpy(cq, cp, size);
        running->fd[fd]->offset += size;
        count += size; avail -= size; nbytes -= size; remain -= size;
        } else if (remain <= avil && remain <= nbytes) {
            memcpy(cq, cp, remain);
            running->fd[fd]->offset += remain;
            count += remain; 
            avil -= remain; 
            nbytes -= remain; 
            remain -= remain;
        } else {
            memcpy(cq, cp, avil);
            running->fd[fd]->offset += avil;
            count += avil; 
            avil -= avil; 
            nbytes -= avil; 
            remain -= avil;
        }
    }
        printf("myread : read %d char from file descriptor %d\n", count, fd);
        FREE_4(buf, inbuf, dinbuf, readbuf);
        return count;
}
Пример #10
0
int
main(int argc, char *argv[])
{
	long timeout_val;
	int c;
	int flushcache = 0;
	int unmount_automounted = 0;	// Unmount automounted mounts
	struct autodir *dir, *d;
	char real_mntpnt[PATH_MAX];
	struct stat stbuf;
	char *master_map = "auto_master";
	int null;
	struct statfs *mntp;
	int count = 0;
	char *stack[STACKSIZ];
	char **stkptr;
	char *defval;
	int fd;
	int flags, altflags;
	struct staticmap *static_ent;

	/*
	 * Read in the values from config file first before we check
	 * commandline options so the options override the file.
	 */
	if ((defopen(AUTOFSADMIN)) == 0) {
		if ((defval = defread("AUTOMOUNT_TIMEOUT=")) != NULL) {
			errno = 0;
			timeout_val = strtol(defval, (char **)NULL, 10);
			if (errno == 0 && timeout_val > 0 &&
			    timeout_val <= INT_MAX)
				mount_timeout = (int)timeout_val;
		}
		if ((defval = defread("AUTOMOUNT_VERBOSE=")) != NULL) {
			if (strncasecmp("true", defval, 4) == 0)
				verbose = TRUE;
			else
				verbose = FALSE;
		}
		if ((defval = defread("AUTOMOUNTD_TRACE=")) != NULL) {
			/*
			 * Turn on tracing here too if the automountd
			 * is set up to do it - since automount calls
			 * many of the common library functions.
			 */
			errno = 0;
			trace = (int)strtol(defval, (char **)NULL, 10);
			if (errno != 0)
				trace = 0;
		}

		/* close defaults file */
		defopen(NULL);
	}

	while ((c = getopt(argc, argv, "mM:D:f:t:vcu?")) != EOF) {
		switch (c) {
		case 'm':
			pr_msg("Warning: -m option not supported");
			break;
		case 'M':
			pr_msg("Warning: -M option not supported");
			break;
		case 'D':
			pr_msg("Warning: -D option not supported");
			break;
		case 'f':
			pr_msg("Error: -f option no longer supported");
			usage();
			break;
		case 't':
			if (strchr(optarg, '=')) {
				pr_msg("Error: invalid value for -t");
				usage();
			}
			mount_timeout = atoi(optarg);
			break;
		case 'v':
			verbose++;
			break;
		case 'c':
			flushcache++;
			break;
		case 'u':
			unmount_automounted++;
			break;
		default:
			usage();
			break;
		}
	}

	if (optind < argc) {
		pr_msg("%s: command line mountpoints/maps "
			"no longer supported",
			argv[optind]);
		usage();
	}

	/*
	 * Get an array of current system mounts
	 */
	num_current_mounts = getmntinfo(&current_mounts, MNT_NOWAIT);
	if (num_current_mounts == 0) {
		pr_msg("Couldn't get current mounts: %m");
		exit(1);
	}

	autofs_control_fd = open("/dev/" AUTOFS_CONTROL_DEVICE, O_RDONLY);
	if (autofs_control_fd == -1 && errno == ENOENT) {
		/*
		 * Oops, we probably don't have the autofs kext
		 * loaded.
		 */
		FTS *fts;
		static char *const paths[] = { "/Network", NULL };
		FTSENT *ftsent;
		int error;

		/*
		 * This means there can't be any autofs mounts yet, so
		 * this is the first time we're being run since a reboot.
		 * Clean out any stuff left in /Network from the reboot.
		 */
		fts = fts_open(paths, FTS_NOCHDIR|FTS_PHYSICAL|FTS_XDEV,
		    NULL);
		if (fts != NULL) {
			while ((ftsent = fts_read(fts)) != NULL) {
				/*
				 * We only remove directories - if
				 * there are files, we assume they're
				 * there for a purpose.
				 *
				 * We remove directories after we've
				 * removed their children, so we want
				 * to process directories visited in
				 * post-order.
				 *
				 * We don't remove /Network itself.
				 */
				if (ftsent->fts_info == FTS_DP &&
				    ftsent->fts_level > FTS_ROOTLEVEL)
					rmdir(ftsent->fts_accpath);
			}
			fts_close(fts);
		}

		/*
		 * Now load it.
		 */
		error = load_autofs();
		if (error != 0) {
			pr_msg("can't load autofs kext");
			exit(1);
		}

		/*
		 * Try the open again.
		 */
		autofs_control_fd = open("/dev/" AUTOFS_CONTROL_DEVICE,
		    O_RDONLY);
	}
	if (autofs_control_fd == -1) {
		if (errno == EBUSY)
			pr_msg("Another automount is running");
		else
			pr_msg("Couldn't open %s: %m", "/dev/" AUTOFS_CONTROL_DEVICE);
		exit(1);
	}

	/*
	 * Update the mount timeout.
	 */
	if (ioctl(autofs_control_fd, AUTOFS_SET_MOUNT_TO, &mount_timeout) == -1)
		pr_msg("AUTOFS_SET_MOUNT_TO failed: %m");

	/*
	 * Attempt to unmount any non-busy triggered mounts; this includes
	 * not only autofs mounts, but, for example SMB Dfs mounts.
	 *
	 * This is done before sleep, and after a network change, to
	 * try to get rid of as many network mounts as we can; each
	 * unmounted network mount is a network mount on which we
	 * can't hang.
	 */
	if (unmount_automounted) {
		if (verbose)
			pr_msg("Unmounting triggered mounts");
		if (ioctl(autofs_control_fd, AUTOFS_UNMOUNT_TRIGGERED, 0) == -1)
			pr_msg("AUTOFS_UNMOUNT_TRIGGERED failed: %m");
		exit(0);
	}

	if (flushcache) {
		/*
		 * Notify the automounter that it should flush its caches,
		 * as we might be on a different network with different maps.
		 */
		if (ioctl(autofs_control_fd, AUTOFS_NOTIFYCHANGE, 0) == -1)
			pr_msg("AUTOFS_NOTIFYCHANGE failed: %m");
	}

	(void) umask(0);
	ns_setup(stack, &stkptr);

	(void) loadmaster_map(master_map, "", stack, &stkptr);

	/*
	 * Mount the daemon at its mount points.
	 */
	for (dir = dir_head; dir; dir = dir->dir_next) {

		if (realpath(dir->dir_name, real_mntpnt) == NULL) {
			/*
			 * We couldn't get the real path for this,
			 * perhaps because it doesn't exist.
			 * If it's not because it doesn't exist, just
			 * give up on this entry.  Otherwise, just null
			 * out the real path - we'll try creating the
			 * directory later, and will set dir_realpath
			 * then, if that succeeds.
			 */
			if (errno != ENOENT) {
				pr_msg("%s: Can't convert to real path: %m",
				    dir->dir_name);
				continue;
			}
			dir->dir_realpath = NULL;
		} else {
			dir->dir_realpath = strdup(real_mntpnt);
			if (dir->dir_realpath == NULL) {
				pr_msg("Couldn't allocate real path: %m");
				exit(1);
			}
		}

		/*
		 * Skip null entries
		 */
		if (strcmp(dir->dir_map, "-null") == 0)
			continue;

		/*
		 * Skip null'ed entries
		 */
		null = 0;
		for (d = dir->dir_prev; d; d = d->dir_prev) {
			if (paths_match(dir, d))
				null = 1;
		}
		if (null)
			continue;

		/*
		 * If this is -fstab, and there are no fstab "net" entries,
		 * skip this map if our directory search path doesn't
		 * include Active Directory.  We don't want /Network/Servers
		 * (or wherever it shows up) to exist if this system isn't
		 * using AD (AD supplies fstab entries on the fly, so they
		 * might not exist right now) and we don't have any fstab
		 * entries.
		 */
		if (strcmp(dir->dir_map, "-fstab") == 0) {
			if (!have_ad() && !havefstabkeys()) {
				/*
				 * We're not using AD, and fstab is
				 * inaccessible or devoid of "net" entries.
				 */
				free(dir->dir_map);
				dir->dir_map = strdup("-null");
				continue;
			}
			endfsent();
		}

		/*
		 * If this is -fstab or -static, and there's another entry
		 * that's supposed to mount something on the same directory
		 * and isn't "-fstab" or "-static", ignore this; we might
		 * have a server that's supplying real automounter maps for
		 * the benefit of OS X systems with autofs and also supplying
		 * fstab entries for the benefit of older OS X systems, and
		 * we want to mount the real automounter map, not the -fstab
		 * or -static map, in that case.
		 */
		if (strcmp(dir->dir_map, "-fstab") == 0 ||
		    strcmp(dir->dir_map, "-static") == 0) {
			for (d = dir_head; d; d = d->dir_next) {
				if (paths_match(dir, d) &&
				    strcmp(d->dir_map, "-fstab") != 0 &&
				    strcmp(d->dir_map, "-static") != 0) {
					pr_msg("%s: ignoring redundant %s map",
					    dir->dir_name, dir->dir_map);
					break;
				}
			}
			if (d != NULL) {
				continue;
			}
		}

		/*
		 * Parse the mount options and get additional flags to pass
		 * to mount() (standard mount options) and autofs mount
		 * options.
		 *
		 * XXX - we ignore flags on an update; if they're different
		 * from the current flags for that mount, we'd need to do a
		 * remount.
		 */
		if (!parse_mntopts(dir->dir_opts, &flags, &altflags)) {
			/*
			 * Failed.
			 */
			continue;
		}

		/*
		 * If this is -static, check whether the entry refers
		 * to this host; if so, make the appropriate symlink
		 * exist at the "mount point" path.
		 */
		if (strcmp(dir->dir_map, "-static") == 0) {
			static_ent = get_staticmap_entry(dir->dir_name);
			if (static_ent == NULL) {
				/*
				 * Whiskey tango foxtrot?  There should
				 * be an entry here.  Log an error and
				 * ignore this mount.
				 */
				pr_msg("can't find fstab entry for %s",
				    dir->dir_name);
				continue;
			}
			if (host_is_us(static_ent->host, strlen(static_ent->host)) ||
			    self_check(static_ent->host)) {
				/*
				 * Yup, this is us.
				 * Try to make the appropriate symlink.
				 */
				make_symlink(static_ent->localpath,
				    dir->dir_name);
				release_staticmap_entry(static_ent);
				continue;
			}
			release_staticmap_entry(static_ent);
		}

		/*
		 * Check whether there's already an entry
		 * in the mnttab for this mountpoint.
		 */
		if (dir->dir_realpath != NULL &&
		    (mntp = find_mount(dir->dir_realpath)) != NULL) {
			struct autofs_update_args au;

			/*
			 * If it's not an autofs mount - don't
			 * mount over it.
			 */
			if (strcmp(mntp->f_fstypename, MNTTYPE_AUTOFS) != 0) {
				pr_msg("%s: already mounted on %s",
					mntp->f_mntfromname, dir->dir_realpath);
				continue;
			}

			/*
			 * This is already mounted, so just update it.
			 * We don't bother to check whether any options are
			 * changing, as we'd have to make a trip into the
			 * kernel to get the current options to check them,
			 * so we might as well just make a trip to do the
			 * update.
			 */
			au.fsid		= mntp->f_fsid;
			au.opts		= dir->dir_opts;
			au.map		= dir->dir_map;
			au.mntflags	= altflags;
			au.direct 	= dir->dir_direct;
			au.node_type	= dir->dir_direct ? NT_TRIGGER : 0;

			if (ioctl(autofs_control_fd, AUTOFS_UPDATE_OPTIONS,
			    &au) < 0) {
				pr_msg("update %s: %m", dir->dir_realpath);
				continue;
			}
			if (verbose)
				pr_msg("%s updated", dir->dir_realpath);
		} else {
			struct autofs_args ai;
			int st_flags = 0;

			/*
			 * This trigger isn't already mounted; either
			 * the path doesn't exist at all, or it
			 * exists but nothing is mounted on it.
			 *
			 * Create a mount point if necessary
			 * If the path refers to an existing symbolic
			 * link, refuse to mount on it.  This avoids
			 * future problems.  (We don't use dir->dir_realpath
			 * because that's never a symbolic link.)
			 */
			if (lstat(dir->dir_name, &stbuf) == 0) {
				if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
					pr_msg("%s: Not a directory", dir->dir_name);
					continue;
				}
				st_flags = stbuf.st_flags;

				/*
				 * Either realpath() succeeded or it
				 * failed with ENOENT; otherwise, we
				 * would have quit before getting here.
				 *
				 * If it failed, report an error, as
				 * the problem isn't that "dir->dir_name"
				 * doesn't exist, the problem is that,
				 * somehow, we got ENOENT even though
				 * it exists.
				 */
				if (dir->dir_realpath == NULL) {
					errno = ENOENT;
					pr_msg("%s: Can't convert to real path: %m",
					    dir->dir_name);
					continue;
				}
			} else {
				/*
				 * Mountpoint doesn't exist.
				 *
				 * Create it unless it's under /Volumes.
				 * At boot time it's possible the volume
				 * containing the mountpoint hasn't mounted yet.
				 */
				if (strncmp(dir->dir_name, "/Volumes/", 9) == 0) {
					pr_msg("%s: mountpoint unavailable", dir->dir_name);
					continue;
				}

				if (mkdir_r(dir->dir_name)) {
					pr_msg("%s: %m", dir->dir_name);
					continue;
				}

				/*
				 * realpath() presumably didn't succeed,
				 * as dir->dir_name couldn't be statted.
				 * Call it again, to get the real path
				 * corresponding to the newly-created
				 * mount point.
				 */
				if (realpath(dir->dir_name, real_mntpnt) == NULL) {
					/*
					 * Failed.
					 */
					pr_msg("%s: Can't convert to real path: %m",
					    dir->dir_name);
					continue;
				}
				dir->dir_realpath = strdup(real_mntpnt);
				if (dir->dir_realpath == NULL) {
					pr_msg("Couldn't allocate real path for %s: %m",
					    dir->dir_name);
					continue;
				}
			}

			/*
			 * If the "hidefromfinder" option is set for
			 * this autofs mountpoint then also set the
			 * UF_HIDDEN bit on the directory so it'll still
			 * be invisible to the Finder even if not mounted on.
			 */
			if (altflags & AUTOFS_MNT_HIDEFROMFINDER)
				st_flags |= UF_HIDDEN;
			else
				st_flags &= ~UF_HIDDEN;
			if (chflags(dir->dir_name, st_flags) < 0)
				pr_msg("%s: can't set hidden", dir->dir_name);

			/*
			 * Mount it.  Use the real path (symlink-free),
			 * for reasons mentioned above.
			 */
			ai.version	= AUTOFS_ARGSVERSION;
			ai.path 	= dir->dir_realpath;
			ai.opts		= dir->dir_opts;
			ai.map		= dir->dir_map;
			ai.subdir	= "";
			ai.direct 	= dir->dir_direct;
			if (dir->dir_direct)
				ai.key = dir->dir_name;
			else
				ai.key = "";
			ai.mntflags	= altflags;
			ai.mount_type	= MOUNT_TYPE_MAP;	/* top-level autofs mount */
			ai.node_type	= dir->dir_direct ? NT_TRIGGER : 0;

			if (mount(MNTTYPE_AUTOFS, dir->dir_realpath,
			    MNT_DONTBROWSE | MNT_AUTOMOUNTED | flags,
			    &ai) < 0) {
				pr_msg("mount %s: %m", dir->dir_realpath);
				continue;
			}
			if (verbose)
				pr_msg("%s mounted", dir->dir_realpath);
		}

		count++;
	}

	if (verbose && count == 0)
		pr_msg("no mounts");

	/*
	 * Now compare the /etc/mnttab with the master
	 * map.  Any autofs mounts in the /etc/mnttab
	 * that are not in the master map must be
	 * unmounted
	 *
	 * XXX - if there are no autofs mounts left, should we
	 * unload autofs, or arrange that it be unloaded?
	 */
	do_unmounts();

	/*
	 * Let PremountHomeDirectoryWithAuthentication() know that we're
	 * done.
	 */
	fd = open("/var/run/automount.initialized", O_CREAT|O_WRONLY, 0600);
	close(fd);

	return (0);
}
Пример #11
0
static void
make_symlink(const char *target, const char *path)
{
	struct stat stbuf;
	char linktarget[PATH_MAX + 1];
	ssize_t pathlength;
	struct statfs *mnt;
	struct stat st;

	/*
	 * Does the target exist?
	 */
	if (lstat(path, &stbuf) == 0) {
		/*
		 * Yes.  What is it?
		 */
		if ((stbuf.st_mode & S_IFMT) == S_IFLNK) {
			/*
			 * It's a symlink.
			 * What does it point to?
			 */
			pathlength = readlink(path, linktarget, PATH_MAX);
			if (pathlength == -1) {
				/*
				 * FAIL.
				 */
				pr_msg("can't read target of %s: %m", path);
				return;
			}
			linktarget[pathlength] = '\0';

			/*
			 * Does it point to the same place that we
			 * want it to point to?
			 *
			 * XXX - case-sensitivity?  That's hard to
			 * handle, given that the path might cross
			 * multiple file systems with different case-
			 * sensitivities.
			 */
			if (strcmp(linktarget, target) == 0) {
				/*
				 * Yes, it does.
				 * We don't need to do anything.
				 */
				if (verbose)
					pr_msg("link %s unchanged", path);
				return;
			}

			/*
			 * Get rid of the existing symlink.
			 */
			if (unlink(path) == -1) {
				pr_msg("can't unlink %s: %m", path);
				return;
			}
		} else if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
			/*
			 * It's a directory.
			 * Is there an autofs mount atop it?
			 */
			mnt = find_mount(path);
			if (mnt != NULL) {
				/*
				 * Something's mounted atop it; is it
				 * autofs?
				 */
				if (strcmp(mnt->f_fstypename, MNTTYPE_AUTOFS) == 0) {
					/*
					 * Yes.  Try to unmount it (and
					 * everything under it).
					 */
					if (ioctl(autofs_control_fd,
					    AUTOFS_UNMOUNT, &mnt->f_fsid) != 0) {
						/*
						 * Failed.
						 * Leave it alone for now.
						 */
						return;
					}
				}
			}

			/*
			 * Now try to remove the directory.
			 */
			if (rmdir(path) != 0) {
				/*
				 * Failed.  Leave it alone.
				 */
				return;
			}
		} else {
			/*
			 * Neither a symlink nor a directory.
			 * Leave it alone.
			 */
			return;
		}
	} else {
		/*
		 * lstat() failed; is it because the target doesn't
		 * exist, or because we couldn't get its
		 * information?
		 */
		if (errno != ENOENT) {
			/*
			 * We couldn't get its information.
			 * Leave it alone.
			 */
			return;
		}
	}

	/*
	 * OK, the target should not exist.
	 * Make the symlink.
	 */
	if (symlink(target, path) == -1) {
		pr_msg("can't create symlink from %s to %s: %m",
		    path, target);
	}

	/*
	 * Validate the symlink in case the path and target
	 * don't match but still yield an ELOOP.
	 */
	if (stat(path, &st) < 0) {
		pr_msg("Invalid symbolic link: %s to %s: %m", path, target);
		(void) unlink(path);
	}
}
Пример #12
0
/**
 * \brief Mount a filesystem into the local VFS
 *
 * \param mountpoint Fully-qualified absolute path to the mount-point
 *   Must be a directory in the existing VFS which is not already a mount-point
 *
 * \param uri URI of source file system to mount.
 *   Currently-supported are:
 *     ramfs://[servicename] where servicename is registered in the name service
 *     nfs://hostip/path
 */
errval_t vfs_mount(const char *mountpoint, const char *uri)
{
    errval_t err;

    // copy mountpoint and normalise it
    assert(mountpoint != NULL);
    char *mp = strdup(mountpoint);
    assert(mp != NULL);
    vfs_path_normalise(mp);

    // sanity-check mountpoint: must start at root and not have .. in it
    if (mp[0] != VFS_PATH_SEP || strncmp(mp, "/../", 4) == 0) {
        free(mp);
        return VFS_ERR_BAD_MOUNTPOINT;
    }

    // sanity-check mountpoint
    // if this is the first mount, it must be for the root, otherwise it must
    // not duplicate an existing mount, and the mount-point must exist
    if (mounts == NULL) {
        if (strcmp(mp, VFS_PATH_SEP_STR) != 0) {
            free(mp);
            return VFS_ERR_BAD_MOUNTPOINT;
        }
    } else {
        struct vfs_mount *parent = find_mount(mp, NULL);
        assert(parent != NULL); // root should always have matched
        if (strcmp(parent->mountpoint, mp) == 0) {
            free(mp);
            return VFS_ERR_MOUNTPOINT_IN_USE;
        }

        // check for existence of mountpoint by attempting to open it
        vfs_handle_t tmp;
        err = vfs_opendir(mp, &tmp);
        if (err_is_fail(err)) {
            free(mp);
            return err_push(err, VFS_ERR_MOUNTPOINT_NOTFOUND);
        }
        vfs_closedir(tmp);
    }

    // parse protocol part of URI
    char *pos = strstr(uri, "://");
    if (pos == NULL) {
        free(mp);
        return VFS_ERR_BAD_URI;
    }

    struct vfs_mount *m = malloc(sizeof(struct vfs_mount));
    assert(m != NULL);

    m->mountpoint = mp;

    size_t len = pos - uri;
    if (strncmp(uri, "nfs", len) == 0) {
#ifndef DISABLE_NFS
        err = vfs_nfs_mount(uri, &m->st, &m->ops);
#else
        err = VFS_ERR_UNKNOWN_FILESYSTEM;
#endif
    } else if (strncmp(uri, "ramfs", len) == 0) {
        err = vfs_ramfs_mount(uri, &m->st, &m->ops);
    } else if (strncmp(uri, "blockdevfs", len) == 0) {
        err = vfs_blockdevfs_mount(uri, &m->st, &m->ops);
    } else if (strncmp(uri, "fat16", len) == 0) {
        err = vfs_fat_mount(uri, &m->st, &m->ops);
    } else if (strncmp(uri, "fat32", len) == 0) {
        err = vfs_fat_mount(uri, &m->st, &m->ops);
    } else {
        debug_printf("VFS: unknown file system %.*s\n", (int)len, uri);
        err = VFS_ERR_UNKNOWN_FILESYSTEM;
    }

    if (err_is_fail(err)) {
        free(m);
        free(mp);
        return err;
    }

    // add to list of mounts
    m->next = mounts;
    mounts = m;

    return SYS_ERR_OK;
}
Пример #13
0
Файл: fs.c Проект: jaw0/osj5
DEFALIAS(dir, ll)
{
    int how=0, i;
    const char *what;
    MountEntry *me;

    if( !strcmp(argv[0], "ll") )
        how = LSHOW_ALL | LSHOW_LONG ;
    if( !strcmp(argv[0], "ls") )
        how = LSHOW_SHORT ;

    if( argc == 1)
        what = "";
    else{
        if( argv[1][0] == '-' ){
            for(i=how=0; argv[1][i]; i++){
                switch( argv[1][i] ){
                case 'a':	how |= LSHOW_ALL;	break;
                case 'd':	how |= LSHOW_DEVS;	break;
                case 'f':	how |= LSHOW_FSYS;	break;
                case 'x':	how |= LSHOW_EXT;	break;
                case 'l':	how |= LSHOW_LONG;	break;
                case 's':	how |= LSHOW_SHORT;	break;
                case 'h':
                    printf("-a\tall\n-d\tdevs\n-f\tfilesys\n-l\tlong\n-s\tshort\n");
                    return 0;
                }
            }
            what = argc>2 ? argv[2] : "";
        }else{
            what = argc>1 ? argv[1] : "";

            if( !strcmp(argv[1], DEVPREFIX) ){
                how |= LSHOW_DEVS;
                what = "";
            }
            if( !strcmp(argv[1], ":") ){
                how |= LSHOW_FSYS;
                what = "";
            }
            if( !strcmp(argv[1], "::") ){
                how |= LSHOW_DEVS | LSHOW_FSYS | LSHOW_LONG;
                what = "";
            }

        }
    }

    if( (how & LSHOW_FSYS) || (how & LSHOW_DEVS) ){

        if( how & LSHOW_FSYS ){
            // synthesize a "dev" filesystem
            printf("\tdev:%s\n", (how & LSHOW_LONG) ? "\ttype dev" : "");
        }

        /* list all devs or filesystems */
        me = mountlist;
        while( me ){
            if( (me->flags & MNTE_F_DEV) && (how & LSHOW_DEVS)
                || (me->flags & MNTE_F_FS) && (how & LSHOW_FSYS) ){
                printf("\t%s", me->name);
                if( how & LSHOW_LONG ){
                    if( me->fscf && me->fscf->name )
                        printf("\ttype %s", me->fscf->name);

                }
                printf("\n");
            }
            me = me->next;
        }
        return 0;
    }

#ifdef USE_FILESYS
    me = find_mount(what);
    if( me )
        what = basenameoffile(what);

#ifdef USE_PROC
    if( !me ) me = currproc->cwd;
#endif

    if( !me ){
        fsmsg("no such file or device\n");
        return -1;
    }

    if( me->fscf && me->fscf->ops )
        i = (me->fscf->ops)(FSOP_DIR, me, how, what);
    else
        i = -1;

    if( i )
        f_error("ls [-adfxl] [me]");
    return i;
#else
    f_error("no filesys configured\n");
    return -1;
#endif
}