sftp O_RDONLY works fine but O_RDWR does not - go

I could read the file after using functions Open() or OpenFile(path, os.O_RDONLY), but I could not remove the file after it. So I tried to open the file with the write flag os.RDWR like below code to see if I can remove the file. However, using os.RDWR I couldn't even read the file. Could anyone explain it to me the reason why it would lead to this issue? I have got the error sftp: "Permission denied" (SSH_FX_PERMISSION_DENIED)
I have tried to see the permission code of the file, the file is -rwxrwxrwx.
import (github.com/pkg/sftp)
config = sftp.NewConfig(nil)
config.SetAcct("xxxxx","xxxxx")
config.SetDes("ip address", 1234)
config.Connect()
if file, err = config.Client.OpenFile(path, os.O_RDWR); err != nil {
log.Println("Cannot open "+path+" , err:", err)
}
if _, err = ioutil.ReadAll(file); err != nil {
log.Println("Cannot read "+path+", err:", err)
}
file.Close()
err = config.Client.Remove(file)
if err != nil {
log.Println("cannot remove file)
}
Problem solved:
found out that I had opened the file without closing it. And somehow the file is still opened by FreeSSHDService. That's why I could not remove the file.

You have to provide the file path instead you have provided file handler.
config.Client.Remove(pathTofile)
defer file.close()
Here is the reference https://godoc.org/github.com/pkg/sftp#Client.Remove

Related

check file existence without using os.Stat after locking the path

When I lock a file path with flock then check the file existence it return no error even though there is no file in that path. The code follows:
filePath := filepath.Join(r.path, fmt.Sprintf("%s_event.json", eventId))
fileLock := flock.New(filePath)
fileLock.Lock()
defer fileLock.Close()
_, err = os.Stat(filePath)
if err != nil {
if os.IsNotExist(errs) {
return event, EventNotFound{}
}
return
}
But when at first check the Stat then lock the file it works. I need to check it before that. Every idea is welcome!

Read file from sftp

I use github.com/pkg/sftp for work with a sftp server in golang.
I want to download file from sftp server.
For that i need to get bytes of this file and copy it to a local file right?
First i get my file with a OpenFile function :
file, err := sc.OpenFile("/backup/" + serverid + "/" + f.Name())
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to open file: %v\n", err)
return err
}
myfiles, err := file.HERE()
os.WriteFile("/text.txt", myfiles, perm)
return nil
But after i need to get bytes of this file but how i can do that?
What should i enter instead of HERE?
Resolved with:
myfile, err := io.ReadAll(file)

Fprintf Error when writing to network mapped drive

I have the following piece of code which creates an output file on a local drive and required to do the same on a network mapped drive let's call it [H:].
The file name (full path name) entered from command line as argument[1].
I am using Windows 10/Server 2016
// The following will create and append to the file when required.
sourcefile, errf := os.OpenFile(os.Args[1], s.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
if erro != nil {
panic(erro)
}
defer outfile.Close()
I use the following function to write a map into this file.
func map2Linpro(inp map[string][]string, outfile io.Writer) {
for k, v := range inp {
_, err := fmt.Fprintf(outfile, "%s %s=%s %s\n", v[0], k, v[1], v[2])
if err != nil {
fmt.Println("Error Writing to File: ", err)
}
}
}
Everything is working just fine if the output file is on the local Drive, but when using full path with the Mapped Drive letter, I received the following error:
Error: write h://00_sc//dest01.txt: The parameter is incorrect.
I searched for any reason, but could not find one.
I would appreciate if someone help
The following is the Error I got after adding Panic(erro) after OpenFile.
Which proves that the error source is fmt.Fprintf
Error Writing to File: write H:/00_sc/dest01.txt: The parameter is incorrect.
Thanks to all.
outfile, _ := os.OpenFile(os.Args[2], os.O_CREATE|os.O_APPEND, 0666)
should read
outfile, err := os.OpenFile(os.Args[2], os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
rewrite those lines and the resulting error message should give a clue as to the cause

How to write a file in specific data volume

I am trying to write in newly generated file in a specific attached volume to my container (a directory)
however i am not sure about the correct the syntax. Below my code:
// Write the certificates to disk
f, _ := os.Create(filepath.Join("/data/certs/", "chamscertificate.pem"))
f.Write(cert)
f.Close()
f, _ = os.Create("key.pem")
f.Write(key)
f.Close()
}
when executing "go run .", i get the "key.pem" but not the "certificate.pem".
You don't check for errors. If the file wasn't created, the information about why the file wasn't created will be in the error return value from os.Create.
f, err := os.Create(filepath.Join("/data/certs/", "chamscertificate.pem"))
if err != nil {
log.Fatal(err)
}
... etc.
Note that f.Write and f.Close also return errors that should be checked.

Golang bad file descriptor

I am getting a bad file descriptor when trying to append to a logging file within my go routine.
write ./log.log: bad file descriptor
The file exists and has 666 for permissions. At first I thought well maybe it is because each one of them is trying to open the file at the same time. I implemented a mutex to try and avoid that but got the same issue so I removed it.
logCh := make(chan string, 150)
go func() {
for {
msg, ok := <-logCh
if ok {
if f, err := os.OpenFile("./log.log", os.O_APPEND, os.ModeAppend); err != nil {
panic(err)
} else {
logTime := time.Now().Format(time.RFC3339)
if _, err := f.WriteString(logTime + " - " + msg); err != nil {
fmt.Print(err)
}
f.Close()
}
} else {
fmt.Print("Channel closed! \n")
break
}
}
}()
You need to add the O_WRONLY flag :
if f, err := os.OpenFile("./log.log", os.O_APPEND|os.O_WRONLY, os.ModeAppend); err != nil { /*[...]*/ }
To explain, here is the linux documentation for open: http://man7.org/linux/man-pages/man2/openat.2.html :
The argument flags must include one of the following access modes:
O_RDONLY, O_WRONLY, or O_RDWR. These request opening the file read-
only, write-only, or read/write, respectively.
If you check /usr/local/go/src/syscall/zerrors_linux_amd64.go:660, you can see that:
O_RDONLY = 0x0
O_RDWR = 0x2
O_WRONLY = 0x1
So by default you get a read-only file descriptor.
it used for me
the code before:
os.OpenFile(fileName, os.O_CREATE|os.O_APPEND, os.ModePerm)
and it occured the error: bad file descriptor,
then i add the os.O_WRONLY into the function
the code after:
os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
and it did't occured the problem.
This appears to be a discrepancy between windows and linux.
On windows os.O_APPEND implies write access, as can be seen in the code in syscall_windows.go.
if mode&O_APPEND != 0 {
access &^= GENERIC_WRITE
access |= FILE_APPEND_DATA
}
in linux the openflags are passed as-is to a linux syscall
So in DOS/WINDOWS you do not need to explicitly add a write flag with an append flag, as it is implied. (this has been default behaviour since the DOS days)
Go in linux does need the extra flag added to work.
(...but imo it should not need this flag, as appending implicitly implies that I want to write. Should I bugreport this to golang ?)

Resources