Beispiel #1
0
/**
 * Mount a new fatfs.
 * @param mode      mount flags.
 * @param param     contains optional mount parameters.
 * @param parm_len  length of param string.
 * @param[out] sb   Returns the superblock of the new mount.
 * @return error code, -errno.
 */
static int fatfs_mount(const char * source, uint32_t mode,
                       const char * parm, int parm_len,
                       struct fs_superblock ** sb)
{
    static dev_t fatfs_vdev_minor;
    struct fatfs_sb * fatfs_sb = NULL;
    vnode_t * vndev;
    char pdrv;
    int err, retval = 0;

    /* Get device vnode */
    err = lookup_vnode(&vndev, curproc->croot, source, 0);
    if (err) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "fatfs source not found\n");
#endif
        return err;
    }
    if (!S_ISBLK(vndev->vn_mode))
        return -ENOTBLK;

    /* Allocate superblock */
    fatfs_sb = kzalloc(sizeof(struct fatfs_sb));
    if (!fatfs_sb)
        return -ENOMEM;

    fs_fildes_set(&fatfs_sb->ff_devfile, vndev, O_RDWR);
    fatfs_sb->sb.vdev_id = DEV_MMTODEV(VDEV_MJNR_FATFS, fatfs_vdev_minor++);

    /* Insert sb to fatfs_sb_arr lookup array */
    fatfs_sb_arr[DEV_MINOR(fatfs_sb->sb.vdev_id)] = fatfs_sb;

    /* Mount */
    pdrv = (char)DEV_MINOR(fatfs_sb->sb.vdev_id);
    err = f_mount(&fatfs_sb->ff_fs, 0);
    if (err) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "Can't init a work area for FAT (%d)\n", err);
#endif
        retval = fresult2errno(err);
        goto fail;
    }
#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "Initialized a work area for FAT\n");
#endif

#if (_FS_NOFSINFO == 0) /* Commit full scan of free clusters */
    DWORD nclst;

    f_getfree(&fatfs_sb->ff_fs, &nclst);
#endif

    /* Init super block */
    fs_init_superblock(&fatfs_sb->sb, &fatfs_fs);
    /* TODO Detect if target dev is rdonly */
    fatfs_sb->sb.mode_flags = mode;
    fatfs_sb->sb.root = create_root(fatfs_sb);
    fatfs_sb->sb.sb_dev = vndev;
    fatfs_sb->sb.sb_hashseed = fatfs_sb->sb.vdev_id;
    /* Function pointers to superblock methods */
    fatfs_sb->sb.get_vnode = NULL; /* Not implemented for FAT. */
    fatfs_sb->sb.delete_vnode = fatfs_delete_vnode;
    fatfs_sb->sb.umount = NULL;

    if (!fatfs_sb->sb.root) {
        KERROR(KERROR_ERR, "Root of fatfs not found\n");

        return -EIO;
    }
    fs_insert_superblock(&fatfs_fs, &fatfs_sb->sb);

fail:
    if (retval) {
        fatfs_sb_arr[DEV_MINOR(fatfs_sb->sb.vdev_id)] = NULL;
        kfree(fatfs_sb);
    }

    *sb = &fatfs_sb->sb;
    return retval;
}
Beispiel #2
0
/* If we have a --backup-dir, then we get here from make_backup().
 * We will move the file to be deleted into a parallel directory tree. */
static int keep_backup(const char *fname)
{
	STRUCT_STAT st;
	struct file_struct *file;
	char *buf;
	int kept = 0;
	int ret_code;

	/* return if no file to keep */
	if (do_lstat(fname, &st) < 0)
		return 1;

	if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
		return 1; /* the file could have disappeared */

	if (!(buf = get_backup_name(fname))) {
		unmake_file(file);
		return 0;
	}

	/* Check to see if this is a device file, or link */
	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
	 || (preserve_specials && IS_SPECIAL(file->mode))) {
		uint32 *devp = F_RDEV_P(file);
		dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
		do_unlink(buf);
		if (do_mknod(buf, file->mode, rdev) < 0
		    && (errno != ENOENT || make_bak_dir(buf) < 0
		     || do_mknod(buf, file->mode, rdev) < 0)) {
			rsyserr(FERROR, errno, "mknod %s failed",
				full_fname(buf));
		} else if (verbose > 2) {
			rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
				fname);
		}
		kept = 1;
		do_unlink(fname);
	}

	if (!kept && S_ISDIR(file->mode)) {
		/* make an empty directory */
		if (do_mkdir(buf, file->mode) < 0
		    && (errno != ENOENT || make_bak_dir(buf) < 0
		     || do_mkdir(buf, file->mode) < 0)) {
			rsyserr(FINFO, errno, "mkdir %s failed",
				full_fname(buf));
		}

		ret_code = do_rmdir(fname);
		if (verbose > 2) {
			rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
				full_fname(fname), ret_code);
		}
		kept = 1;
	}

#ifdef SUPPORT_LINKS
	if (!kept && preserve_links && S_ISLNK(file->mode)) {
		const char *sl = F_SYMLINK(file);
		if (safe_symlinks && unsafe_symlink(sl, buf)) {
			if (verbose) {
				rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
					full_fname(buf), sl);
			}
			kept = 1;
		} else {
			do_unlink(buf);
			if (do_symlink(sl, buf) < 0
			    && (errno != ENOENT || make_bak_dir(buf) < 0
			     || do_symlink(sl, buf) < 0)) {
				rsyserr(FERROR, errno, "link %s -> \"%s\"",
					full_fname(buf), sl);
			}
			do_unlink(fname);
			kept = 1;
		}
	}
#endif

	if (!kept && !S_ISREG(file->mode)) {
		rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
			fname);
		unmake_file(file);
		return 1;
	}

	/* move to keep tree if a file */
	if (!kept) {
		if (robust_move(fname, buf) != 0) {
			rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
				full_fname(fname), buf);
		} else if (st.st_nlink > 1) {
			/* If someone has hard-linked the file into the backup
			 * dir, rename() might return success but do nothing! */
			robust_unlink(fname); /* Just in case... */
		}
	}
	set_file_attrs(buf, file, NULL, 0);
	unmake_file(file);

	if (verbose > 1) {
		rprintf(FINFO, "backed up %s to %s\n",
			fname, buf);
	}
	return 1;
}