// vfs.go package models import ( "crypto/rand" "database/sql" "errors" "fmt" "path" "time" _ "github.com/mattn/go-sqlite3" ) type Vfs struct { DB *sql.DB } type VfsNodeType int const ( VfsNodeTypeFile VfsNodeType = iota VfsNodeTypeService VfsNodeTypeDirectory VfsNodeTypeSymlink ) type VfsNode struct { ID uint64 Name string ParentID uint64 Type VfsNodeType CreatedAt time.Time UpdatedAt time.Time } type VfsUser struct { Name string Token string } type VfsDirEntry struct { ID uint64 Name string Type VfsNodeType } // NewVfs 创建新的 VFS 实例 func NewVfs(dbPath string) (*Vfs, error) { db, err := sql.Open("sqlite3", dbPath) if err != nil { return nil, err } _, err = db.Exec(` CREATE TABLE IF NOT EXISTS vfs_nodes ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, parent_id INTEGER, type INTEGER NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(parent_id, name) )`) if err != nil { return nil, err } _, err = db.Exec(` CREATE TABLE IF NOT EXISTS vfs_users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, token TEXT NOT NULL UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )`) if err != nil { return nil, err } err = createInitialDirectories(db) if err != nil { return nil, err } return &Vfs{DB: db}, nil } // 创建初始目录结构 func createInitialDirectories(db *sql.DB) error { var err error // 创建 /home 目录 _, err = db.Exec(` INSERT OR IGNORE INTO vfs_nodes (name, parent_id, type, created_at, updated_at) VALUES ('home', 0, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, VfsNodeTypeDirectory) if err != nil { return err } // 创建 /public 目录 _, err = db.Exec(` INSERT OR IGNORE INTO vfs_nodes (name, parent_id, type, created_at, updated_at) VALUES ('public', 0, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, VfsNodeTypeDirectory) if err != nil { return err } return nil } func generateToken() string { bytes := make([]byte, 16) if _, err := rand.Read(bytes); err != nil { // fallback to time-based token return fmt.Sprintf("%x", time.Now().UnixNano()) } return fmt.Sprintf("%x", bytes) } // 添加用户相关操作 func (v *Vfs) CreateUser(username string) (string, error) { // 生成随机token token := generateToken() // 检查用户是否已存在 _, err := v.GetUserByName(username) if err == nil { return "", errors.New("user already exists") } // 插入用户(不使用事务) _, err = v.DB.Exec("INSERT INTO vfs_users (name, token) VALUES (?, ?)", username, token) if err != nil { return "", err } // 使用 defer 确保出错时能清理已创建的用户 defer func() { if err != nil { v.DB.Exec("DELETE FROM vfs_users WHERE name = ? AND token = ?", username, token) } }() // 确保 /home 目录存在 homeDir, getHomeErr := v.GetNodeByPath("/home/") if getHomeErr != nil { // 如果 /home 不存在,创建它 homeDir = &VfsNode{ Name: "home", ParentID: 0, Type: VfsNodeTypeDirectory, } if createHomeErr := v.CreateVFSNode(homeDir); createHomeErr != nil { err = createHomeErr return "", err } } // 创建用户目录 /home/username userDir := &VfsNode{ Name: username, ParentID: homeDir.ID, Type: VfsNodeTypeDirectory, CreatedAt: time.Now(), UpdatedAt: time.Now(), } if createDirErr := v.CreateVFSNode(userDir); createDirErr != nil { err = createDirErr return "", err } return token, nil } func (v *Vfs) DeleteUser(username string) error { // TODO: 递归删除用户相关文件 // 这里暂时只删除用户记录 _, err := v.DB.Exec("DELETE FROM vfs_users WHERE name = ?", username) return err } func (v *Vfs) GetUserByToken(token string) (*VfsUser, error) { user := &VfsUser{} err := v.DB.QueryRow("SELECT name, token FROM vfs_users WHERE token = ?", token). Scan(&user.Name, &user.Token) if err != nil { if err == sql.ErrNoRows { return nil, errors.New("user not found") } return nil, err } return user, nil } func (v *Vfs) GetUserByName(username string) (*VfsUser, error) { user := &VfsUser{} err := v.DB.QueryRow("SELECT name, token FROM vfs_users WHERE name = ?", username). Scan(&user.Name, &user.Token) if err != nil { if err == sql.ErrNoRows { return nil, errors.New("user not found") } return nil, err } return user, nil } // GetChildrenID 获取目录下所有子项的 ID func (v *Vfs) GetChildren(parentID uint64) ([]VfsDirEntry, error) { rows, err := v.DB.Query("SELECT id, name, type FROM vfs_nodes WHERE parent_id = ?", parentID) if err != nil { return nil, err } defer rows.Close() var dirEntrys []VfsDirEntry for rows.Next() { var entry VfsDirEntry if err := rows.Scan(&entry.ID, &entry.Name, &entry.Type); err != nil { return nil, err } dirEntrys = append(dirEntrys, entry) } return dirEntrys, nil } // GetParentID 根据父路径查找父节点 ID // parentPath 应该是 ParsePathComponents 的第一个返回值 func (v *Vfs) GetParentID(parentPath string) (uint64, error) { // 根目录特殊处理 if parentPath == "/" || parentPath == "" { return 0, nil } // 递归查找父路径ID // 先解析父路径的父路径和节点名 grandParentPath, parentName, _, err := ParsePathComponents(parentPath) if err != nil { return 0, err } // 递归获取祖父节点ID grandParentID, err := v.GetParentID(grandParentPath) if err != nil { return 0, err } // 在祖父节点下查找父节点 var parentID uint64 err = v.DB.QueryRow("SELECT id FROM vfs_nodes WHERE parent_id = ? AND name = ?", grandParentID, parentName).Scan(&parentID) if err != nil { if err == sql.ErrNoRows { return 0, errors.New("parent path not found") } return 0, err } return parentID, nil } // GetNodeByPath 根据完整路径查找节点 func (v *Vfs) GetNodeByPath(fullPath string) (*VfsNode, error) { // 根目录特殊处理 if path.Clean(fullPath) == "/" { return &VfsNode{ ID: 0, Name: "/", ParentID: 0, Type: VfsNodeTypeDirectory, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, nil } // 使用 ParsePathComponents 解析路径 parentPath, nodeName, nodeType, err := ParsePathComponents(fullPath) if err != nil { return nil, err } // 获取父节点ID parentID, err := v.GetParentID(parentPath) if err != nil { return nil, err } // 根据 parentID, nodeName, nodeType 查找或创建节点 node, err := v.GetNodeByParentIDAndName(parentID, nodeName) if err != nil { // 如果节点不存在,可以选择创建它或者返回错误 // 这里根据你的需求决定是返回错误还是创建节点 return nil, err } if node.Type != nodeType { return nil, errors.New("node type mismatch") } return node, nil } // GetNodeByParentIDAndName 根据父ID和名称查找节点 func (v *Vfs) GetNodeByParentIDAndName(parentID uint64, name string) (*VfsNode, error) { node := &VfsNode{} err := v.DB.QueryRow(` SELECT id, name, parent_id, type, created_at, updated_at FROM vfs_nodes WHERE parent_id = ? AND name = ?`, parentID, name).Scan( &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) if err != nil { if err == sql.ErrNoRows { return nil, errors.New("node not found") } return nil, err } return node, nil } // CreateNodeByComponents 根据路径组件创建节点 func (v *Vfs) CreateNodeByComponents(parentPath, nodeName string, nodeType VfsNodeType) (*VfsNode, error) { // 获取父节点ID parentID, err := v.GetParentID(parentPath) if err != nil { return nil, err } // 创建新节点 node := &VfsNode{ Name: nodeName, ParentID: parentID, Type: nodeType, CreatedAt: time.Now(), UpdatedAt: time.Now(), } // 保存到数据库 result, err := v.DB.Exec(` INSERT INTO vfs_nodes (name, parent_id, type, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`, node.Name, node.ParentID, node.Type, node.CreatedAt, node.UpdatedAt) if err != nil { return nil, err } // 获取插入的ID id, err := result.LastInsertId() if err != nil { return nil, err } node.ID = uint64(id) return node, nil } func ParsePathComponents(pathStr string) (parentPath, nodeName string, nodeType VfsNodeType, err error) { // FIXME: 路径判断以及update的类型判断 abspath := path.Clean(pathStr) if !path.IsAbs(abspath) { return "", "", 0, errors.New("path must be absolute") } // 特殊处理根路径 if abspath == "/" { return "", "", VfsNodeTypeDirectory, nil } // 判断是文件还是目录 nodeType = VfsNodeTypeFile // 如果原始路径以 / 结尾,则为目录 if len(pathStr) > 1 && pathStr[len(pathStr)-1] == '/' { nodeType = VfsNodeTypeDirectory } if nodeType == VfsNodeTypeFile && path.Ext(pathStr) == ".api" { nodeType = VfsNodeTypeService } // 分割路径 parentPath, nodeName = path.Split(abspath) // 清理父路径 if parentPath != "/" && parentPath != "" { parentPath = path.Clean(parentPath) } // 处理特殊情况 if parentPath == "." { parentPath = "/" } return parentPath, nodeName, nodeType, nil } // MoveToPath 将节点移动到指定路径 func (v *Vfs) MoveToPath(node *VfsNode, destPath string) error { // 1. 解析目标路径 parentPath, nodeName, _, err := ParsePathComponents(destPath) if err != nil { return fmt.Errorf("invalid destination path: %w", err) } // 2. 查找目标父节点 parentID, err := v.GetParentID(parentPath) if err != nil { return fmt.Errorf("failed to find parent directory '%s': %w", parentPath, err) } // 3. 检查目标位置是否已存在同名节点 _, err = v.GetNodeByParentIDAndName(parentID, nodeName) if err == nil { return fmt.Errorf("destination path '%s' already exists", destPath) } if err.Error() != "node not found" { return fmt.Errorf("error checking destination path: %w", err) } // 4. 更新节点的父节点ID和名称 node.ParentID = parentID node.Name = nodeName node.UpdatedAt = time.Now() // 5. 更新数据库中的节点信息 _, err = v.DB.Exec(` UPDATE vfs_nodes SET name = ?, parent_id = ?, updated_at = ? WHERE id = ?`, node.Name, node.ParentID, node.UpdatedAt, node.ID) if err != nil { return fmt.Errorf("failed to update node: %w", err) } return nil } func (v *Vfs) CreateVFSNode(p *VfsNode) error { _, err := v.DB.Exec(` INSERT INTO vfs_nodes (name, parent_id, type, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`, p.Name, p.ParentID, p.Type, time.Now(), time.Now()) return err } func (v *Vfs) DeleteVFSNode(p *VfsNode) error { _, err := v.DB.Exec("DELETE FROM vfs_nodes WHERE id = ?", p.ID) return err } func (v *Vfs) GetVFSNode(p *VfsNode) *VfsNode { node := &VfsNode{} err := v.DB.QueryRow(` SELECT id, name, parent_id, type, created_at, updated_at FROM vfs_nodes WHERE id = ?`, p.ID).Scan( &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) if err != nil { return nil } return node } func (v *Vfs) UpdateVFSNode(p *VfsNode) error { _, err := v.DB.Exec(` UPDATE vfs_nodes SET name = ?, parent_id = ?, type = ?, updated_at = ? WHERE id = ?`, p.Name, p.ParentID, p.Type, time.Now(), p.ID) return err }