gaulthiergain-tools/srcs/common/utils.go
2020-09-16 09:14:26 +02:00

199 lines
4.6 KiB
Go

// Copyright 2019 The UNICORE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
//
// Author: Gaulthier Gain <gaulthier.gain@uliege.be>
package common
import (
"encoding/json"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"reflect"
"strings"
)
// Contains checks if a given slice contains a particular string.
//
// It returns true if the given contains the searched string.
func Contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
// DownloadFile downloads a file from an URL and reads its content.
//
// It returns a pointer to a string that represents the file content and an
// error if any, otherwise it returns nil.
func DownloadFile(url string) (*string, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var bodyString string
if resp.StatusCode == http.StatusOK {
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
bodyString = string(bodyBytes)
}
return &bodyString, err
}
// GetProgramPath returns the absolute path of a given program.
//
// It returns a string that represents the absolute path of a program and an
// error if any, otherwise it returns nil.
func GetProgramPath(programName *string) (string, error) {
var programPath string
if ok, err := Exists(*programName); err != nil {
return programPath, err
} else if ok {
// Program (binary) is installed
if filepath.IsAbs(*programName) {
programPath = *programName
*programName = filepath.Base(programPath)
} else if programPath, err = filepath.Abs(*programName); err != nil {
return programPath, err
}
} else {
// Run 'which' command to determine if program has a symbolic name
out, err := ExecuteCommand("which", []string{*programName})
if err != nil {
return programPath, err
} else {
// Check if out is a valid path
if _, err := os.Stat(out); err == nil {
PrintWarning("Unknown Program -> will skip gathering" +
" symbols, system calls and shared libs process")
} else {
programPath = strings.TrimSpace(out)
}
}
}
return programPath, nil
}
// ---------------------------------Record Data---------------------------------
// RecordDataTxt saves data into a text file named by filename.
//
// It returns an error if any, otherwise it returns nil.
func RecordDataTxt(filename string, headers []string, data interface{}) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
v := reflect.ValueOf(data)
values := make([]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
values[i] = v.Field(i).Interface()
if err := WriteMapToFile(file, headers[i], values[i]); err != nil {
return err
}
}
return nil
}
// WriteMapToFile saves map into a text file named by filename.
//
// It returns an error if any, otherwise it returns nil.
func WriteMapToFile(file *os.File, headerName string, in interface{}) error {
header := "----------------------------------------------\n" +
headerName + "\n----------------------------------------------\n"
if _, err := file.WriteString(header); err != nil {
return err
}
switch v := in.(type) {
case map[string]string:
for key, value := range v {
var str string
if len(value) > 0 {
str = key + "@" + value
} else {
str = key
}
if _, err := file.WriteString(str + "\n"); err != nil {
return err
}
}
case map[string][]string:
for key, values := range v {
var str string
if len(values) > 0 {
str = key + "->" + strings.Join(values, ",")
} else {
str = key
}
if _, err := file.WriteString(str + "\n"); err != nil {
return err
}
}
}
return nil
}
// -------------------------------------JSON------------------------------------
// RecordDataJson saves json into a json file named by filename.
//
// It returns an error if any, otherwise it returns nil.
func RecordDataJson(filename string, data *Data) error {
b, err := json.Marshal(data)
if err != nil {
return err
}
if err = ioutil.WriteFile(filename+".json", b, os.ModePerm); err != nil {
return err
}
return nil
}
// ReadDataJson load json from a json file named by filename.
//
// It returns a Data structure initialized and an error if any, otherwise it
// returns nil.
func ReadDataJson(filename string, data *Data) (*Data, error) {
jsonFile, err := os.Open(filename + ".json")
if err != nil {
return nil, err
}
defer jsonFile.Close()
byteValue, err := ioutil.ReadAll(jsonFile)
if err != nil {
return nil, err
}
if err = json.Unmarshal(byteValue, &data); err != nil {
return nil, err
}
return data, nil
}