@cryptotaxi247 / kubo / commits / b29945e79

Windows root parse fix

License: MIT Signed-off-by: Dominic Della Valle <ddvpublic@gmail.com>

Dominic Della Valle committed Oct 25, 2016 at 12:39 UTC b29945e791071654cb36a6391fc13643c52c0050
1 file changed +48 -1
commands/cli/parse.go
+48 -1
@@ -11,7 +11,9 @@ import (
11
12 cmds "github.com/ipfs/go-ipfs/commands"
13 files "github.com/ipfs/go-ipfs/commands/files"
14 +
15 logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
16 + osh "gx/ipfs/QmXuBJ7DR6k3rmUEKtvVMhwjmXDuJgXXPUt4LQXKBMsU93/go-os-helper"
17 u "gx/ipfs/QmZuY8aV7zbNXVy6DyN9SmnuH3o9nG852F4aTiSBpts8d1/go-ipfs-util"
18 )
19
@@ -398,8 +400,20 @@ func getArgDef(i int, argDefs []cmds.Argument) *cmds.Argument {
400
401 const notRecursiveFmtStr = "'%s' is a directory, use the '-%s' flag to specify directories"
402 const dirNotSupportedFmtStr = "Invalid path '%s', argument '%s' does not support directories"
403 +const winDriveLetterFmtStr = "%q is a drive letter, not a drive path"
404
405 func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (files.File, error) {
406 + // resolve Windows relative dot paths like `X:.\somepath`
407 + if osh.IsWindows() {
408 + if len(fpath) >= 3 && fpath[1:3] == ":." {
409 + var err error
410 + fpath, err = filepath.Abs(fpath)
411 + if err != nil {
412 + return nil, err
413 + }
414 + }
415 + }
416 +
417 if fpath == "." {
418 cwd, err := os.Getwd()
419 if err != nil {
@@ -412,7 +426,7 @@ func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (fi
426 fpath = cwd
427 }
428
415 - fpath = filepath.ToSlash(filepath.Clean(fpath))
429 + fpath = filepath.Clean(fpath)
430
431 stat, err := os.Lstat(fpath)
432 if err != nil {
@@ -428,6 +442,10 @@ func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (fi
442 }
443 }
444
445 + if osh.IsWindows() {
446 + return windowsParseFile(fpath, hidden, stat)
447 + }
448 +
449 return files.NewSerialFile(path.Base(fpath), fpath, hidden, stat)
450 }
451
@@ -480,3 +498,32 @@ func (r *messageReader) Read(b []byte) (int, error) {
498 func (r *messageReader) Close() error {
499 return r.r.Close()
500 }
501 +
502 +func windowsParseFile(fpath string, hidden bool, stat os.FileInfo) (files.File, error) {
503 + // special cases for Windows drive roots i.e. `X:\` and their long form `\\?\X:\`
504 + // drive path must be preserved as `X:\` (or it's longform) and not converted to `X:`, `X:.`, `\`, or `/` here
505 + switch len(fpath) {
506 + case 3:
507 + // `X:` is cleaned to `X:.` which may not be the expected behaviour by the user, they'll need to provide more specific input
508 + if fpath[1:3] == ":." {
509 + return nil, fmt.Errorf(winDriveLetterFmtStr, fpath[:2])
510 + }
511 + // `X:\` needs to preserve the `\`, path.Base(filepath.ToSlash(fpath)) results in `X:` which is not valid
512 + if fpath[1:3] == ":\\" {
513 + return files.NewSerialFile(fpath, fpath, hidden, stat)
514 + }
515 + case 6:
516 + // `\\?\X:` long prefix form of `X:`, still ambiguous
517 + if fpath[:4] == "\\\\?\\" && fpath[5] == ':' {
518 + return nil, fmt.Errorf(winDriveLetterFmtStr, fpath)
519 + }
520 + case 7:
521 + // `\\?\X:\` long prefix form is translated into short form `X:\`
522 + if fpath[:4] == "\\\\?\\" && fpath[5] == ':' && fpath[6] == '\\' {
523 + fpath = string(fpath[4]) + ":\\"
524 + return files.NewSerialFile(fpath, fpath, hidden, stat)
525 + }
526 + }
527 +
528 + return files.NewSerialFile(path.Base(filepath.ToSlash(fpath)), fpath, hidden, stat)
529 +}