Example #1
0
static int FuseHFS_statfs(const char *path, struct statvfs *stbuf) {
	memset(stbuf, 0, sizeof(*stbuf));
	hfsvolent vstat;
	hfs_vstat(NULL, &vstat);
	
	stbuf->f_bsize = stbuf->f_frsize = vstat.alblocksz;
	stbuf->f_blocks = vstat.totbytes / vstat.alblocksz;
	stbuf->f_bfree = stbuf->f_bavail = vstat.freebytes / vstat.alblocksz;
	 
	stbuf->f_files = vstat.numfiles + vstat.numdirs + 1;
	stbuf->f_namemax = HFS_MAX_FLEN;
	return 0;
}
Example #2
0
void * FuseHFS_init(struct fuse_conn_info *conn) {
	struct fuse_context *cntx=fuse_get_context();
	struct fusehfs_options *options = cntx->private_data;
	
#if (__FreeBSD__ >= 10)
	FUSE_ENABLE_SETVOLNAME(conn); // this actually doesn't do anything
	FUSE_ENABLE_XTIMES(conn); // and apparently this doesn't either
#endif
	
	
#ifdef DEBUG
	//char logfn[128];
	//sprintf(logfn, "/fusefs_hfs/FuseHFS.%d.log", getpid());
	//stderr = freopen(logfn, "a", stderr);
    log_to_file();
	fprintf(stderr, "FuseHFS_init\n");
	fflush(stderr);
#endif
	
	// create iconv
	iconv_to_utf8 = iconv_open("UTF-8", options->encoding);
	if (iconv_to_utf8 == (iconv_t)-1) {
		perror("iconv_open");
		exit(1);
	}
	iconv_to_mac = iconv_open(options->encoding, "UTF-8");
	if (iconv_to_mac == (iconv_t)-1) {
		perror("iconv_open");
		exit(1);
	}
	
	// mount volume
	int mode = options->readonly?HFS_MODE_RDONLY:HFS_MODE_ANY;
	if (NULL == hfs_mount(options->path, 0, mode)) {
		perror("hfs_mount");
		exit(1);
	}
	
	// initialize some globals
	_readonly = options->readonly;
	hfsvolent vstat;
	hfs_vstat(NULL, &vstat);
	strcpy(_volname, vstat.name);
	
	return NULL;
}
Example #3
0
static int FuseHFS_rename(const char *from, const char *to) {
	dprintf("rename %s %s\n", from, to);
	if (_readonly) return -EPERM;
	
	// convert to hfs paths
	char *hfspath1 = mkhfspath(from);
	char *hfspath2 = mkhfspath(to);
	
	// delete destination file if it exists
	hfsdirent ent;
	if (hfs_stat(NULL, hfspath2, &ent) == 0)
		if (!(ent.flags & HFS_ISDIR)) hfs_delete(NULL, hfspath2);
	
	// rename
	if (hfs_rename(NULL, hfspath1, hfspath2) != 0) {
		free(hfspath1);
		free(hfspath2);
		perror("hfs_rename");
		return -errno;
	}
	
	// bless parent folder if it's a system file
	if (hfs_stat(NULL, hfspath2, &ent) == -1) {
		free(hfspath1);
		free(hfspath2);
		return -ENOENT;
	}
	
	if ((strcmp(ent.u.file.type, "zsys") == 0) && (strcmp(ent.u.file.creator, "MACS") == 0) && (strcmp(ent.name, "System") == 0)) {
		// bless
		dprintf("rename: blessing folder %lu\n", ent.parid);
		hfsvolent volent;
		hfs_vstat(NULL, &volent);
		volent.blessed = ent.parid;
		hfs_vsetattr(NULL, &volent);
	}
	
	// success
	free(hfspath1);
	free(hfspath2);
	return 0;
}
Example #4
0
static int FuseHFS_setxattr(const char *path, const char *name, const char *value,
				  size_t size, int flags, uint32_t position) {
	dprintf("setxattr %s %s %p %lu %02x %u\n", path, name, value, size, flags, position);
	if (_readonly) return -EPERM;
	
	// convert to hfs path
	char *hfspath = mkhfspath(path);
	if (hfspath == NULL) return -ENOENT;
	
	// find file
	hfsdirent ent;
	if (hfs_stat(NULL, hfspath, &ent) == -1) {
		free(hfspath);
		return -ENOENT;
	}
	
	if (strcmp(name, XATTR_FINDERINFO_NAME) == 0) {
		if (size != 32) {
			dprintf("setxattr: finder info is not 32 bytes\n");
			free(hfspath);
			return -ERANGE;
		}
		// write finder info to dirent
		if (ent.flags & HFS_ISDIR) {
			// directory
			ent.u.dir.rect.top =		OSReadBigInt16(value, 0);
			ent.u.dir.rect.left =		OSReadBigInt16(value, 2);
			ent.u.dir.rect.bottom =		OSReadBigInt16(value, 4);
			ent.u.dir.rect.right =		OSReadBigInt16(value, 6);
			ent.fdflags =				OSReadBigInt16(value, 8);
			ent.fdlocation.v =			OSReadBigInt16(value, 10);
			ent.fdlocation.h =			OSReadBigInt16(value, 12);
			ent.u.dir.view =			OSReadBigInt16(value, 14);
			// DXInfo
			((DXInfo*)(ent.u.dir.xinfo))->frScroll.v   = OSReadBigInt16(value, 16);
			((DXInfo*)(ent.u.dir.xinfo))->frScroll.h   = OSReadBigInt16(value, 18);
			((DXInfo*)(ent.u.dir.xinfo))->frOpenChain  = OSReadBigInt32(value, 20);
			((DXInfo*)(ent.u.dir.xinfo))->frUnused     = OSReadBigInt16(value, 24);
			((DXInfo*)(ent.u.dir.xinfo))->frComment    = OSReadBigInt16(value, 26);
			((DXInfo*)(ent.u.dir.xinfo))->frPutAway    = OSReadBigInt32(value, 28);
		} else {
			// regular file
			memcpy(ent.u.file.type, value, 4);
			memcpy(ent.u.file.creator, value+4, 4);
			ent.u.file.type[4] = ent.u.file.type[4] = '\0';
			ent.fdflags       = OSReadBigInt16(value, 8);
			ent.fdlocation.v  = OSReadBigInt16(value, 10);
			ent.fdlocation.h  = OSReadBigInt16(value, 12);
			ent.u.file.window = OSReadBigInt16(value, 14);
			// FXInfo
			((FXInfo*)(ent.u.file.xinfo))->fdIconID    = OSReadBigInt16(value, 16);
			((FXInfo*)(ent.u.file.xinfo))->fdUnused[0] = OSReadBigInt16(value, 18);
			((FXInfo*)(ent.u.file.xinfo))->fdUnused[1] = OSReadBigInt16(value, 20);
			((FXInfo*)(ent.u.file.xinfo))->fdUnused[2] = OSReadBigInt16(value, 22);
			((FXInfo*)(ent.u.file.xinfo))->fdUnused[3] = OSReadBigInt16(value, 24);
			((FXInfo*)(ent.u.file.xinfo))->fdComment   = OSReadBigInt16(value, 26);
			((FXInfo*)(ent.u.file.xinfo))->fdPutAway   = OSReadBigInt32(value, 28);
			// bless parent folder if it's a system file
			if ((strcmp(ent.u.file.type, "zsys") == 0) && (strcmp(ent.u.file.creator, "MACS") == 0) && (strcmp(ent.name, "System") == 0)) {
				// bless
				dprintf("setxattr: blessing folder %lu\n", ent.parid);
				hfsvolent volent;
				hfs_vstat(NULL, &volent);
				volent.blessed = ent.parid;
				hfs_vsetattr(NULL, &volent);
			}
		}
		// update file
		hfs_setattr(NULL, hfspath, &ent);
		free(hfspath);
		return 0;
	} else if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && (!(ent.flags & HFS_ISDIR))) {
		// resource fork
		// TODO: how are resource forks truncated?
		hfsfile *fp = hfs_open(NULL, hfspath);
		hfs_setfork(fp, 1);
		hfs_seek(fp, position, SEEK_SET);
		hfs_write(fp, value, size);
		hfs_close(fp);
		// the end
		free(hfspath);
		return 0;
	} else {
		free(hfspath);
		return 0;
	}
	
	free(hfspath);
	return -ENOATTR;
	
}
Example #5
0
short int FS_MOUNT(unsigned short flag, struct vpfsi *pvpfsi,
                   struct vpfsd *pvpfsd, unsigned short hVPB,
                   unsigned short vol_descr, unsigned char *pBoot)
{
    unsigned short oldVPB;
    unsigned long len_parm;
    unsigned char label[CCHMAXPATH], maclabel[HFS_MAX_VLEN+1];
    hfsvolent volent;

#ifdef DEBUG
    printf("Mount, flag = %hu, hVPB = %hu\n", flag, hVPB);
#endif
    switch(flag) {
    case MOUNT_MOUNT:
        /* The cache uses hVPB as part of the key, so we flush it here. */
        flush_cache();

        /* Check for duplicate VPB */
        oldVPB = hVPB;
        if( do_FSCtl(NULL, 0, NULL,
                     &oldVPB, sizeof(unsigned short), &len_parm,
                     FSCTL_FUNC_FINDDUPHVPB)
                == NO_ERROR ) {
            /* We should read the vol info and bitmap again here for the old VPB,
               as the volume may have been written while it was removed. */

            /* Mark the VPB as duplicate */
            set_vol_status(hVPB, pvpfsi->vpi_drive, MTSTAT_DUPLICATE);
            /* If necessary, mark the old VPB as mounted */
            if(get_mount_status(oldVPB)==MTSTAT_REMOVED)
                set_vol_status(oldVPB, pvpfsi->vpi_drive, MTSTAT_MOUNTED);
            return NO_ERROR;
        }

        /* Mount the volume */
        pvpfsd->vol = hfs_mount(hVPB, 1, pvpfsi->vpi_bsize, 0);
        if(pvpfsd->vol == NULL) {
#ifdef DEBUG
            printf("hfs_mount failed!\n");
#endif
            return ERROR_VOLUME_NOT_MOUNTED;
        }

        if(hfs_vstat(pvpfsd->vol, &volent) < 0) {
#ifdef DEBUG
            printf("hfs_vstat failed!\n");
#endif
            return ERROR_VOLUME_NOT_MOUNTED;
        }

        /* Fill vpfsi fields */
        /* Use creation timestamp as ID */
        pvpfsi->vpi_vid = volent.crdate;
        strcpy(maclabel, pvpfsd->vol->mdb.drVN);
        mac_to_os2_label(maclabel, label);
        strncpy(pvpfsi->vpi_text, label, 12);
        pvpfsi->vpi_text[11]=0;

        set_vol_status(hVPB, pvpfsi->vpi_drive, MTSTAT_MOUNTED);
        if(is_readonly(hVPB, pvpfsd->vol))
            pvpfsd->vol->flags |= HFS_READONLY;
#ifdef DEBUG
        printf("Got HFS volume\n");
#endif
        return NO_ERROR;

    case MOUNT_VOL_REMOVED:
        flush_cache();
        /* If the disk was removed, forget about flushing. We should do a
           setvolume() here if volume is dirty, but it does not work. */
        pvpfsd->vol->flags |= HFS_READONLY;
        return NO_ERROR;

    case MOUNT_RELEASE:
        switch(get_mount_status(hVPB)) {
        case MTSTAT_REMOVED:
        case MTSTAT_MOUNTED:
            hfs_umount(pvpfsd->vol);
            break;
        case MTSTAT_DUPLICATE:
#ifdef DEBUG
            printf("Trying to unmount non-mounted volume!\n");
#endif
            break;
        }
        flush_cache();
        set_vol_status(hVPB, 0, MTSTAT_FREE);
        return NO_ERROR;

    case MOUNT_ACCEPT:
        return ERROR_NOT_SUPPORTED;

    default:
        return ERROR_NOT_SUPPORTED;
    }
}
Example #6
0
/*
 * NAME:	hformat->main()
 * DESCRIPTION:	implement hformat command
 */
int hformat_main(int argc, char *argv[])
{
    const char *vname, *path;
    hfsvol *vol;
    hfsvolent ent;
    int nparts, partno, options = 0, result = 0;

    vname = "Untitled";

    while (1)
    {
        int opt;

        opt = getopt(argc, argv, "fl:");
        if (opt == EOF)
            break;

        switch (opt)
        {
        case '?':
            return usage();

        case 'f':
            options |= O_FORCE;
            break;

        case 'l':
            vname = optarg;
            break;
        }
    }

    if (argc - optind < 1 || argc - optind > 2)
        return usage();

    path = argv[optind];

    nparts = hfs_nparts(path);

    if (argc - optind == 2)
    {
        partno = atoi(argv[optind + 1]);

        if (nparts != -1 && partno == 0)
        {
            if (options & O_FORCE)
            {
                fprintf(stderr,
                        "%s: warning: erasing partition information\n", argv0);
            }
            else
            {
                fprintf(stderr, "%s: medium is partitioned; "
                        "select partition > 0 or use -f\n", argv0);
                return 1;
            }
        }
    }
    else
    {
        if (nparts > 1)
        {
            fprintf(stderr,
                    "%s: must specify partition number (%d available)\n",
                    argv0, nparts);
            return 1;
        }
        else if (nparts == -1)
            partno = 0;
        else
            partno = 1;
    }

    vol = do_format(path, partno, vname);
    if (vol == 0)
    {
        hfsutil_perror(path);
        return 1;
    }

    hfs_vstat(vol, &ent);
    hfsutil_pinfo(&ent);

    if (hcwd_mounted(ent.name, ent.crdate, path, partno) == -1)
    {
        perror("Failed to record mount");
        result = 1;
    }

    hfsutil_unmount(vol, &result);

    return result;
}