Files
drivefs/cmd/main.go
Matheus Sampaio Queiroga 9bd1c98de0 Refactor gdrive client and add compatibility to cgofuse
- Update modules version
- Add cmd to start fuse mount
- Update Write and Read logic and add ReadAt and WriteAt
- Clean cache function and add cache to readdir

Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
2025-08-10 17:36:33 -03:00

139 lines
3.4 KiB
Go

package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"net"
"net/http"
"net/url"
"os"
"os/signal"
"path/filepath"
"runtime"
"golang.org/x/oauth2"
"sirherobrine23.com.br/Sirherobrine23/cgofuse/fs"
"sirherobrine23.com.br/Sirherobrine23/drivefs"
)
var (
Config = flag.String("config", "", "config file")
Target = flag.String("target", "", "target mount fs")
)
var _ fs.FileSystem[drivefs.File] = (*drivefs.Gdrive)(nil)
func main() {
flag.Parse()
configFile, err := os.OpenFile(*Config, os.O_CREATE|os.O_RDWR, 0600)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
defer configFile.Close()
runtime.KeepAlive(configFile)
var gConfig drivefs.GoogleOauthConfig
json.NewDecoder(configFile).Decode(&gConfig)
gConfig.UserAuth = func(ctx context.Context, config *oauth2.Config) (token *oauth2.Token, err error) {
listen, err := net.Listen("tcp", ":0")
if err != nil {
return nil, err
}
defer listen.Close()
url, err := url.Parse("http://" + listen.Addr().String())
if err != nil {
return nil, err
}
_, port, err := net.SplitHostPort(url.Host)
if err != nil {
return nil, err
}
url.Host = "localhost:" + port
config.RedirectURL = url.String()
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Fprintf(os.Stderr, "Go to the following link in your browser then type the authorization code:\n%v\n", authURL)
http.Serve(listen, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
if code == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("No code"))
return
}
if token, err = config.Exchange(ctx, code); err == nil {
gConfig.AccessToken = token.AccessToken
gConfig.RefreshToken = token.RefreshToken
gConfig.TokenType = token.TokenType
gConfig.Expire = token.Expiry
configFile.Seek(0, 0)
js := json.NewEncoder(configFile)
js.SetIndent("", " ")
if err = js.Encode(&gConfig); err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
}
listen.Close()
}))
return
}
gdriveClient, err := drivefs.NewGoogleDrive(gConfig)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
defer func() {
gConfig.AccessToken = gdriveClient.(*drivefs.Gdrive).GoogleToken.AccessToken
gConfig.RefreshToken = gdriveClient.(*drivefs.Gdrive).GoogleToken.RefreshToken
gConfig.TokenType = gdriveClient.(*drivefs.Gdrive).GoogleToken.TokenType
gConfig.Expire = gdriveClient.(*drivefs.Gdrive).GoogleToken.Expiry
configFile.Seek(0, 0)
js := json.NewEncoder(configFile)
js.SetIndent("", " ")
js.Encode(&gConfig)
}()
fmt.Fprintf(os.Stderr, "Mount overlayfs into %q\n", *Target)
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
defer stop()
cwd, err := filepath.Abs(*Target)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
if _, err := os.Stat(cwd); os.IsNotExist(err) {
if err = os.Mkdir(cwd, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
}
fs := fs.New(cwd, gdriveClient)
if err := fs.Mount(ctx); err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
fmt.Fprintf(os.Stderr, "Mounted overlayfs in %q\n", cwd)
<-ctx.Done()
fmt.Fprintf(os.Stderr, "Unmount overlayfs\n")
fs.Done()
fmt.Fprintf(os.Stderr, "Unmounted overlayfs\n")
}