Esempio n. 1
0
// runMakeBucketCmd is the handler for mc mb command
func runMakeBucketCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "mb", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}
	config := mustGetMcConfig()
	for _, arg := range ctx.Args() {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		msg, err := doMakeBucketCmd(targetURL)
		if err != nil {
			console.Fatalln(msg)
		}
		console.Infoln(msg)
	}
}
Esempio n. 2
0
// runListCmd - is a handler for mc ls command
func runListCmd(ctx *cli.Context) {
	args := ctx.Args()
	if globalAliasFlag {
		if !ctx.Args().Present() {
			args = []string{"."}
		}
	} else if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "ls", 1) // last argument is exit code
	}

	config := mustGetMcConfig()
	for _, arg := range args {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		// if recursive strip off the "..."
		newTargetURL := stripRecursiveURL(targetURL)
		err = doListCmd(newTargetURL, isURLRecursive(targetURL))
		if err != nil {
			console.Fatalf("Failed to list : %s. %s\n", targetURL, err)
		}
	}
}
Esempio n. 3
0
func runAccessCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "access", 1) // last argument is exit code
	}
	config := mustGetMcConfig()
	acl := bucketACL(ctx.Args().First())
	if !acl.isValidBucketACL() {
		console.Fatalf("Valid types are [private, public, readonly]. %s\n", errInvalidACL{acl: acl.String()})
	}
	for _, arg := range ctx.Args().Tail() {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		msg, err := doUpdateAccessCmd(targetURL, acl)
		if err != nil {
			console.Fatalln(msg)
		}
		console.Infoln(msg)
	}
}
Esempio n. 4
0
// checkCopySyntaxTypeB verifies if the source is a valid file and target is a valid dir.
func checkCopySyntaxTypeB(srcURLs []string, tgtURL string) {
	if len(srcURLs) != 1 {
		console.Fatalf("Invalid number of source arguments to copy command. %s\n", NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	srcURL := srcURLs[0]
	_, srcContent, err := url2Stat(srcURL)
	// Source exist?.
	if err != nil {
		console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
	}
	if srcContent.Type.IsDir() {
		console.Fatalf("Source ‘%s’ is a folder. Use ‘%s...’ argument to copy this folder and its contents recursively. %s\n", srcURL, srcURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	if !srcContent.Type.IsRegular() {
		console.Fatalf("Source ‘%s’ is not a file. %s\n", srcURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}

	_, tgtContent, err := url2Stat(tgtURL)
	// Target exist?.
	if err == nil {
		if !tgtContent.Type.IsDir() {
			console.Fatalf("Target ‘%s’ is not a folder. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
		}
	}
}
Esempio n. 5
0
func runCastCmd(ctx *cli.Context) {
	checkCastSyntax(ctx)

	session := newSessionV2()

	var err error
	session.Header.CommandType = "cast"
	session.Header.RootPath, err = os.Getwd()
	if err != nil {
		session.Close()
		session.Delete()
		console.Fatalf("Unable to get current working folder. %s\n", err)
	}

	// extract URLs.
	session.Header.CommandArgs, err = args2URLs(ctx.Args())
	if err != nil {
		session.Close()
		session.Delete()
		console.Fatalf("One or more unknown URL types found in %s. %s\n", ctx.Args(), err)
	}

	doCastCmdSession(session)
	session.Close()
	session.Delete()
}
Esempio n. 6
0
func runCatCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cat", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}
	config := mustGetMcConfig()
	// Convert arguments to URLs: expand alias, fix format...
	for _, arg := range ctx.Args() {
		sourceURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		errorMsg, err := doCatCmd(sourceURL)
		if err != nil {
			console.Fatalln(errorMsg)
		}
	}
}
Esempio n. 7
0
// Check for the environment early on and gracefully report.
func checkConfig() {
	_, err := user.Current()
	if err != nil {
		console.Fatalf("Unable to determine current user. %s\n", err)
	}

	// Ensures config file is sane
	_, err = getMcConfig()
	if err != nil {
		console.Fatalf("Unable to read config file. %s\n", err)
	}

}
Esempio n. 8
0
// mustGetHostConfig retrieves host specific configuration such as access keys, exits upon error
func mustGetHostConfig(URL string) *hostConfig {
	hostCfg, err := getHostConfig(URL)
	if err != nil {
		console.Fatalf("Unable to retrieve host configuration. %s\n", NewIodine(iodine.New(err, nil)))
	}
	return hostCfg
}
Esempio n. 9
0
// loadSession - reads session file if exists and re-initiates internal variables
func loadSessionV2(sid string) (*sessionV2, error) {
	if !isSessionDirExists() {
		return nil, NewIodine(iodine.New(errInvalidArgument{}, nil))
	}
	sessionFile := getSessionFile(sid)

	_, err := os.Stat(sessionFile)
	if err != nil {
		return nil, NewIodine(iodine.New(err, nil))
	}

	s := &sessionV2{}
	s.Header = &sessionV2Header{}
	s.SessionID = sid
	s.Header.Version = "1.1.0"
	qs, err := quick.New(s.Header)
	if err != nil {
		return nil, NewIodine(iodine.New(err, nil))
	}
	err = qs.Load(sessionFile)
	if err != nil {
		return nil, NewIodine(iodine.New(err, nil))
	}

	s.mutex = new(sync.Mutex)
	s.Header = qs.Data().(*sessionV2Header)

	s.DataFP, err = os.Open(getSessionDataFile(s.SessionID))
	if err != nil {
		console.Fatalf("Unable to open session data file \""+getSessionDataFile(s.SessionID)+"\". %s", NewIodine(iodine.New(errNotConfigured{}, nil)))
	}

	return s, nil
}
Esempio n. 10
0
// mustGetMcConfigDir - construct minio client config folder or fail
func mustGetMcConfigDir() (configDir string) {
	configDir, err := getMcConfigDir()
	if err != nil {
		console.Fatalf("Unable to determine default configuration folder. %s\n", NewIodine(iodine.New(err, nil)))
	}
	return configDir
}
Esempio n. 11
0
// mustGetMcConfigPath - similar to getMcConfigPath, ignores errors
func mustGetMcConfigPath() string {
	p, err := getMcConfigPath()
	if err != nil {
		console.Fatalf("Unable to determine default config path. %s\n", NewIodine(iodine.New(err, nil)))
	}
	return p
}
Esempio n. 12
0
// mustNewConfig instantiates a new config handler, exists upon error
func mustNewConfig() quick.Config {
	config, err := newConfig()
	if err != nil {
		console.Fatalf("Unable to instantiate a new config handler. %s\n", NewIodine(iodine.New(err, nil)))
	}
	return config
}
Esempio n. 13
0
// mustGetMcConfig - reads configuration file and returns configs, exits on error
func mustGetMcConfig() *configV1 {
	config, err := getMcConfig()
	if err != nil {
		console.Fatalf("Unable to retrieve mc configuration. %s\n", err)
	}
	return config
}
Esempio n. 14
0
//   NOTE: All the parse rules should reduced to A: Copy(Source, Target).
//
//   * VALID RULES
//   =======================
//   A: copy(f, f) -> copy(f, f)
//   B: copy(f, d) -> copy(f, d/f) -> A
//   C: copy(d1..., d2) -> []copy(d1/f, d1/d2/f) -> []A
//
//   * INVALID RULES
//   =========================
//   A: copy(d, *)
//   B: copy(d..., f)
//   C: copy(*, d...)
//
func checkCopySyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code.
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), iodine.New(err, nil))
	}

	srcURLs := URLs[:len(URLs)-1]
	tgtURL := URLs[len(URLs)-1]

	/****** Generic rules *******/
	// Recursive URLs are not allowed in target.
	if isURLRecursive(tgtURL) {
		console.Fatalf("Target ‘%s’ cannot be recursive. %s\n", tgtURL, iodine.New(err, nil))
	}

	switch guessCopyURLType(srcURLs, tgtURL) {
	case copyURLsTypeA: // Source is already a regular file.
		// no verification needed, pass through
	case copyURLsTypeB: // Source is already a regular file.
		// no verification needed, pass through
	case copyURLsTypeC:
		for _, srcURL := range srcURLs {
			srcURL = stripRecursiveURL(srcURL)
			_, srcContent, err := url2Stat(srcURL)
			// Source exist?.
			if err != nil {
				console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, iodine.New(err, nil))
			}
			if srcContent.Type.IsRegular() { // Ellipses is supported only for directories.
				console.Fatalf("Source ‘%s’ is not a directory. %s\n", stripRecursiveURL(srcURL), iodine.New(err, nil))
			}
		}
	case copyURLsTypeD:
		// only verify if target is a valid directory and exists
		if !isTargetURLDir(tgtURL) {
			console.Fatalf("Target ‘%s’ should be a directory and exist, when we have a mixture of files and folders in source\n", tgtURL)
		}
	default:
		console.Fatalln("Invalid arguments. Unable to determine how to copy. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Esempio n. 15
0
func checkCastSyntaxTypeB(srcURL string, tgtURLs []string) {
	if len(tgtURLs) == 0 && tgtURLs == nil {
		console.Fatalf("Invalid number of target arguments to cast command. %s\n", NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	_, srcContent, err := url2Stat(srcURL)
	// Source exist?.
	if err != nil {
		console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
	}
	if srcContent.Type.IsDir() {
		console.Fatalf("Source ‘%s’ is a folder. Use ‘%s...’ argument to cast this folder and its contents recursively. %s\n", srcURL, srcURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	if !srcContent.Type.IsRegular() {
		console.Fatalf("Source ‘%s’ is not a file. %s\n", srcURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	// targetURL can be folder or file, internally TypeB calls TypeA if it finds a file
}
Esempio n. 16
0
// migrateSessionV1ToV2 migrates all session files from v1 to v2.
// This function should be called from the main early on.
func migrateSessionV1ToV2() {
	for _, sid := range getSessionIDsV1() {
		err := os.Remove(getSessionFileV1(sid))
		if err != nil {
			console.Fatalf("Migration failed. Unable to remove old session file %s. %s\n", getSessionFileV1(sid), NewIodine(iodine.New(err, nil)))
		}
	}
}
Esempio n. 17
0
// checkCopySyntaxTypeD verifies if the source is a valid list of file or valid recursive dir and target is a valid dir.
func checkCopySyntaxTypeD(srcURLs []string, tgtURL string) {
	for _, srcURL := range srcURLs {
		if isURLRecursive(srcURL) {
			srcURL = stripRecursiveURL(srcURL)
			_, srcContent, err := url2Stat(srcURL)
			// Source exist?.
			if err != nil {
				console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
			}
			if !srcContent.Type.IsDir() { // Ellipses is supported only for folders.
				console.Fatalf("Source ‘%s’ is not a folder. %s\n", stripRecursiveURL(srcURL), NewIodine(iodine.New(errInvalidArgument{}, nil)))
			}
		} else { // Regular URL.
			_, srcContent, err := url2Stat(srcURL)
			// Source exist?.
			if err != nil {
				console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
			}
			if srcContent.Type.IsDir() {
				console.Fatalf("Source ‘%s’ is a folder. Use ‘%s...’ argument to copy this folder and its contents recursively. %s\n", srcURL, srcURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
			}
			if !srcContent.Type.IsRegular() {
				console.Fatalf("Source ‘%s’ is not a file. %s\n", srcURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
			}
		}
	}
	_, tgtContent, err := url2Stat(tgtURL)
	// Target exist?.
	if err != nil {
		console.Fatalf("Unable to stat target ‘%s’. %s\n", tgtURL, NewIodine(iodine.New(err, nil)))
	}
	if !tgtContent.Type.IsDir() {
		console.Fatalf("Target ‘%s’ is not a folder. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
}
Esempio n. 18
0
// Verify main command syntax.
func checkMainSyntax(c *cli.Context) {
	configPath, err := getConfigPath()
	if err != nil {
		console.Fatalf("Unable to obtain user's home directory. \nError: %s\n", err)
	}
	if configPath == "" {
		console.Fatalln("Config folder cannot be empty, please specify --config-dir <foldername>.")
	}
}
Esempio n. 19
0
// checkCastSyntax(URLs []string)
func checkCastSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cast", 1) // last argument is exit code.
	}
	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), NewIodine(iodine.New(err, nil)))
	}

	srcURL := URLs[0]
	tgtURLs := URLs[1:]

	/****** Generic rules *******/
	// Source cannot be a folder (except when recursive)
	if !isURLRecursive(srcURL) {
		_, srcContent, err := url2Stat(srcURL)
		// Source exist?.
		if err != nil {
			console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
		}
		if !srcContent.Type.IsRegular() {
			if srcContent.Type.IsDir() {
				console.Fatalf("Source ‘%s’ is a folder. Please use ‘%s...’ to recursively copy this folder and its contents.\n", srcURL, srcURL)
			}
			console.Fatalf("Source ‘%s’ is not a regular file.\n", srcURL)
		}
	}
	// Recursive URLs are not allowed in target.
	for _, tgtURL := range tgtURLs {
		if isURLRecursive(tgtURL) {
			console.Fatalf("Target ‘%s’ cannot be recursive. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
		}
	}

	for _, tgtURL := range tgtURLs {
		url, err := client.Parse(tgtURL)
		if err != nil {
			console.Fatalf("Unable to parse target ‘%s’ argument. %s\n", tgtURL, NewIodine(iodine.New(err, nil)))
		}
		if url.Host != "" {
			if url.Path == string(url.Separator) {
				console.Fatalf("Bucket creation detected for %s, cloud storage URL's should use ‘mc mb’ to create buckets\n", tgtURL)
			}
		}
	}

	switch guessCastURLType(srcURL, tgtURLs) {
	case castURLsTypeA: // File -> File.
		checkCastSyntaxTypeA(srcURL, tgtURLs)
	case castURLsTypeB: // File -> Folder.
		checkCastSyntaxTypeB(srcURL, tgtURLs)
	case castURLsTypeC: // Folder -> Folder.
		checkCastSyntaxTypeC(srcURL, tgtURLs)
	default:
		console.Fatalln("Invalid arguments. Unable to determine how to cast. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Esempio n. 20
0
// checkCastSyntax(URLs []string)
func checkCastSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cast", 1) // last argument is exit code.
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), iodine.New(err, nil))
	}

	srcURL := URLs[0]
	tgtURLs := URLs[1:]

	/****** Generic rules *******/
	// Source cannot be a directory (except when recursive)
	if !isURLRecursive(srcURL) {
		_, srcContent, err := url2Stat(srcURL)
		// Source exist?.
		if err != nil {
			console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, iodine.New(err, nil))
		}
		if !srcContent.Type.IsRegular() {
			if srcContent.Type.IsDir() {
				console.Fatalf("Source ‘%s’ is a directory. Please use ‘%s...’ to recursively copy this directory and its contents.\n", srcURL, srcURL)
			}
			console.Fatalf("Source ‘%s’ is not a regular file.\n", srcURL)
		}
	}
	// Recursive URLs are not allowed in target.
	for _, tgtURL := range tgtURLs {
		if isURLRecursive(tgtURL) {
			console.Fatalf("Target ‘%s’ cannot be recursive. %s\n", tgtURL, iodine.New(err, nil))
		}
	}

	switch guessCastURLType(srcURL, tgtURLs) {
	case castURLsTypeA: // Source is already a regular file.
		//
	case castURLsTypeB: // Source is already a regular file.
		//
	case castURLsTypeC:
		srcURL = stripRecursiveURL(srcURL)
		_, srcContent, err := url2Stat(srcURL)
		// Source exist?.
		if err != nil {
			console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, iodine.New(err, nil))
		}

		if srcContent.Type.IsRegular() { // Ellipses is supported only for directories.
			console.Fatalf("Source ‘%s’ is not a directory. %s\n", stripRecursiveURL(srcURL), iodine.New(err, nil))
		}

	default:
		console.Fatalln("Invalid arguments. Unable to determine how to cast. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Esempio n. 21
0
// provides a new session
func newSessionV2() *sessionV2 {
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}

	s := &sessionV2{}
	s.Header = &sessionV2Header{}
	s.Header.Version = "1.1.0"
	// map of command and files copied
	s.Header.CommandArgs = nil
	s.Header.When = time.Now().UTC()
	s.mutex = new(sync.Mutex)
	s.SessionID = newSID(8)
	var err error
	s.DataFP, err = os.Create(getSessionDataFile(s.SessionID))
	if err != nil {
		console.Fatalf("Unable to create session data file \""+getSessionDataFile(s.SessionID)+"\". %s\n", err)
	}
	return s
}
Esempio n. 22
0
func getSessionIDs() (sids []string) {
	sessionList, err := filepath.Glob(getSessionDir() + "/*.json")
	if err != nil {
		console.Fatalf("Unable to list session folder ‘%s’, %s", getSessionDir(), NewIodine(iodine.New(err, nil)))
	}

	for _, path := range sessionList {
		sids = append(sids, strings.TrimSuffix(filepath.Base(path), ".json"))
	}
	return sids
}
Esempio n. 23
0
func registerApp() *cli.App {
	// Register all the commands
	registerCmd(lsCmd)      // List contents of a bucket
	registerCmd(mbCmd)      // make a bucket
	registerCmd(catCmd)     // concantenate an object to standard output
	registerCmd(cpCmd)      // copy objects and files from multiple sources to single destination
	registerCmd(castCmd)    // cast objects and files from single source to multiple destinations
	registerCmd(sessionCmd) // session handling for resuming copy and cast operations
	registerCmd(diffCmd)    // compare two objects
	registerCmd(accessCmd)  // set permissions [public, private, readonly, authenticated] for buckets and folders.
	registerCmd(configCmd)  // generate configuration "/home/harsha/.mc/config.json" file.
	registerCmd(updateCmd)  // update Check for new software updates

	// register all the flags
	registerFlag(configFlag) // path to config folder
	registerFlag(quietFlag)  // suppress console output
	registerFlag(forceFlag)  // force copying data
	registerFlag(aliasFlag)  // OS toolchain mimic
	registerFlag(themeFlag)  // console theme flag
	registerFlag(jsonFlag)   // json formatted output
	registerFlag(debugFlag)  // enable debugging output

	app := cli.NewApp()
	app.Usage = "Minio Client for cloud storage and filesystems"
	app.Version = getVersion()
	app.Commands = commands
	app.Compiled = getVersion()
	app.Flags = flags
	app.Author = "Minio.io"
	app.CustomAppHelpTemplate = `NAME:
  {{.Name}} - {{.Usage}}

USAGE:
  {{.Name}} {{if .Flags}}[global flags] {{end}}command{{if .Flags}} [command flags]{{end}} [arguments...]

COMMANDS:
  {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
  {{end}}{{if .Flags}}
GLOBAL FLAGS:
  {{range .Flags}}{{.}}
  {{end}}{{end}}
VERSION:
  {{if .Compiled}}
  {{.Compiled}}{{end}}
  {{range $key, $value := ExtraInfo}}
{{$key}}:
  {{$value}}
{{end}}
`
	app.CommandNotFound = func(ctx *cli.Context, command string) {
		console.Fatalf("Command not found: ‘%s’\n", command)
	}
	return app
}
Esempio n. 24
0
//   NOTE: All the parse rules should reduced to A: Copy(Source, Target).
//
//   * VALID RULES
//   =======================
//   A: copy(f, f) -> copy(f, f)
//   B: copy(f, d) -> copy(f, d/f) -> A
//   C: copy(d1..., d2) -> []copy(d1/f, d2/d1/f) -> []A
//   D: copy([]{d1... | f}, d2) -> []{copy(d1/f, d2/d1/f) | copy(f, d2/f )} -> []A
//
//   * INVALID RULES
//   =========================
//   A: copy(d, *)
//   B: copy(d..., f)
//   C: copy(*, d...)
//
func checkCopySyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code.
	}
	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), NewIodine(iodine.New(err, nil)))
	}

	srcURLs := URLs[:len(URLs)-1]
	tgtURL := URLs[len(URLs)-1]

	/****** Generic rules *******/
	// Recursive URLs are not allowed in target.
	if isURLRecursive(tgtURL) {
		console.Fatalf("Recursive option is not supported for target ‘%s’ argument. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	url, err := client.Parse(tgtURL)
	if err != nil {
		console.Fatalf("Unable to parse target ‘%s’ argument. %s\n", tgtURL, NewIodine(iodine.New(err, nil)))
	}
	if url.Host != "" {
		if url.Path == string(url.Separator) {
			console.Fatalf("Bucket creation detected for %s, cloud storage URL's should use ‘mc mb’ to create buckets\n", tgtURL)
		}
	}
	switch guessCopyURLType(srcURLs, tgtURL) {
	case copyURLsTypeA: // File -> File.
		checkCopySyntaxTypeA(srcURLs, tgtURL)
	case copyURLsTypeB: // File -> Folder.
		checkCopySyntaxTypeB(srcURLs, tgtURL)
	case copyURLsTypeC: // Folder... -> Folder.
		checkCopySyntaxTypeC(srcURLs, tgtURL)
	case copyURLsTypeD: // File | Folder... -> Folder.
		checkCopySyntaxTypeD(srcURLs, tgtURL)
	default:
		console.Fatalln("Invalid arguments. Unable to determine how to copy. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Esempio n. 25
0
// runDiffCmd - is a handler for mc diff command
func runDiffCmd(ctx *cli.Context) {
	if len(ctx.Args()) != 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "diff", 1) // last argument is exit code
	}

	config := mustGetMcConfig()
	firstURL := ctx.Args().First()
	secondURL := ctx.Args()[1]

	var err error
	firstURL, err = getExpandedURL(firstURL, config.Aliases)
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case errUnsupportedScheme:
			console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
		default:
			console.Fatalf("Unable to parse argument %s. %s\n", firstURL, err)
		}
	}
	secondURL, err = getExpandedURL(secondURL, config.Aliases)
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case errUnsupportedScheme:
			console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
		default:
			console.Fatalf("Unable to parse argument %s. %s\n", secondURL, err)
		}
	}
	if isURLRecursive(secondURL) {
		console.Fatalf("Second URL cannot be recursive. %s\n", errInvalidArgument{})
	}
	newFirstURL := stripRecursiveURL(firstURL)
	for diff := range doDiffCmd(newFirstURL, secondURL, isURLRecursive(firstURL)) {
		if diff.err != nil {
			console.Fatalln(diff.message)
		}
		console.Infoln(diff.message)
	}
}
Esempio n. 26
0
func clearSession(sid string) {
	if sid == "all" {
		for _, sid := range getSessionIDs() {
			session, err := loadSessionV2(sid)
			if err != nil {
				console.Fatalf("Unable to load session ‘%s’, %s", sid, NewIodine(iodine.New(err, nil)))
			}
			session.Close()
		}
		return
	}

	if !isSession(sid) {
		console.Fatalf("Session ‘%s’ not found.\n", sid)
	}

	session, err := loadSessionV2(sid)
	if err != nil {
		console.Fatalf("Unable to load session ‘%s’, %s", sid, NewIodine(iodine.New(err, nil)))
	}
	session.Close()
}
Esempio n. 27
0
func getSessionIDsV1() (sids []string) {
	sessionList, err := filepath.Glob(getSessionDir() + "/*")
	if err != nil {
		console.Fatalf("Unable to list session directory ‘%s’, %s", getSessionDir(), NewIodine(iodine.New(err, nil)))
	}

	for _, path := range sessionList {
		sidReg := regexp.MustCompile("^[a-zA-Z]{8}$")
		sid := filepath.Base(path)
		if sidReg.Match([]byte(sid)) {
			sessionV1, err := loadSessionV1(sid)
			if err != nil {
				console.Fatalf("Unable to load session ‘%s’, %s", sid, NewIodine(iodine.New(err, nil)))
			}
			if sessionV1.Version != "1.0.0" {
				continue
			}
			sids = append(sids, sid)
		}
	}
	return sids
}
Esempio n. 28
0
func firstTimeRun() {
	if !isMcConfigExists() {
		if err := createMcConfigDir(); err != nil {
			console.Fatalf("Unable to create ‘mc’ config folder. %s\n", err)
		}
		config, err := newConfig()
		if err != nil {
			console.Fatalln(NewIodine(iodine.New(err, nil)))
		}
		err = writeConfig(config)
		if err != nil {
			console.Fatalln(NewIodine(iodine.New(err, nil)))
		}
		console.Infoln("Configuration written to [" + mustGetMcConfigPath() + "]. Please update your access credentials.")
	}
	if !isSessionDirExists() {
		if err := createSessionDir(); err != nil {
			console.Fatalf("Unable to create ‘mc’ session folder. %s\n", err)
		}
	}
	checkGolangVersion()
}
Esempio n. 29
0
func checkCastSyntaxTypeC(srcURL string, tgtURLs []string) {
	if len(tgtURLs) == 0 && tgtURLs == nil {
		console.Fatalf("Invalid number of target arguments to cast command. %s\n", NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	srcURL = stripRecursiveURL(srcURL)
	_, srcContent, err := url2Stat(srcURL)
	// Source exist?.
	if err != nil {
		console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
	}

	if srcContent.Type.IsRegular() { // Ellipses is supported only for folders.
		console.Fatalf("Source ‘%s’ is not a folder. %s\n", stripRecursiveURL(srcURL), NewIodine(iodine.New(err, nil)))
	}
	for _, tgtURL := range tgtURLs {
		_, content, err := url2Stat(tgtURL)
		if err == nil {
			if !content.Type.IsDir() {
				console.Fatalf("One of the target ‘%s’ is not a folder. cannot have mixtures of directories and files while copying directories recursively. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
			}
		}
	}
}
Esempio n. 30
0
// checkCopySyntaxTypeC verifies if the source is a valid recursive dir and target is a valid dir.
func checkCopySyntaxTypeC(srcURLs []string, tgtURL string) {
	if len(srcURLs) != 1 {
		console.Fatalf("Invalid number of source arguments to copy command. %s\n", NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	srcURL := srcURLs[0]
	srcURL = stripRecursiveURL(srcURL)
	_, srcContent, err := url2Stat(srcURL)
	// Source exist?.
	if err != nil {
		console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
	}
	if srcContent.Type.IsRegular() { // Ellipses is supported only for folders.
		console.Fatalf("Source ‘%s’ is not a folder. %s\n", stripRecursiveURL(srcURL), NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}

	_, tgtContent, err := url2Stat(tgtURL)
	// Target exist?.
	if err == nil {
		if !tgtContent.Type.IsDir() {
			console.Fatalf("Target ‘%s’ is not a folder. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
		}
	}
}