Files
wehub-resource-sync 5357c39144
Fuzzer / Run Fuzzer (push) Has been cancelled
Race tests / Go race tests (ubuntu-22.04) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:01:40 +08:00

157 lines
4.3 KiB
Go

// Copyright 2023 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sqlserver
import (
"errors"
"fmt"
iofs "io/fs"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/google/uuid"
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
"github.com/dolthub/dolt/go/libraries/utils/filesys"
)
const ServerLocalCredsFile = "sql-server.info"
// LocalCreds is a struct that contains information about how to access the
// locally running server for a CLI process which wants to operate against a
// database while a sql-server process is running. It contains the pid of the
// process that created the lockfile, the port that the server is running on
// and the password to be used connecting to the server.
//
// Pid is a legacy field which is retained for compatibility but no longer
// influences the behavior of the running program(s).
type LocalCreds struct {
Pid int
Port int
Secret string
}
func NewLocalCreds(port int) *LocalCreds {
return &LocalCreds{os.Getpid(), port, uuid.New().String()}
}
// Best effort attempt to remove local creds file persisted as the Filesys
// rooted there.
func RemoveLocalCreds(fs filesys.Filesys) {
credsFilePath, err := fs.Abs(filepath.Join(dbfactory.DoltDir, ServerLocalCredsFile))
if err != nil {
return
}
_ = fs.Delete(credsFilePath, false)
}
// WriteLocalCreds writes a file containing the contents of LocalCreds to the
// DoltDir rooted at the provided Filesys.
func WriteLocalCreds(fs filesys.Filesys, creds *LocalCreds) error {
// if the DoltDir doesn't exist, create it.
doltDir, err := fs.Abs(dbfactory.DoltDir)
if err != nil {
return err
}
err = fs.MkDirs(doltDir)
if err != nil {
return err
}
credsFile, err := fs.Abs(filepath.Join(dbfactory.DoltDir, ServerLocalCredsFile))
if err != nil {
return err
}
portStr := strconv.Itoa(creds.Port)
if creds.Port < 0 {
portStr = "-"
}
return fs.WriteFile(credsFile, []byte(fmt.Sprintf("%d:%s:%s", creds.Pid, portStr, creds.Secret)), 0600)
}
// Starting at `fs`, look for the a ServerLocalCredsFile in the .dolt directory
// of this directory and every parent directory, until we find one. When we
// find one, we return its contents if we can open and parse it successfully.
// Otherwise, we return an error associated with attempting to read it. If we
// do not find anything all the way up to the root of the filesystem, returns
// `nil` *LocalCreds and a `nil` error.
func FindAndLoadLocalCreds(fs filesys.Filesys) (creds *LocalCreds, err error) {
root, err := fs.Abs(".")
if err != nil {
return nil, err
}
for root != "" && root[len(root)-1] != filepath.Separator {
creds, err := LoadLocalCreds(fs)
if err == nil {
return creds, err
}
// If we have an error that is not ErrNotExist, for example, a
// permission error opening the credentials file, or an error
// indicating that the contents of the file were malformed, go
// ahead and return the error and terminate our search here.
if !errors.Is(err, iofs.ErrNotExist) {
return nil, err
}
fs, err = fs.WithWorkingDir("..")
if err != nil {
return nil, err
}
root, err = fs.Abs(".")
if err != nil {
return nil, err
}
}
return nil, nil
}
func LoadLocalCreds(fs filesys.Filesys) (creds *LocalCreds, err error) {
rd, err := fs.OpenForRead(filepath.Join(dbfactory.DoltDir, ServerLocalCredsFile))
if err != nil {
return nil, err
}
defer rd.Close()
b := make([]byte, 256)
n, err := rd.Read(b)
if err != nil {
return nil, err
}
data := strings.TrimSpace(string(b[:n]))
parts := strings.Split(data, ":")
if len(parts) != 3 {
return nil, errors.New("invalid lock file format")
}
pid, err := strconv.Atoi(parts[0])
if err != nil {
return nil, err
}
port := -1
if parts[1] != "-" {
port, err = strconv.Atoi(parts[1])
if err != nil {
return nil, err
}
}
secret := parts[2]
return &LocalCreds{Pid: pid, Port: port, Secret: secret}, nil
}