upgrade golangci-lint to v2

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2025-03-29 11:21:01 +01:00
commit 2255c5f000
No known key found for this signature in database
GPG key ID: 935D2952DEC4EECF
23 changed files with 113 additions and 112 deletions

View file

@ -614,7 +614,6 @@ jobs:
go-version: '1.24'
- uses: actions/checkout@v4
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v7
with:
args: --timeout=10m
version: latest

View file

@ -1,52 +1,54 @@
version: "2"
run:
timeout: 10m
issues-exit-code: 1
tests: true
linters-settings:
dupl:
threshold: 150
errcheck:
check-type-assertions: false
check-blank: false
goconst:
min-len: 3
min-occurrences: 3
gocyclo:
min-complexity: 15
gofmt:
simplify: true
goimports:
local-prefixes: github.com/drakkan/sftpgo
#govet:
# report about shadowed variables
#check-shadowing: true
#enable:
# - fieldalignment
issues:
include:
- EXC0002
- EXC0012
- EXC0013
- EXC0014
- EXC0015
linters:
enable:
- goconst
- errcheck
- gofmt
- goimports
- revive
- unconvert
- unparam
- bodyclose
- dogsled
- dupl
- goconst
- gocyclo
- misspell
- whitespace
- dupl
- revive
- rowserrcheck
- dogsled
- govet
- unconvert
- unparam
- whitespace
settings:
dupl:
threshold: 150
errcheck:
check-type-assertions: false
check-blank: false
goconst:
min-len: 3
min-occurrences: 3
gocyclo:
min-complexity: 15
exclusions:
generated: lax
presets:
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- goimports
settings:
gofmt:
simplify: true
goimports:
local-prefixes:
- github.com/drakkan/sftpgo
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$

View file

@ -78,11 +78,12 @@ Please take a look at the usage below to customize the options.`,
providerConf.Actions.ExecuteOn = nil
logger.InfoToConsole("Initializing provider: %q config file: %q", providerConf.Driver, viper.ConfigFileUsed())
err = dataprovider.InitializeDatabase(providerConf, configDir)
if err == nil {
switch err {
case nil:
logger.InfoToConsole("Data provider successfully initialized/updated")
} else if err == dataprovider.ErrNoInitRequired {
case dataprovider.ErrNoInitRequired:
logger.InfoToConsole("%v", err.Error())
} else {
default:
logger.ErrorToConsole("Unable to initialize/update the data provider: %v", err)
os.Exit(1)
}

View file

@ -64,7 +64,7 @@ func (c *fakeConnection) AddUser(user dataprovider.User) error {
if err != nil {
return err
}
c.BaseConnection.User = user
c.User = user
return nil
}
@ -999,9 +999,10 @@ func TestConnectionStatus(t *testing.T) {
assert.Len(t, stats, 3)
for _, stat := range stats {
assert.Equal(t, stat.Username, username)
if stat.ConnectionID == "SFTP_id1" {
switch stat.ConnectionID {
case "SFTP_id1":
assert.Len(t, stat.Transfers, 2)
} else if stat.ConnectionID == "DAV_id3" {
case "DAV_id3":
assert.Len(t, stat.Transfers, 1)
}
}

View file

@ -771,10 +771,7 @@ func (c *BaseConnection) Copy(virtualSourcePath, virtualTargetPath string) error
return err
}
}
createTargetDir := true
if dstInfo != nil && dstInfo.IsDir() {
createTargetDir = false
}
createTargetDir := dstInfo == nil || !dstInfo.IsDir()
if err := c.checkCopy(srcInfo, dstInfo, virtualSourcePath, destPath); err != nil {
return err
}

View file

@ -62,7 +62,7 @@ func (d *dbDefender) GetHost(ip string) (dataprovider.DefenderEntry, error) {
// and increase ban time if the IP is found.
// This method must be called as soon as the client connects
func (d *dbDefender) IsBanned(ip, protocol string) bool {
if d.baseDefender.isBanned(ip, protocol) {
if d.isBanned(ip, protocol) {
return true
}
@ -95,15 +95,15 @@ func (d *dbDefender) AddEvent(ip, protocol string, event HostEvent) bool {
return true
}
score := d.baseDefender.getScore(event)
score := d.getScore(event)
host, err := dataprovider.AddDefenderEvent(ip, score, d.getStartObservationTime())
if err != nil {
return false
}
d.baseDefender.logEvent(ip, protocol, event, host.Score)
d.logEvent(ip, protocol, event, host.Score)
if host.Score > d.config.Threshold {
d.baseDefender.logBan(ip, protocol)
d.logBan(ip, protocol)
banTime := time.Now().Add(time.Duration(d.config.BanTime) * time.Minute)
err = dataprovider.SetDefenderBanTime(ip, util.GetTimeAsMsSinceEpoch(banTime))
if err == nil {

View file

@ -148,7 +148,7 @@ func (d *memoryDefender) IsBanned(ip, protocol string) bool {
defer d.RUnlock()
return d.baseDefender.isBanned(ip, protocol)
return d.isBanned(ip, protocol)
}
// DeleteHost removes the specified IP from the defender lists
@ -188,7 +188,7 @@ func (d *memoryDefender) AddEvent(ip, protocol string, event HostEvent) bool {
delete(d.banned, ip)
}
score := d.baseDefender.getScore(event)
score := d.getScore(event)
ev := hostEvent{
dateTime: time.Now(),
@ -207,11 +207,11 @@ func (d *memoryDefender) AddEvent(ip, protocol string, event HostEvent) bool {
idx++
}
}
d.baseDefender.logEvent(ip, protocol, event, hs.TotalScore)
d.logEvent(ip, protocol, event, hs.TotalScore)
hs.Events = hs.Events[:idx]
if hs.TotalScore >= d.config.Threshold {
d.baseDefender.logBan(ip, protocol)
d.logBan(ip, protocol)
d.banned[ip] = time.Now().Add(time.Duration(d.config.BanTime) * time.Minute)
delete(d.hosts, ip)
d.cleanupBanned()
@ -225,7 +225,7 @@ func (d *memoryDefender) AddEvent(ip, protocol string, event HostEvent) bool {
d.hosts[ip] = hs
}
} else {
d.baseDefender.logEvent(ip, protocol, event, ev.score)
d.logEvent(ip, protocol, event, ev.score)
d.hosts[ip] = hostScore{
TotalScore: ev.score,
Events: []hostEvent{ev},

View file

@ -35,7 +35,7 @@ var (
)
// BaseTransfer contains protocols common transfer details for an upload or a download.
type BaseTransfer struct { //nolint:maligned
type BaseTransfer struct {
ID int64
BytesSent atomic.Int64
BytesReceived atomic.Int64

View file

@ -3700,7 +3700,8 @@ func comparePbkdf2PasswordAndHash(password, hashedPassword string) (bool, error)
}
func getSSLMode() string {
if config.Driver == PGSQLDataProviderName || config.Driver == CockroachDataProviderName {
switch config.Driver {
case PGSQLDataProviderName, CockroachDataProviderName:
switch config.SSLMode {
case 0:
return "disable"
@ -3715,7 +3716,7 @@ func getSSLMode() string {
case 5:
return "allow"
}
} else if config.Driver == MySQLDataProviderName {
case MySQLDataProviderName:
if config.requireCustomTLSForMySQL() {
return "custom"
}

View file

@ -287,7 +287,7 @@ func (c *Connection) RemoveDir(name string) error {
func (c *Connection) Symlink(oldname, newname string) error {
c.UpdateLastActivity()
return c.BaseConnection.CreateSymlink(oldname, newname)
return c.CreateSymlink(oldname, newname)
}
// ReadDir implements ClientDriverExtensionFilelist

View file

@ -136,7 +136,7 @@ func (t *transfer) closeIO() error {
} else if t.reader != nil {
err = t.reader.Close()
if metadater, ok := t.reader.(vfs.Metadater); ok {
t.BaseTransfer.SetMetadata(metadater.Metadata())
t.SetMetadata(metadater.Metadata())
}
}
return err

View file

@ -66,7 +66,7 @@ func testSMTPConfig(w http.ResponseWriter, r *http.Request) {
}
}
if req.AuthType == 3 {
if err := req.Config.OAuth2.Validate(); err != nil {
if err := req.OAuth2.Validate(); err != nil {
sendAPIResponse(w, r, err, "", http.StatusBadRequest)
return
}
@ -106,10 +106,10 @@ func (s *httpdServer) handleSMTPOAuth2TokenRequestPost(w http.ResponseWriter, r
}
configs.SetNilsToEmpty()
if err := configs.SMTP.TryDecrypt(); err == nil {
req.OAuth2Config.ClientSecret = configs.SMTP.OAuth2.ClientSecret.GetPayload()
req.ClientSecret = configs.SMTP.OAuth2.ClientSecret.GetPayload()
}
}
cfg := req.OAuth2Config.GetOAuth2()
cfg := req.GetOAuth2()
cfg.RedirectURL = req.BaseRedirectURL + webOAuth2RedirectPath
clientSecret := kms.NewPlainSecret(cfg.ClientSecret)
clientSecret.SetAdditionalData(xid.New().String())

View file

@ -126,7 +126,7 @@ func (f *httpdFile) closeIO() error {
} else if f.reader != nil {
err = f.reader.Close()
if metadater, ok := f.reader.(vfs.Metadater); ok {
f.BaseTransfer.SetMetadata(metadater.Metadata())
f.SetMetadata(metadater.Metadata())
}
}
return err

View file

@ -1364,19 +1364,19 @@ func TestGroupSettingsOverride(t *testing.T) {
switch f.Name {
case folderName1:
assert.Equal(t, mappedPath1, f.MappedPath)
assert.Equal(t, 3, f.BaseVirtualFolder.FsConfig.OSConfig.ReadBufferSize)
assert.Equal(t, 5, f.BaseVirtualFolder.FsConfig.OSConfig.WriteBufferSize)
assert.Equal(t, 3, f.FsConfig.OSConfig.ReadBufferSize)
assert.Equal(t, 5, f.FsConfig.OSConfig.WriteBufferSize)
assert.True(t, slices.Contains([]string{"/vdir1", "/vdir2"}, f.VirtualPath))
case folderName2:
assert.Equal(t, mappedPath2, f.MappedPath)
assert.Equal(t, "/vdir3", f.VirtualPath)
assert.Equal(t, 0, f.BaseVirtualFolder.FsConfig.OSConfig.ReadBufferSize)
assert.Equal(t, 0, f.BaseVirtualFolder.FsConfig.OSConfig.WriteBufferSize)
assert.Equal(t, 0, f.FsConfig.OSConfig.ReadBufferSize)
assert.Equal(t, 0, f.FsConfig.OSConfig.WriteBufferSize)
case folderName3:
assert.Equal(t, mappedPath3, f.MappedPath)
assert.Equal(t, "/vdir4", f.VirtualPath)
assert.Equal(t, 1, f.BaseVirtualFolder.FsConfig.OSConfig.ReadBufferSize)
assert.Equal(t, 2, f.BaseVirtualFolder.FsConfig.OSConfig.WriteBufferSize)
assert.Equal(t, 1, f.FsConfig.OSConfig.ReadBufferSize)
assert.Equal(t, 2, f.FsConfig.OSConfig.WriteBufferSize)
}
}
}

View file

@ -857,11 +857,12 @@ func (c *Configuration) generateDefaultHostKeys(configDir string) error {
if _, err = os.Stat(autoFile); errors.Is(err, fs.ErrNotExist) {
logger.Info(logSender, "", "No host keys configured and %q does not exist; try to create a new host key", autoFile)
logger.InfoToConsole("No host keys configured and %q does not exist; try to create a new host key", autoFile)
if k == defaultPrivateRSAKeyName {
switch k {
case defaultPrivateRSAKeyName:
err = util.GenerateRSAKeys(autoFile)
} else if k == defaultPrivateECDSAKeyName {
case defaultPrivateECDSAKeyName:
err = util.GenerateECDSAKeys(autoFile)
} else {
default:
err = util.GenerateEd25519Keys(autoFile)
}
if err != nil {

View file

@ -201,15 +201,16 @@ func (c *sshCommand) updateQuota(sshDestPath string, filesNum int, filesSize int
func (c *sshCommand) handleHashCommands() error {
var h hash.Hash
if c.command == "md5sum" {
switch c.command {
case "md5sum":
h = md5.New()
} else if c.command == "sha1sum" {
case "sha1sum":
h = sha1.New()
} else if c.command == "sha256sum" {
case "sha256sum":
h = sha256.New()
} else if c.command == "sha384sum" {
case "sha384sum":
h = sha512.New384()
} else {
default:
h = sha512.New()
}
var response string

View file

@ -177,7 +177,7 @@ func (t *transfer) closeIO() error {
} else if t.readerAt != nil {
err = t.readerAt.Close()
if metadater, ok := t.readerAt.(vfs.Metadater); ok {
t.BaseTransfer.SetMetadata(metadater.Metadata())
t.SetMetadata(metadater.Metadata())
}
}
return err

View file

@ -60,7 +60,7 @@ func (c *Conn) Read(b []byte) (n int, err error) {
c.BytesReadFromDeadline.Store(0)
// we set both read and write deadlines here otherwise after the request
// is read writing the response fails with an i/o timeout error
err = c.Conn.SetDeadline(time.Now().Add(c.ReadTimeout))
err = c.SetDeadline(time.Now().Add(c.ReadTimeout))
if err != nil {
return 0, err
}
@ -75,7 +75,7 @@ func (c *Conn) Write(b []byte) (n int, err error) {
c.BytesWrittenFromDeadline.Store(0)
// we extend the read deadline too, not sure it's necessary,
// but it doesn't hurt
err = c.Conn.SetDeadline(time.Now().Add(c.WriteTimeout))
err = c.SetDeadline(time.Now().Add(c.WriteTimeout))
if err != nil {
return
}

View file

@ -235,7 +235,7 @@ func ParseBytes(s string) (int64, error) {
lastDigit := 0
hasComma := false
for _, r := range s {
if !(unicode.IsDigit(r) || r == '.' || r == ',') {
if !unicode.IsDigit(r) && r != '.' && r != ',' {
break
}
if r == ',' {
@ -246,7 +246,7 @@ func ParseBytes(s string) (int64, error) {
num := s[:lastDigit]
if hasComma {
num = strings.Replace(num, ",", "", -1)
num = strings.ReplaceAll(num, ",", "")
}
f, err := strconv.ParseFloat(num, 64)
@ -489,10 +489,7 @@ func GetDirsForVirtualPath(virtualPath string) []string {
}
}
dirsForPath := []string{virtualPath}
for {
if virtualPath == "/" {
break
}
for virtualPath != "/" {
virtualPath = path.Dir(virtualPath)
dirsForPath = append(dirsForPath, virtualPath)
}

View file

@ -561,7 +561,7 @@ func (fs *AzureBlobFs) GetDirSize(dirname string) (int, int64, error) {
metric.AZListObjectsCompleted(err)
return numFiles, size, err
}
for _, blobItem := range resp.ListBlobsFlatSegmentResponse.Segment.BlobItems {
for _, blobItem := range resp.Segment.BlobItems {
if blobItem.Properties != nil {
contentType := util.GetStringFromPointer(blobItem.Properties.ContentType)
isDir := checkDirectoryMarkers(contentType, blobItem.Metadata)
@ -629,7 +629,7 @@ func (fs *AzureBlobFs) Walk(root string, walkFn filepath.WalkFunc) error {
metric.AZListObjectsCompleted(err)
return err
}
for _, blobItem := range resp.ListBlobsFlatSegmentResponse.Segment.BlobItems {
for _, blobItem := range resp.Segment.BlobItems {
name := util.GetStringFromPointer(blobItem.Name)
if fs.isEqual(name, prefix) {
continue
@ -886,7 +886,7 @@ func (fs *AzureBlobFs) hasContents(name string) (bool, error) {
return result, err
}
result = len(resp.ListBlobsFlatSegmentResponse.Segment.BlobItems) > 0
result = len(resp.Segment.BlobItems) > 0
}
metric.AZListObjectsCompleted(nil)
@ -909,9 +909,9 @@ func (fs *AzureBlobFs) downloadPart(ctx context.Context, blockBlob *blockblob.Cl
if err != nil {
return err
}
defer resp.DownloadResponse.Body.Close()
defer resp.Body.Close()
_, err = io.ReadAtLeast(resp.DownloadResponse.Body, buf, int(count))
_, err = io.ReadAtLeast(resp.Body, buf, int(count))
if err != nil {
return err
}
@ -1280,7 +1280,7 @@ func (l *azureBlobDirLister) Next(limit int) ([]os.FileInfo, error) {
return l.cache, err
}
for _, blobPrefix := range page.ListBlobsHierarchySegmentResponse.Segment.BlobPrefixes {
for _, blobPrefix := range page.Segment.BlobPrefixes {
name := util.GetStringFromPointer(blobPrefix.Name)
// we don't support prefixes == "/" this will be sent if a key starts with "/"
if name == "" || name == "/" {
@ -1295,7 +1295,7 @@ func (l *azureBlobDirLister) Next(limit int) ([]os.FileInfo, error) {
l.prefixes[strings.TrimSuffix(name, "/")] = true
}
for _, blobItem := range page.ListBlobsHierarchySegmentResponse.Segment.BlobItems {
for _, blobItem := range page.Segment.BlobItems {
name := util.GetStringFromPointer(blobItem.Name)
name = strings.TrimPrefix(name, l.prefix)
size := int64(0)

View file

@ -59,8 +59,8 @@ func NewCryptFs(connectionID, rootDir, mountPath string, config CryptFsConfig) (
connectionID: connectionID,
rootDir: rootDir,
mountPath: getMountPath(mountPath),
readBufferSize: config.OSFsConfig.ReadBufferSize * 1024 * 1024,
writeBufferSize: config.OSFsConfig.WriteBufferSize * 1024 * 1024,
readBufferSize: config.ReadBufferSize * 1024 * 1024,
writeBufferSize: config.WriteBufferSize * 1024 * 1024,
},
masterKey: []byte(config.Passphrase.GetPayload()),
}

View file

@ -730,10 +730,10 @@ func (fs *GCSFs) setWriterAttrs(objectWriter *storage.Writer, flag int, name str
contentType = mime.TypeByExtension(path.Ext(name))
}
if contentType != "" {
objectWriter.ObjectAttrs.ContentType = contentType
objectWriter.ContentType = contentType
}
if fs.config.StorageClass != "" {
objectWriter.ObjectAttrs.StorageClass = fs.config.StorageClass
objectWriter.StorageClass = fs.config.StorageClass
}
if fs.config.ACL != "" {
objectWriter.PredefinedACL = fs.config.ACL

View file

@ -165,7 +165,7 @@ func (f *webDavFile) checkFirstRead() error {
if !f.Connection.User.HasPerm(dataprovider.PermDownload, path.Dir(f.GetVirtualPath())) {
return f.Connection.GetPermissionDeniedError()
}
transferQuota := f.BaseTransfer.GetTransferQuota()
transferQuota := f.GetTransferQuota()
if !transferQuota.HasDownloadSpace() {
f.Connection.Log(logger.LevelInfo, "denying file read due to quota limits")
return f.Connection.GetReadQuotaExceededError()
@ -212,7 +212,7 @@ func (f *webDavFile) Read(p []byte) (n int, err error) {
} else if r != nil {
f.reader = r
}
f.BaseTransfer.SetCancelFn(cancelFn)
f.SetCancelFn(cancelFn)
}
f.ErrTransfer = e
f.startOffset = 0
@ -322,9 +322,10 @@ func (f *webDavFile) Seek(offset int64, whence int) (int64, error) {
if f.GetType() == common.TransferDownload {
readOffset := f.startOffset + f.BytesSent.Load()
if offset == 0 && readOffset == 0 {
if whence == io.SeekStart {
switch whence {
case io.SeekStart:
return 0, nil
} else if whence == io.SeekEnd {
case io.SeekEnd:
if err := f.updateStatInfo(); err != nil {
return 0, err
}
@ -363,7 +364,7 @@ func (f *webDavFile) Seek(offset int64, whence int) (int64, error) {
f.reader = r
}
f.ErrTransfer = err
f.BaseTransfer.SetCancelFn(cancelFn)
f.SetCancelFn(cancelFn)
f.Unlock()
return startByte, err
@ -403,7 +404,7 @@ func (f *webDavFile) closeIO() error {
} else if f.reader != nil {
err = f.reader.Close()
if metadater, ok := f.reader.(vfs.Metadater); ok {
f.BaseTransfer.SetMetadata(metadater.Metadata())
f.SetMetadata(metadater.Metadata())
}
}
return err