commit 6d42c7b0e3902ad8b40b17ef096bb79d50ec56f1 Author: Yawning Angel yawning@schwanenlied.me Date: Fri May 23 06:43:24 2014 +0000
Implement MakeStateDir() instead of messing with the info structs.
This fixes bug #12088. --- pt.go | 35 ++++++++++------------------------- pt_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 25 deletions(-)
diff --git a/pt.go b/pt.go index 7f6c0a7..dba6701 100644 --- a/pt.go +++ b/pt.go @@ -322,20 +322,17 @@ func getManagedTransportVer() (string, error) { return "", versionError("no-version") }
-// Get the pluggable transport state location offered by Tor, and create it if -// missing. This function reads the enviornment variable -// TOR_PT_STATE_LOCATION. -func getStateLocation() (string, error) { - stateLocation, err := getenvRequired("TOR_PT_STATE_LOCATION") +// Return the directory name in the TOR_PT_STATE_LOCATION environment variable, +// creating it if it doesn't exist. Returns non-nil error if +// TOR_PT_STATE_LOCATION is not set or if there is an error creating the +// directory. +func MakeStateDir() (string, error) { + dir, err := getenvRequired("TOR_PT_STATE_LOCATION") if err != nil { return "", err } - err = os.MkdirAll(stateLocation, 0700) - if err != nil { - return "", envError(fmt.Sprintf("error creating TOR_PT_STATE_LOCATION: %s", err)) - } - - return stateLocation, nil + err = os.MkdirAll(dir, 0700) + return dir, err }
// Get the intersection of the method names offered by Tor and those in @@ -353,10 +350,9 @@ func getClientTransports(star []string) ([]string, error) { }
// This structure is returned by ClientSetup. It consists of a list of method -// names and the state location. +// names. type ClientInfo struct { MethodNames []string - StateLocation string }
// Check the client pluggable transports environment, emitting an error message @@ -370,11 +366,6 @@ func ClientSetup(star []string) (info ClientInfo, err error) { } line("VERSION", ver)
- info.StateLocation, err = getStateLocation() - if err != nil { - return - } - info.MethodNames, err = getClientTransports(star) if err != nil { return @@ -540,13 +531,12 @@ func readAuthCookieFile(filename string) ([]byte, error) {
// This structure is returned by ServerSetup. It consists of a list of // Bindaddrs, an address for the ORPort, an address for the extended ORPort (if -// any), an authentication cookie (if any), and the state location. +// any), and an authentication cookie (if any). type ServerInfo struct { Bindaddrs []Bindaddr OrAddr *net.TCPAddr ExtendedOrAddr *net.TCPAddr AuthCookie []byte - StateLocation string }
// Check the server pluggable transports environment, emitting an error message @@ -561,11 +551,6 @@ func ServerSetup(star []string) (info ServerInfo, err error) { } line("VERSION", ver)
- info.StateLocation, err = getStateLocation() - if err != nil { - return - } - info.Bindaddrs, err = getServerBindaddrs(star) if err != nil { return diff --git a/pt_test.go b/pt_test.go index 5689405..b569352 100644 --- a/pt_test.go +++ b/pt_test.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "net" "os" + "path" "sort" "testing" ) @@ -738,6 +739,64 @@ func TestExtOrPortSetup(t *testing.T) { testExtOrPortSetupIndividual(t, addr, methodName) }
+func TestMakeStateDir(t *testing.T) { + os.Clearenv() + + // TOR_PT_STATE_LOCATION not set. + _, err := MakeStateDir() + if err == nil { + t.Errorf("empty environment unexpectedly succeeded") + } + + // Setup the scratch directory. + tempDir, err := ioutil.TempDir("", "testMakeStateDir") + if err != nil { + t.Fatalf("ioutil.TempDir failed: %s", err) + } + defer os.RemoveAll(tempDir) + + goodTests := [...]string { + // Already existing directory. + tempDir, + + // Nonexistent directory, parent exists. + path.Join(tempDir, "parentExists"), + + // Nonexistent directory, parent doesn't exist. + path.Join(tempDir, "missingParent", "parentMissing"), + } + for _, test := range goodTests { + os.Setenv("TOR_PT_STATE_LOCATION", test) + dir, err := MakeStateDir() + if err != nil { + t.Errorf("MakeStateDir unexpectedly failed: %s", err) + } + if dir != test { + t.Errorf("MakeStateDir returned an unexpected path %s (expecting %s)", dir, test) + } + } + + // Name already exists, but is an ordinary file. + tempFile := path.Join(tempDir, "file") + f, err := os.Create(tempFile) + if err != nil { + t.Fatalf("os.Create failed: %s", err) + } + defer f.Close() + os.Setenv("TOR_PT_STATE_LOCATION", tempFile) + _, err = MakeStateDir() + if err == nil { + t.Errorf("MakeStateDir with a file unexpectedly succeded") + } + + // Directory name that cannot be created. (Subdir of a file) + os.Setenv("TOR_PT_STATE_LOCATION", path.Join(tempFile, "subDir")) + _, err = MakeStateDir() + if err == nil { + t.Errorf("MakeStateDir with a subdirectory of a file unexpectedly succeded") + } +} + func TestIsClient(t *testing.T) { os.Clearenv() if IsClient() {