diff --git a/Gomfile b/Gomfile index 929235a6..c96908e4 100644 --- a/Gomfile +++ b/Gomfile @@ -26,6 +26,7 @@ gom 'github.com/ugorji/go/codec', :commit => '71c2886f5a673a35f909803f38ece58101 gom 'github.com/vaughan0/go-ini', :commit => 'a98ad7ee00ec53921f08832bc06ecf7fd600e6a1' gom 'github.com/wsxiaoys/terminal/color', :commit => '5668e431776a7957528361f90ce828266c69ed08' gom 'golang.org/x/crypto/ssh/terminal', :commit => 'a7ead6ddf06233883deca151dffaef2effbf498f' +gom 'golang.org/x/sys/unix', :commit => '7a6e5648d140666db5d920909e082ca00a87ba2c' group :test do gom 'gopkg.in/check.v1' diff --git a/cmd/api_serve.go b/cmd/api_serve.go index fd4c765b..7064a1aa 100644 --- a/cmd/api_serve.go +++ b/cmd/api_serve.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "github.com/smira/aptly/api" + "github.com/smira/aptly/utils" "github.com/smira/commander" "github.com/smira/flag" "net/http" @@ -18,6 +19,17 @@ func aptlyAPIServe(cmd *commander.Command, args []string) error { return commander.ErrCommandError } + // There are only two working options for aptly's rootDir: + // 1. rootDir does not exist, then we'll create it + // 2. rootDir exists and is writable + // anything else must fail. + // E.g.: Running the service under a different user may lead to a rootDir + // that exists but is not usable due to access permissions. + err = utils.DirIsAccessible(context.Config().RootDir) + if err != nil { + return err + } + listen := context.Flags().Lookup("listen").Value.String() fmt.Printf("\nStarting web server at: %s (press Ctrl+C to quit)...\n", listen) diff --git a/cmd/serve.go b/cmd/serve.go index d1c19e03..03aabdf1 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -22,6 +22,17 @@ func aptlyServe(cmd *commander.Command, args []string) error { return commander.ErrCommandError } + // There are only two working options for aptly's rootDir: + // 1. rootDir does not exist, then we'll create it + // 2. rootDir exists and is writable + // anything else must fail. + // E.g.: Running the service under a different user may lead to a rootDir + // that exists but is not usable due to access permissions. + err = utils.DirIsAccessible(context.Config().RootDir) + if err != nil { + return err + } + if context.CollectionFactory().PublishedRepoCollection().Len() == 0 { fmt.Printf("No published repositories, unable to serve.\n") return nil diff --git a/system/t07_serve/RootDirInaccessible_gold b/system/t07_serve/RootDirInaccessible_gold new file mode 100644 index 00000000..8933b9cb --- /dev/null +++ b/system/t07_serve/RootDirInaccessible_gold @@ -0,0 +1 @@ +ERROR: '/root' is inaccessible, check access rights diff --git a/system/t07_serve/__init__.py b/system/t07_serve/__init__.py index 063f72da..1fb6e655 100644 --- a/system/t07_serve/__init__.py +++ b/system/t07_serve/__init__.py @@ -8,9 +8,24 @@ import signal import subprocess import shlex import time +import errno from lib import BaseTest +from socket import error as socket_error +class RootDirInaccessible(BaseTest): + """ + serve command aborts if rootDir is inaccessible + """ + fixtureDB = False + fixturePool = False + + configOverride = { + "rootDir": "/root" # any directory that exists but is not writable + } + + runCmd = "aptly serve -listen=127.0.0.1:8765" + expectedCode = 1 class Serve1Test(BaseTest): """ diff --git a/utils/utils.go b/utils/utils.go index d4d17a23..96d11f57 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,2 +1,23 @@ // Package utils collects various services: simple operations, compression, etc. package utils + +import ( + "fmt" + "os" + "golang.org/x/sys/unix" +) + +// check if directory exists and is accessible +func DirIsAccessible(filename string) error { + _, err := os.Stat(filename); + if err != nil { + if ! os.IsNotExist(err) { + return fmt.Errorf("Something went wrong, %v", err) + } + } else { + if unix.Access(filename, unix.W_OK) != nil { + return fmt.Errorf("'%s' is inaccessible, check access rights", filename) + } + } + return nil +}