GoLang os.Chdir() permission denied - file

I am writing a program that creates a directory and then changes the working directory to the newly created directorty in order to do some work:
func main() {
err := os.Mkdir("English", 0777) // I know 777 is not good practice, first I want to get Chdir() working
if err != nil && !os.IsExist(err) {
log.Fatal(err)
}
err = os.Chdir("English")
if err != nil {
log.Fatal(err)
}
}
Console output:
023/02/05 18:15:45 chdir English: permission denied
exit status 1

Simple fix: executing the program using sudo resulted in the directoy being created with permissions as specified.

Related

Why does writing to a deleted file not return an error in Go?

This program successfully runs even though it's writing to a deleted file. Why does this work?
package main
import (
"fmt"
"os"
)
func main() {
const path = "test.txt"
f, err := os.Create(path) // Create file
if err != nil {
panic(err)
}
err = os.Remove(path) // Delete file
if err != nil {
panic(err)
}
_, err = f.WriteString("test") // Write to deleted file
if err != nil {
panic(err)
}
err = f.Close()
if err != nil {
panic(err)
}
fmt.Printf("No errors occurred") // test.txt doesn't exist anymore
}
On Unix-like systems, when a process opens a file it gets a File descriptor which points to the process File table entry, which, in turn, refers to inode structure on the disk. inode keeps file information, including data location.
Contents of a directory are just pairs of inode numbers and names.
If you delete a file, you simply delete a link to inode from the directory, inode still exists (as long as there is no link to it from somewhere, including processes) and data can be read and written from/to data location.
On Windows this code fails since Windows does not allow opened file to be deleted:
panic: remove test.txt: The process cannot access the file because it is being used by another process.
goroutine 1 [running]:
main.main()
D:/tmp/main.go:18 +0x1d1
exit status 2

How to fix : Sql logic error sqlite3 in Clion?

I'm trying to link sqlite3 library to CMakeList in Clion using the following code:
find_package(SQLite3)
target_link_libraries(IIWProject SQLite::SQLite3)
Library has been loaded but when i Run the code, Clion shows the following error:
SQL logic error
The database has been loaded but when sqlite3_prepare_v2(db, query, -1, &stmt, NULL) was called return SQL logic error
void get_db(sqlite3 **db){
int rc;
if ((rc = sqlite3_open("db_project.db", db)) != SQLITE_OK){
//fprintf(stderr, "Failed to open DB.\n");
fprintf(stderr,"Failed to open DB: %s\n\r", sqlite3_errstr(rc));
exit(EXIT_FAILURE);
}
}
int clear_table(sqlite3 *db){
sqlite3_stmt *stmt;
int rc;
char* query = "DELETE FROM resources";
if ((rc=sqlite3_prepare_v2(db, query, -1, &stmt, NULL)) != SQLITE_OK){
fprintf(stderr,"Failed to prepare statement: %s\n\r", sqlite3_errstr(rc));
return 1;
}
if ((rc = sqlite3_step(stmt)) != SQLITE_DONE){
fprintf(stderr,"Delete failed: %s\n\r", sqlite3_errstr(rc));
return 1;
}
return 0;
}
How can I try to fix it?
EDIT:
If I compile, without Clion manually, with gcc -lsqlite3,it work
Now that we've established that the table doesn't exist when you run your program though your IDE...
The current working directory when you run your program through a command line is different than the current working directory your IDE runs it in. Since you're using a relative path to the database file, this means you're using a different one depending on how you run your program. Only one of the databases actually has the table(s) you're trying to use.
Some solutions:
Use an absolute path to the database.
Configure your IDE to use the same working directory as when you're running your program through a command line.

Get file size given file descriptor in Go

If given a path, I would use this to get file size
file, _ := os.Open(path)
fi, _ := file.Stat()
fsuze := fi.Size()
But if only given fd, how can I get the file size?
Is there any way in Go like this in C:
lseek(fd, 0, SEEK_END)
You create a new *os.File from a file descriptor using the os.NewFile function.
You can do it exactly the same way as in C, using Seek
offset, err := f.Seek(0, os.SEEK_END)
But since you have the *os.File already, you can call Stat even if it was derived directly from the file descriptor.
try to get the file start
fileInfo, err := file.Stat()
if err != nil {...
}
files fileInfo.Size())

How to use the pulseaudio API as root?

I am currently trying to use the pulseaudio simple API to record microphone data from my USB sound card with my raspberry pi 3. I used the example program parec-simple from pulseaudio in my own program and it works quite nice.
The program i used this code for is accessing gpio's so i need to run this as root. However, when i try to execute the program as root, i get the following errors:
Home directory not accessible: Permission denied
W: [pulseaudio] core-util.c: Failed to open configuration file '/root/.config/pulse//daemon.conf': Permission denied
W: [pulseaudio] daemon-conf.c: Failed to open configuration file: Permission denied
pa_simple_new() failed: Connection refused
the code is used is the following:
static const pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 1
};
pa_simple *s = NULL;
int ret = 1;
int error;
/* Create the recording stream */
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
fprintf(stderr, "pa_simple_new() failed: %s\n", pa_strerror(error));
goto finish;
}
while(1)
{
uint8_t buf[BUFSIZE];
/* Record some data ... */
if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) {
fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
goto finish;
}
/* And write it to STDOUT */
if (loop_write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) {
fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno));
goto finish;
}
}
ret = 0;
finish:
if (s)
pa_simple_free(s);
return ret;
I already tried chown pi:pi /home/pi as suggested here to try to fix it but it doesn't work. changing the owner of /home/pi from pi to root didn't work for me either.
I also tried a clean reinstall of pulseaudio but unfortunately it didn't fix it.
So what can i do to fix these errors?
If you need to run your program as user root, then you must impersonate root. I don't know if pulseaudio looks at the username in order to find configuration files, or it looks at the $HOME variable. In the second case, maybe that by setting HOME to the home of a "working" user helps.
Anyway what you told about the situation is clear: pulseaudio does not find a file:
'/root/.config/pulse//daemon.conf'
Place a correct "daemon.conf" in that directory - probably you can copy it from somewhere (like /home/auser/.config/pulse/daemon.conf).
Consider that directories with name starting with a dot are normally hidden; if using a file manager you must enable "show hidden files", if you use the shell, ls -a can help.
Your first target is to confirm that the file is there, and your program should not complain about a missing/unreadable config file. Then, maybe other errors will show up but, one after another, you can eliminate them.
When you run process with sudo it does not change Home directory to /root - sudo echo $HOME # /home/username. You need to specify HOME directory with by running sudo HOME=/root executable.
When you want to access pulseaudio from root you need to run it system wide with command - sudo pulseaudio --system=true.
Then you will receive an error from pulseaudio:
W: [pulseaudio] protocol-native.c: Denied access to client with invalid authentication data.
Which can be solved by adding root user to audio-pulse group - sudo adduser root pulse-access.

Reading the first two bytes from a file efficiently - Golang

I'm trying to find a good way of reading the first two bytes from a file using Go.
I have some .zip files in my current directory, mixed in with other files.
I would like to loop through all the files in the directory and check if the first two bytes contain the right .zip identifier, namely 50 4B.
What would be a good way to accomplish this using the standard library without having to read the entire file?
Going through the available functions in the io package I managed to find:
func LimitReader(r Reader, n int64) Reader
Which seems to fit my description, it reads from Reader (How do I get a Reader?) but stops after n bytes. Since I'm rather new to Go, I'm not sure how to go about it.
You get the initial reader by opening the file. For 2 bytes, I wouldn't use the LimitReader though. Just reading 2 bytes with io.ReadFull is easier.
r, err := os.Open(file)
if err != nil {
return err
}
defer r.Close()
var header [2]byte
n, err := io.ReadFull(r, header[:])
if err != nil {
return err
}

Resources