Skip to content

Commit

Permalink
fix: normalize paths on windows
Browse files Browse the repository at this point in the history
Fixes #73 by normalizing paths to UNC on windows. This is _slightly_ less hacky
than registering a new schema.

The underlying issue was twofold:

1. When specifying a windows file URL as `file://c:/foo/bar`, go barfs because
`:` can't be in a domain name.
2. When specifying a windows file URL as `file:///c:/foo/bar`, we'd end up
trying to open `/c:/foo/bar` which is actually `CURRENT_DRIVE:/c:/foo/bar`.
  • Loading branch information
Stebalien committed Mar 24, 2020
1 parent 125e1f0 commit 45b384f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
11 changes: 11 additions & 0 deletions path_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//+build !windows

package log

import (
"path/filepath"
)

func normalizePath(p string) (string, error) {
return filepath.Abs(p)
}
35 changes: 35 additions & 0 deletions path_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//+build windows

package log

import (
"fmt"
"path/filepath"
"strings"
)

func normalizePath(p string) (string, error) {
if p == "" {
return "", fmt.Errorf("path empty")
}
p, err := filepath.Abs(p)
if err != nil {
return "", err
}
// Is this _really_ an absolute path?
if !strings.HasPrefix(p, "\\\\") {
// It's a drive: path!
// Return a UNC path.
p = "\\\\?\\" + p
}

// This will return file:////?/c:/foobar
//
// Why? Because:
// 1. Go will choke on file://c:/ because the "domain" includes a :.
// 2. Windows will choke on file:///c:/ because the path will be
// /c:/... which is _relative_ to the current drive.
//
// This path (a) has no "domain" and (b) starts with a slash. Yay!
return "file://" + filepath.ToSlash(p), nil
}
8 changes: 6 additions & 2 deletions setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ func SetupLogging() {
zapCfg.OutputPaths = []string{"stderr"}
// check if we log to a file
if logfp := os.Getenv(envLoggingFile); len(logfp) > 0 {
zapCfg.OutputPaths = append(zapCfg.OutputPaths, logfp)
if path, err := normalizePath(logfp); err != nil {
fmt.Fprintf(os.Stderr, "failed to resolve log path '%q', logging to stderr only: %s\n", logfp, err)
} else {
zapCfg.OutputPaths = append(zapCfg.OutputPaths, path)
}
}

// set the backend(s)
Expand All @@ -83,7 +87,7 @@ func SetupLogging() {
var err error
lvl, err = LevelFromString(logenv)
if err != nil {
fmt.Println("error setting log levels", err)
fmt.Fprintf(os.Stderr, "error setting log levels: %s\n", err)
}
}
zapCfg.Level.SetLevel(zapcore.Level(lvl))
Expand Down

0 comments on commit 45b384f

Please sign in to comment.