Reputation:
I have a little bit of C code for getting the realpath that seems to work:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
char* getrpath(char *symlink) {
char *symlinkpath = symlink;
char actualpath [PATH_MAX];
symlink = realpath(symlinkpath, actualpath);
return symlink;
}
int main(int argc, char *argv[]) {
char *symlinkpath = argv[0];
symlinkpath = getrpath(symlinkpath);
printf("%s\n", symlinkpath);
return 0;
}
I am attempting to create a wrapper for it (for learning purposes only):
package main
/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
char* getrpath(char *symlink) {
char *symlinkpath = symlink;
char actualpath [PATH_MAX];
symlink = realpath(symlinkpath, actualpath);
return symlink;
}
*/
import "C"
import (
"fmt"
"os"
"path"
"unsafe"
)
func getArgv() string {
return fmt.Sprintf("./%s", path.Base(os.Args[0]))
}
func main() {
slink := C.CString(getArgv())
defer C.free(unsafe.Pointer(slink))
ret := C.getrpath(slink)
fmt.Println(C.GoString(ret))
}
I am unable to get the the value back into the main() Golang function. If I place a print in the C getrpath() function, it prints the path. Any tips are greatly appreciated.
Upvotes: 1
Views: 235
Reputation:
Okay ended up getting it but had to call C.realpath directly:
package main
/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
*/
import "C"
import (
"fmt"
"unsafe"
)
func currentDir() []byte {
return []byte{0x2e, 0x2f}
}
func rpath() string {
relativePath := currentDir()
limit := make([]byte, C.PATH_MAX)
slink := make([]byte, len(relativePath)+1)
copy(slink, relativePath)
C.realpath(
(*C.char)(unsafe.Pointer(&slink[0])),
(*C.char)(unsafe.Pointer(&limit[0])))
return C.GoString((*C.char)(unsafe.Pointer(&limit[0])))
}
func main() {
fmt.Println(rpath())
}
Also I am not checking to see if it returns anything... might be better to check if actually using this.
Upvotes: 0
Reputation: 58349
The problem is that your C function is returning memory allocated on the C stack, which is undefined behavior in C (and likely to result in garbage values in practice):
char* getrpath(char *symlink) {
char *symlinkpath = symlink;
char actualpath [PATH_MAX];
symlink = realpath(symlinkpath, actualpath);
return symlink;
}
You need to return heap-allocated memory instead. Like this:
char* getrpath(char *symlink) {
char *actualpath = malloc(PATH_MAX);
return realpath(symlink, actualpath);
}
Or more simply -- because getpath
is defined to malloc
memory itself if you pass in NULL for the second argument:
char *getrpath(char *symlink) {
return realpath(symlink, 0);
}
(I also removed the variable you introduced, but that's not the important part of the edit).
Upvotes: 1