コード例 #1
0
ファイル: main.go プロジェクト: shining0x55aa/go-mtpfs
func main() {
	fsdebug := flag.Bool("fs-debug", false, "switch on FS debugging")
	mtpDebug := flag.Bool("mtp-debug", false, "switch on MTP debugging")
	vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.")
	other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.")
	deviceFilter := flag.String("dev", "", "regular expression to filter devices.")
	storageFilter := flag.String("storage", "", "regular expression to filter storage areas.")
	flag.Parse()

	if len(flag.Args()) != 1 {
		log.Fatalf("Usage: %s [options] MOUNT-POINT\n", os.Args[0])
	}
	mountpoint := flag.Arg(0)

	dev, err := mtp.SelectDevice(*deviceFilter)
	if err != nil {
		log.Fatalf("detect failed: %v", err)
	}
	defer dev.Close()

	if err = dev.OpenSession(); err != nil {
		log.Fatalf("OpenSession failed: %v", err)
	}

	sids, err := fs.SelectStorages(dev, *storageFilter)
	if err != nil {
		log.Fatalf("selectStorages failed: %v", err)
	}

	dev.DebugPrint = *mtpDebug
	opts := fs.DeviceFsOptions{
		RemovableVFat: *vfat,
	}
	fs, err := fs.NewDeviceFs(dev, sids, opts)
	if err != nil {
		log.Fatalf("NewDeviceFs failed: %v", err)
	}
	conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn)

	mount := fuse.NewMountState(rawFs)
	mOpts := &fuse.MountOptions{
		AllowOther: *other,
	}
	if err := mount.Mount(mountpoint, mOpts); err != nil {
		log.Fatalf("mount failed: %v", err)
	}

	conn.Debug = *fsdebug
	mount.Debug = *fsdebug
	log.Printf("starting FUSE %v", fuse.Version())
	mount.Loop()
}
コード例 #2
0
ファイル: main.go プロジェクト: xushiwei/go-mtpfs
func main() {
	fsdebug := flag.Bool("fs-debug", false, "switch on FS debugging")
	mtpDebug := flag.Int("mtp-debug", 0, "switch on MTP debugging")
	flag.Parse()

	if len(flag.Args()) != 1 {
		log.Fatal("Usage: mtpfs MOUNT-POINT")
	}
	mountpoint := flag.Arg(0)

	Init()
	SetDebug(*mtpDebug)
	devs, err := Detect()
	if err != nil {
		log.Fatalf("detect: %v", err)
	}
	for _, d := range devs {
		log.Printf("device %v: ", d)
	}
	if len(devs) == 0 {
		log.Fatal("no device found.  Try replugging it.")
	}
	if len(devs) > 1 {
		log.Fatal("must have exactly one device")
	}

	rdev := devs[0]

	dev, err := rdev.Open()
	if err != nil {
		log.Fatalf("rdev.open: %v", err)
	}
	defer dev.Release()
	dev.GetStorage(0)
	for _, s := range dev.ListStorage() {
		log.Printf("storage ID %d: %s", s.Id(), s.Description())
	}

	if len(dev.ListStorage()) == 0 {
		log.Fatalf("No storages found.  Try unlocking the device.")
	}

	backing, err := ioutil.TempDir("", "go-mtpfs")
	if err != nil {
		log.Fatalf("TempDir failed: %v", err)
	}
	fs := NewDeviceFs(dev, backing)
	conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn)

	mount := fuse.NewMountState(rawFs)
	if err := mount.Mount(mountpoint, nil); err != nil {
		log.Fatalf("mount failed: %v", err)
	}

	conn.Debug = *fsdebug
	mount.Debug = *fsdebug
	log.Println("starting FUSE.")
	mount.Loop()
	os.RemoveAll(backing)
}
コード例 #3
0
ファイル: main.go プロジェクト: thomasf/go-mtpfs
func main() {
	fsdebug := flag.Bool("fs-debug", false, "switch on FS debugging")
	mtpDebug := flag.Int("mtp-debug", 0, "switch on MTP debugging. 1=PTP, 2=PLST, 4=USB, 8=DATA")
	backing := flag.String("backing-dir", "", "backing store for locally cached files. Default: use a temporary directory.")
	vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.")
	other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.")
	deviceFilter := flag.String("dev", "", "regular expression to filter devices.")
	storageFilter := flag.String("storage", "", "regular expression to filter storage areas.")
	flag.Parse()

	if len(flag.Args()) != 1 {
		log.Fatalf("Usage: %s [options] MOUNT-POINT\n", os.Args[0])
	}
	mountpoint := flag.Arg(0)

	Init()
	SetDebug(*mtpDebug)
	devs, err := Detect()
	if err != nil {
		log.Fatalf("detect failed: %v", err)
	}

	if *deviceFilter != "" {
		re, err := regexp.Compile(*deviceFilter)
		if err != nil {
			log.Fatalf("invalid regexp %q: %v", *deviceFilter, err)
		}
		filtered := []*RawDevice{}
		for _, d := range devs {
			if re.FindStringIndex(d.String()) != nil {
				filtered = append(filtered, d)
			} else {
				log.Printf("filtering out device %v: ", d)
			}
		}
		devs = filtered
	} else {
		for _, d := range devs {
			log.Printf("found device %v: ", d)
		}
	}

	if len(devs) == 0 {
		log.Fatal("no device found.  Try replugging it.")
	}
	if len(devs) > 1 {
		log.Fatal("must have exactly one device. Try using -dev")
	}

	rdev := devs[0]

	dev, err := rdev.Open()
	if err != nil {
		log.Fatalf("rdev.open failed: %v", err)
	}
	defer dev.Release()
	dev.GetStorage(0)

	storages := []*DeviceStorage{}
	for _, s := range dev.ListStorage() {
		if !s.IsHierarchical() {
			log.Printf("skipping non hierarchical storage %q", s.Description())
			continue
		}
		storages = append(storages, s)
	}

	if *storageFilter != "" {
		re, err := regexp.Compile(*storageFilter)
		if err != nil {
			log.Fatalf("invalid regexp %q: %v", *storageFilter, err)
		}

		filtered := []*DeviceStorage{}
		for _, s := range storages {
			if re.FindStringIndex(s.Description()) == nil {
				log.Printf("filtering out storage %q", s.Description())
				continue
			}
			filtered = append(filtered, s)
		}

		if len(filtered) == 0 {
			log.Fatalf("No storages found. Try changing the -storage flag.")
		}
		storages = filtered
	} else {
		for _, s := range storages {
			log.Printf("storage ID %d: %s", s.Id(), s.Description())
		}
	}

	if len(storages) == 0 {
		log.Fatalf("No storages found. Try unlocking the device.")
	}

	if *backing == "" {
		*backing, err = ioutil.TempDir("", "go-mtpfs")
		if err != nil {
			log.Fatalf("TempDir failed: %v", err)
		}
	} else {
		*backing = *backing + "/go-mtpfs"
		err = os.Mkdir(*backing, 0700)
		if err != nil {
			log.Fatalf("Mkdir failed: %v", err)
		}
	}
	log.Println("backing data", *backing)
	defer os.RemoveAll(*backing)

	opts := DeviceFsOptions{
		Dir:           *backing,
		RemovableVFat: *vfat,
	}
	fs := NewDeviceFs(dev, storages, opts)
	conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn)

	mount := fuse.NewMountState(rawFs)
	mOpts := &fuse.MountOptions{
		AllowOther: *other,
	}
	if err := mount.Mount(mountpoint, mOpts); err != nil {
		log.Fatalf("mount failed: %v", err)
	}

	conn.Debug = *fsdebug
	mount.Debug = *fsdebug
	log.Printf("starting FUSE %v", fuse.Version())
	mount.Loop()
}
コード例 #4
0
ファイル: main.go プロジェクト: emmerich1234/go-mtpfs
func main() {
	fsdebug := flag.Bool("fs-debug", false, "switch on FS debugging")
	mtpDebug := flag.Int("mtp-debug", 0, "switch on MTP debugging. 1=PTP, 2=PLST, 4=USB, 8=DATA")
	backing := flag.String("backing-dir", "", "backing store for locally cached files. Default: use a temporary directory.")
	vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.")
	other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.")
	flag.Parse()

	if len(flag.Args()) != 1 {
		log.Fatal("Usage: mtpfs MOUNT-POINT")
	}
	mountpoint := flag.Arg(0)

	Init()
	SetDebug(*mtpDebug)
	devs, err := Detect()
	if err != nil {
		log.Fatalf("detect: %v", err)
	}
	for _, d := range devs {
		log.Printf("device %v: ", d)
	}
	if len(devs) == 0 {
		log.Fatal("no device found.  Try replugging it.")
	}
	if len(devs) > 1 {
		log.Fatal("must have exactly one device")
	}

	rdev := devs[0]

	dev, err := rdev.Open()
	if err != nil {
		log.Fatalf("rdev.open: %v", err)
	}
	defer dev.Release()
	dev.GetStorage(0)
	for _, s := range dev.ListStorage() {
		log.Printf("storage ID %d: %s", s.Id(), s.Description())
	}

	if len(dev.ListStorage()) == 0 {
		log.Fatalf("No storages found.  Try unlocking the device.")
	}

	if *backing == "" {
		*backing, err = ioutil.TempDir("", "go-mtpfs")
		if err != nil {
			log.Fatalf("TempDir failed: %v", err)
		}
	} else {
		*backing = *backing + "/go-mtpfs"
		err = os.Mkdir(*backing, 0700)
		if err != nil {
			log.Fatalf("Mkdir failed: %v", err)
		}
	}
	log.Println("backing data", *backing)
	defer os.RemoveAll(*backing)

	opts := DeviceFsOptions{
		Dir:           *backing,
		RemovableVFat: *vfat,
	}
	fs := NewDeviceFs(dev, &opts)
	conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn)

	mount := fuse.NewMountState(rawFs)
	mOpts := &fuse.MountOptions{
		AllowOther: *other,
	}
	if err := mount.Mount(mountpoint, mOpts); err != nil {
		log.Fatalf("mount failed: %v", err)
	}

	conn.Debug = *fsdebug
	mount.Debug = *fsdebug
	log.Println("starting FUSE.")
	mount.Loop()
}
コード例 #5
0
ファイル: device_test.go プロジェクト: pvsousalima/go-mtpfs
func startFs(t *testing.T, useAndroid bool) (root string, cleanup func()) {
	dev, err := mtp.SelectDevice("")
	if err != nil {
		t.Fatalf("SelectDevice failed: %v", err)
	}
	defer func() {
		if dev != nil {
			dev.Close()
		}
	}()

	if err = dev.Configure(); err != nil {
		t.Fatalf("Configure failed: %v", err)
	}

	sids, err := SelectStorages(dev, "")
	if err != nil {
		t.Fatalf("selectStorages failed: %v", err)
	}
	if len(sids) == 0 {
		t.Fatal("no storages found. Unlock device?")
	}
	tempdir, err := ioutil.TempDir("", "mtpfs")
	if err != nil {
		t.Fatal(err)
	}
	opts := DeviceFsOptions{
		Android: useAndroid,
	}
	fs, err := NewDeviceFs(dev, sids, opts)
	if err != nil {
		t.Fatal("NewDeviceFs failed:", err)
	}
	conn := nodefs.NewFileSystemConnector(fs, nodefs.NewOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn.RawFS())
	mount, err := fuse.NewServer(rawFs, tempdir, nil)
	if err != nil {
		t.Fatalf("mount failed: %v", err)
	}

	mount.SetDebug(fuse.VerboseTest())
	dev.MTPDebug = fuse.VerboseTest()
	dev.USBDebug = fuse.VerboseTest()
	dev.DataDebug = fuse.VerboseTest()
	go mount.Serve()

	for i := 0; i < 10; i++ {
		fis, err := ioutil.ReadDir(tempdir)
		if err == nil && len(fis) > 0 {
			root = filepath.Join(tempdir, fis[0].Name())
			break
		}
		time.Sleep(1)
	}

	if root == "" {
		mount.Unmount()
		t.Fatal("could not find entries in mount point.")
	}

	d := dev
	dev = nil
	return root, func() {
		mount.Unmount()
		d.Close()
	}
}
コード例 #6
0
ファイル: main.go プロジェクト: sneezer/go-mtpfs
func main() {
	debug := flag.String("debug", "", "comma-separated list of debugging options: usb, data, mtp, fuse")
	usbTimeout := flag.Int("usb-timeout", 5000, "timeout in milliseconds")
	vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.")
	other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.")
	deviceFilter := flag.String("dev", "", "regular expression to filter devices.")
	storageFilter := flag.String("storage", "", "regular expression to filter storage areas.")
	android := flag.Bool("android", true, "use android extensions if available")
	flag.Parse()

	if len(flag.Args()) != 1 {
		log.Fatalf("Usage: %s [options] MOUNT-POINT\n", os.Args[0])
	}
	mountpoint := flag.Arg(0)

	dev, err := mtp.SelectDevice(*deviceFilter)
	if err != nil {
		log.Fatalf("detect failed: %v", err)
	}
	defer dev.Close()
	debugs := map[string]bool{}
	for _, s := range strings.Split(*debug, ",") {
		debugs[s] = true
	}
	dev.MTPDebug = debugs["mtp"]
	dev.DataDebug = debugs["data"]
	dev.USBDebug = debugs["usb"]
	dev.Timeout = *usbTimeout
	if err = dev.Configure(); err != nil {
		log.Fatalf("Configure failed: %v", err)
	}

	sids, err := fs.SelectStorages(dev, *storageFilter)
	if err != nil {
		log.Fatalf("selectStorages failed: %v", err)
	}

	opts := fs.DeviceFsOptions{
		RemovableVFat: *vfat,
		Android:       *android,
	}
	fs, err := fs.NewDeviceFs(dev, sids, opts)
	if err != nil {
		log.Fatalf("NewDeviceFs failed: %v", err)
	}
	conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn)

	mount := fuse.NewMountState(rawFs)
	mOpts := &fuse.MountOptions{
		AllowOther: *other,
	}
	if err := mount.Mount(mountpoint, mOpts); err != nil {
		log.Fatalf("mount failed: %v", err)
	}

	conn.Debug = debugs["fuse"] || debugs["fs"]
	mount.Debug = debugs["fuse"] || debugs["fs"]
	log.Printf("starting FUSE %v", fuse.Version())
	mount.Loop()
	fs.OnUnmount()
}
コード例 #7
0
ファイル: main.go プロジェクト: YoshikuniShiku/go-mtpfs
func main() {
	debug := flag.String("debug", "", "comma-separated list of debugging options: usb, data, mtp, fuse")
	usbTimeout := flag.Int("usb-timeout", 5000, "timeout in milliseconds")
	vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.")
	other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.")
	deviceFilter := flag.String("dev", "",
		"regular expression to filter device IDs, "+
			"which are composed of manufacturer/product/serial.")
	storageFilter := flag.String("storage", "", "regular expression to filter storage areas.")
	android := flag.Bool("android", true, "use android extensions if available")
	flag.Parse()

	if len(flag.Args()) != 1 {
		log.Fatalf("Usage: %s [options] MOUNT-POINT\n", os.Args[0])
	}
	mountpoint := flag.Arg(0)

	dev, err := mtp.SelectDevice(*deviceFilter)
	if err != nil {
		log.Fatalf("detect failed: %v", err)
	}
	defer dev.Close()
	debugs := map[string]bool{}
	for _, s := range strings.Split(*debug, ",") {
		debugs[s] = true
	}
	dev.MTPDebug = debugs["mtp"]
	dev.DataDebug = debugs["data"]
	dev.USBDebug = debugs["usb"]
	dev.Timeout = *usbTimeout
	if err = dev.Configure(); err != nil {
		log.Fatalf("Configure failed: %v", err)
	}

	sids, err := fs.SelectStorages(dev, *storageFilter)
	if err != nil {
		log.Fatalf("selectStorages failed: %v", err)
	}

	opts := fs.DeviceFsOptions{
		RemovableVFat: *vfat,
		Android:       *android,
	}
	root, err := fs.NewDeviceFSRoot(dev, sids, opts)
	if err != nil {
		log.Fatalf("NewDeviceFs failed: %v", err)
	}
	conn := nodefs.NewFileSystemConnector(root, nodefs.NewOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn.RawFS())

	mOpts := &fuse.MountOptions{
		AllowOther: *other,
	}
	mount, err := fuse.NewServer(rawFs, mountpoint, mOpts)
	if err != nil {
		log.Fatalf("mount failed: %v", err)
	}

	conn.SetDebug(debugs["fuse"] || debugs["fs"])
	mount.SetDebug(debugs["fuse"] || debugs["fs"])
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		mount.Serve()
		wg.Done()
	}()
	mount.WaitMount()
	log.Printf("FUSE mounted")
	wg.Wait()
	root.OnUnmount()
}
コード例 #8
0
ファイル: device_test.go プロジェクト: shining0x55aa/go-mtpfs
func TestDevice(t *testing.T) {
	dev, err := mtp.SelectDevice("")
	if err != nil {
		t.Fatalf("detect failed: %v", err)
	}
	defer dev.Close()

	if err = dev.OpenSession(); err != nil {
		t.Fatalf("OpenSession failed: %v", err)
	}

	sids, err := SelectStorages(dev, "")
	if err != nil {
		t.Fatalf("selectStorages failed: %v", err)
	}

	tempdir, err := ioutil.TempDir("", "mtpfs")
	if err != nil {
		t.Fatal(err)
	}
	opts := DeviceFsOptions{}
	fs, err := NewDeviceFs(dev, sids, opts)
	conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions())
	rawFs := fuse.NewLockingRawFileSystem(conn)
	mount := fuse.NewMountState(rawFs)
	if err := mount.Mount(tempdir, nil); err != nil {
		t.Fatalf("mount failed: %v", err)
	}

	mount.Debug = true
	dev.DebugPrint = true

	defer mount.Unmount()
	go mount.Loop()

	var root string
	for i := 0; i < 10; i++ {
		fis, err := ioutil.ReadDir(tempdir)
		if err != nil || len(fis) == 0 {
			time.Sleep(1)
			continue
		}

		root = filepath.Join(tempdir, fis[0].Name())
		break
		if i == 9 {
			t.Fatal("mount unsuccessful")
		}
	}

	_, err = os.Lstat(root + "/Music")
	if err != nil {
		t.Fatal("Music not found", err)
	}

	name := filepath.Join(root, fmt.Sprintf("mtpfs-test-%x", rand.Int31()))
	golden := "abcpxq134"
	if err := ioutil.WriteFile(name, []byte("abcpxq134"), 0644); err != nil {
		t.Fatal(err)
	}
	got, err := ioutil.ReadFile(name)
	if err != nil {
		t.Fatal("ReadFile failed", err)
	}

	if string(got) != golden {
		t.Fatalf("got %q, want %q", got, golden)
	}

	f, err := os.OpenFile(name, os.O_RDWR|os.O_APPEND, 0644)
	if err != nil {
		t.Fatal("OpenFile failed:", err)
	}

	log.Println("writing...")
	golden += "hello"
	f.Write([]byte("hello"))
	log.Println("done...")
	f.Close()

	got, err = ioutil.ReadFile(name)
	if err != nil {
		t.Fatal("ReadFile failed", err)
	}

	if string(got) != golden {
		t.Fatalf("got %q, want %q", got, golden)
	}

	newName := filepath.Join(root, fmt.Sprintf("mtpfs-test-%x", rand.Int31()))
	err = os.Rename(name, newName)
	if err != nil {
		t.Fatal("Rename failed", err)
	}

	if fi, err := os.Lstat(name); err == nil {
		t.Fatal("should have disappeared after rename", fi)
	}

	if _, err := os.Lstat(newName); err != nil {
		t.Fatal("should be able to stat after rename", err)
	}

	err = os.Remove(newName)
	if err != nil {
		t.Fatal("Remove failed", err)
	}
	if fi, err := os.Lstat(newName); err == nil {
		t.Fatal("should have disappeared after Remove", fi)
	}
}