The manpage for copy_file_range() at
https://man7.org/linux/man-pages/man2/copy_file_range.2.html
says:
#define _GNU_SOURCE
#include <unistd.h>
ssize_t copy_file_range(
(...)
The copy_file_range() system call first appeared in Linux 4.5
but when I try to compile the user sample code that contains the above, I get
warning: implicit declaration of function ‘copy_file_range’(...)
In function ‘main':
(...)undefined reference to ‘copy_file_range'
and I have Linux 4.15 :
$uname -r
4.15.0-142-generic
NOTE: I don't want to use any user-mode version which may or may not be present in glibc. I want to use the kernel version which should be available according to the manpage and also to all the Googling I could find. I want to know why is it not available - is the documentation completely wrong? Is it missing some crucial requirement for compilation? Am I completely not understanding something basic?
Full data which I think is irrelevant:
Full sample code foobar.c from the documentation:
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
int fd_in, fd_out;
struct stat stat;
off64_t len, ret;
if (argc != 3) {
fprintf(stderr, "Usage: %s <source> <destination>\n", argv[0]);
exit(EXIT_FAILURE);
}
fd_in = open(argv[1], O_RDONLY);
if (fd_in == -1) {
perror("open (argv[1])");
exit(EXIT_FAILURE);
}
if (fstat(fd_in, &stat) == -1) {
perror("fstat");
exit(EXIT_FAILURE);
}
len = stat.st_size;
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd_out == -1) {
perror("open (argv[2])");
exit(EXIT_FAILURE);
}
do {
ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
if (ret == -1) {
perror("copy_file_range");
exit(EXIT_FAILURE);
}
len -= ret;
} while (len > 0 && ret > 0);
close(fd_in);
close(fd_out);
exit(EXIT_SUCCESS);
}
Full errors:
$ gcc foobar.c
foobar.c: In function ‘main’:
foobar.c:40:19: warning: implicit declaration of function ‘copy_file_range’; did you mean ‘sync_file_range’? [-Wimplicit-function-declaration]
40 | ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
| ^~~~~~~~~~~~~~~
| sync_file_range
/tmp/ccfnzueg.o: In function `main':
foobar.c:(.text+0x127): undefined reference to `copy_file_range'
collect2: error: ld returned 1 exit status
my vm system is ubuntu 16.04, and i have download the kernel header files,i have write the code,but don't know how to edit gcc code or Makefile
#include <linux/netdevice.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(){
struct net_device *dev = dev_base;
struct in_device *mydevice;
struct in_ifaddr *myifaddr;
while( dev != NULL ){
printf("dev name: %s\n", dev->name);
mydevice = dev->ip_ptr;
myifaddr = mydevice->ifa_list;
while(myifaddr != NULL){
printf("ip: %s\n", inet_ntoa((struct in_addr)(myifaddr->ifa_local)));
myifaddr = myifaddr->ifa_next;
}
dev = dev->next;
}
return 0;
}
if i use gcc test.c it will come out some error like this
yq#ubuntu:~/test$ gcc test.c
In file included from /usr/include/linux/netdevice.h:28:0,
from test.c:1:
/usr/include/linux/if.h:234:19: error: field ‘ifru_addr’ has incomplete type
struct sockaddr ifru_addr;
^
......
test.c: In function ‘main’:
test.c:8:27: error: ‘dev_base’ undeclared (first use in this function)
struct net_device *dev = dev_base;
On a regular ubuntu machine, the following test succeeds unless I run it in my home directory, in which case it crashes with a bus error. All I can think of is that it's because the home directory is encrypted. (I find Private and .ecryptfs links there.)
// Make with g++ -mcmodel=large -fPIC -g -O0 -o checkmm checkmm.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#define TALLIES "tallies.bin"
#define NUM_TALLIES (550588000/sizeof(int))
typedef struct { int tallies[NUM_TALLIES]; } World;
World* world;
void loadWorld() {
int fd = open(TALLIES, O_RDWR | O_CREAT);
if (fd == -1) { printf("Can't open tallies file %s\n", TALLIES); exit(0); }
fallocate(fd, 0, 0, sizeof(World));
world = (World*) mmap(0, sizeof(World), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (world ==(World*) -1) { printf("Failed to map tallies file %s\n", TALLIES); exit(1); }
}
void unloadWorld() { munmap(world, sizeof(World)); }
void resetWorld() {
int i;
for (i=0;i<NUM_TALLIES;i++) world->tallies[i]=-1;
}
int main() {
loadWorld();
resetWorld();
unloadWorld();
}
Can anyone elucidate?
You should check the return codes for each system call. Particularly fallocate() and mmap().
fallocate() is supported on a handful of filesystems. You should use ftruncate() if fallocate() fails (with errno set to EOPNOTSUPP).
This is my first post and I am trying to adhere to the forum rules.
I know this question has been asked a number of times before, but the provided solutions do not work for me. I am not quite sure why this is so, probably I have overlooked something.
I want to access from a shared module (.so) symbols (variables and functions) which reside inside the main application.
I am always getting link errors ("undefined reference").
The scenario is similar as described here, with the one expection that I am using plain C instead of C++:
shared object can't find symbols in main binary, C++
Maybe this difference is the reason for that the proposed solution does not work.
I am using 32bit MinGW, version 4.6.2 under 32bit Windows (XP if that matters).
I also read these posts:
Receive "undefined symbol" error when loading library with dlopen
Dynamic loading and symbols sharing
Can I access to symbols of the host proccess from a shared object loaded in runtime? Any alternative?
The latter solution would work, I suppose, but is not an option because this is a porting project from Linux with 100+ symbols. It is a plugin system and I do not want to limit the possibilities avalable for the plugins.
I tried a number of commandline switches when linking the main application, such as -rdynamic (is apparently not supported in MinGW), --export-all-symbols, --export-dynamic.
I also tried different commandline options when linking the shared library, such as --allow-shlib-undefined, --enable-auto-import, --enable-runtime-pseudo-reloc
The application is a linux application and works well there; I managed it to make it work under Mac OSX (Darwin) as well. There I must not strip the main application executable during linking and specify "-bundle -bundle_loader 'app name'" when linking the shared objects.
Many thanks in advance!
Johannes
Well, I found out myself with some help of the codeguru forum (see http://forums.codeguru.com/showthread.php?536343-RESOLVED-accessing-symbols-in-appllication-from-within-dynamic-library-MinGW ).
The solution is not - as I was thinking first - some option to the linker; apparently automatic back-linking is not possible in Windows. You have to manully load the symbols you want to use from the main application at runtime; similiar to when you manually load a DLL.
I made a small test and demonstration project:
file "my_app.c":
#include <stdio.h>
#include <stdlib.h>
#include "my_app.h"
#include "plugins.h"
int a;
int b;
Plugin *P;
void hello ()
{
printf ("Hello World!\n");
}
int main ()
{
char choice;
char buf[BUFLEN];
char *plugin_name=NULL;
Plugin *p=NULL;
do
{
printf ("\n --- Menu items ---\n");
printf (" '1' .. select plugin\n");
printf (" '2' .. load plugin\n");
printf (" '3' .. execute plugin function\n");
printf (" '4' .. unload plugin\n");
printf (" 'x' .. exit\n");
printf ("\n Your choice: ");
fgets (buf, sizeof(buf), stdin);
putchar ('\n');
choice = buf[0];
switch (choice)
{
case '1':
plugin_name = plugin_select ();
break;
case '2':
if (plugin_name)
{
p = plugin_load (plugin_name);
if (p)
printf ("Plugin '%s' loaded successfully\n", plugin_name);
P = p;
} else
printf ("No plugin selected\n");
break;
case '3':
if (p)
{
printf ("Enter the 1st number: ");
fgets (buf, sizeof(buf), stdin);
a = atoi (buf);
printf ("Enter the 2nd number: ");
fgets (buf, sizeof(buf), stdin);
b = atoi (buf);
printf ("\nExecuting the plugin '%s' ...\n", plugin_name);
plugin_action (p);
} else
printf ("No plugin loaded\n");
break;
case '4':
if (p)
{
plugin_destroy (p);
p = NULL;
P = NULL;
} else
printf ("No plugin loaded\n");
break;
}
} while (choice != 'x');
return 0;
}
file "my_app.h":
#ifndef __MYAPP_H
#define __MYAPP_H
#include "plugins.h"
#define TRUE 1
#define FALSE 0
#define BUFLEN 120
extern int a;
extern int b;
extern void hello (void);
extern Plugin *P;
#endif /* __MYAPP_H */
file "plugins.c":
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <dlfcn.h>
#include "my_app.h"
#include "plugins.h"
Plugin *plugin_load (const char *filename)
{
Plugin *p;
int (*init)(Plugin *);
p = malloc (sizeof(Plugin));
if (p == NULL)
{
printf ("Couldn't allocate Plugin object\n");
return NULL;
}
strncpy (p->filename, filename, sizeof(p->filename));
if ((p->module = dlopen(p->filename, RTLD_LAZY)) == NULL)
{
printf ("%s\n", dlerror());
free (p);
return NULL;
}
init = dlsym (p->module, "init_plugin");
if (init == NULL)
{
printf ("%s\n", dlerror());
free (p);
return NULL;
}
if (!init(p))
{
perror ("Couldn't initialize plugin");
free (p);
return NULL;
}
p->load = TRUE;
return p;
}
void plugin_action (Plugin *p)
{
if (p == NULL)
{
printf ("Plugin not found!\n");
return;
}
p->plugin_cb();
}
char *plugin_select ()
{
DIR *dp;
struct dirent *e;
static char buf[BUFLEN];
char *p;
size_t len;
char *suffix;
dp = opendir (".");
if (dp == NULL)
{
perror ("Cannot open '.'");
return NULL;
}
printf ("\nFollowing plugins are available:\n");
while ((e=readdir(dp)) != NULL)
{
suffix = strrchr (e->d_name, '.');
if (suffix)
{
if (strcmp (suffix, PLUGIN_SUFFIX) == 0)
printf (" %s\n", e->d_name);
}
}
closedir (dp);
printf ("Your choice: ");
buf[0] = '.';
buf[1] = '/';
p = &buf[2];
fgets (p, sizeof(buf)-2, stdin);
len = strlen (buf);
if (len > 0)
len --;
buf[len] = '\0';
if (strchr(p, '.') == NULL)
strcat (buf, PLUGIN_SUFFIX);
return buf;
}
void plugin_destroy (Plugin *p)
{
void (*unload)(Plugin *);
unload = dlsym (p->module, "unload_plugin");
if (unload != NULL)
unload (p);
dlclose (p->module);
free (p);
}
file "plugins.h":
#ifndef __PLUGINS_H
#define __PLUGINS_H
#include <limits.h> /*PATH_MAX */
#define PLUGIN_SUFFIX ".so"
typedef struct _Plugin
{
char filename[PATH_MAX];
char *name;
char *description;
unsigned int show_in_menu;
unsigned int load;
void *module;
void (*plugin_cb)();
} Plugin;
Plugin *plugin_load (const char *filename);
void plugin_action (Plugin *p);
char *plugin_select (void);
void plugin_destroy (Plugin *p);
#endif /* __PLUGINS_H */
Now the plugins:
Hide the nasty function pointer declarations, etc.: "plugin_macros.h":
#ifndef __PLUGIN_MACROS_H
#define __PLUGIN_MACROS_H
#ifdef WIN32
#include <windows.h>
#define DECLARE_FUNC(type,name,par) typedef type (WINAPI *name ## _t)par; static name ## _t name;
#define DECLARE_VAR(type,name) static type * p ## name;
#define DECLARE_PTR(type,name) static type *name;
#define LOAD_FUNCC(name) if((name=(name ## _t)GetProcAddress(GetModuleHandle(NULL),#name))==NULL) return 0
#define LOAD_FUNC(name) (name=(name ## _t)GetProcAddress(GetModuleHandle(NULL),#name))
#define LOAD_VARC(type,name) if((p ## name=(type *)GetProcAddress(GetModuleHandle(NULL),#name))==NULL) return 0
#define LOAD_VAR(type,name) (name=(type *)GetProcAddress(GetModuleHandle(NULL),#name))
#define LOAD_PTRC(type,name) if((name=*(type **)GetProcAddress(GetModuleHandle(NULL),#name))==NULL) return 0
#define LOAD_PTR(type,name) (name=*(type **)GetProcAddress(GetModuleHandle(NULL),#name))
#else
/* not WIN32 */
#define DECLARE_FUNC(type,name,par)
#define DECLARE_VAR(type,name)
#define DECLARE_PTR(type,name)
#define LOAD_FUNCC(name)
#define LOAD_FUNC(name)
#define LOAD_VARC(type,name)
#define LOAD_VAR(type,name)
#define LOAD_PTRC(type,name)
#define LOAD_PTR(type,name)
#endif
#endif /* __PLUGIN_MACROS_H */
file "add.c":
#include <stdio.h>
#include "plugins.h"
#include "plugin_macros.h"
#ifdef WIN32
#include <windows.h>
DECLARE_FUNC(void, hello, (void));
DECLARE_VAR(int, a);
DECLARE_VAR(int, b);
DECLARE_PTR(Plugin, P);
#define a (*pa)
#define b (*pb)
#else
#include "my_app.h"
#endif
static void add ()
{
hello();
LOAD_PTR(Plugin, P);
printf ("name=%s\n", P->name);
printf ("description=%s\n\n", P->description);
printf ("%d + %d = %d\n", a, b, a+b);
}
int init_plugin (Plugin *p)
{
LOAD_FUNCC(hello);
LOAD_VARC(int, a);
LOAD_VARC(int, b);
p->name = "Add";
p->description = "Add two integers.";
p->plugin_cb = add;
P = p;
return TRUE;
}
file "multiply.c":
#include <stdio.h>
#include "plugins.h"
#include "plugin_macros.h"
#ifdef WIN32
#include <windows.h>
DECLARE_VAR(int, a);
DECLARE_VAR(int, b);
DECLARE_PTR(Plugin, P);
#define a (*pa)
#define b (*pb)
#else
#include "my_app.h"
#endif
static void multiply ()
{
LOAD_PTR(Plugin, P);
printf ("name=%s\n", P->name);
printf ("description=%s\n\n", P->description);
printf ("%d * %d = %d\n", a, b, a*b);
}
int init_plugin (Plugin *p)
{
LOAD_VARC(int, a);
LOAD_VARC(int, b);
p->name = "Multiply";
p->description = "Multiply two integers.";
p->plugin_cb = multiply;
P = p;
return TRUE;
}
... and the Makefile:
ifeq ($(OS), Windows_NT)
TARGET = plugintest.exe
CC = $(MINGW)\bin\gcc.exe
LDFLAGS = -Wl,--export-all-symbols
STRIP = -s
SHARED = -shared
RM = del
else
TARGET = plugintest
UNAME := $(shell uname -s)
ifeq ($(UNAME),Linux)
LDFLAGS = -Wl,--export-dynamic
STRIP = -s
SHARED = -shared
endif
ifeq ($(UNAME),Darwin)
LDFLAGS =
STRIP =
SHARED = -bundle -bundle_loader plugintest
endif
RM = rm -f
endif
PLUGINS = add.so multiply.so
OBJS = my_app.o plugins.o
LIBS = -ldl
CFLAGS = -Wall
all: $(TARGET) my_plugins
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(LIBS) $(LDFLAGS) -o $(TARGET)
my_app.o: my_app.c my_app.h plugins.h
$(CC) $(CFLAGS) -c my_app.c -o my_app.o
plugins.o: plugins.c my_app.h plugins.h
$(CC) $(CFLAGS) -c plugins.c -o plugins.o
my_plugins: $(PLUGINS)
add.so: add.c my_app.h plugin_macros.h
$(CC) $(CFLAGS) $(SHARED) add.c -o add.so
multiply.so: multiply.c my_app.h plugin_macros.h
$(CC) $(CFLAGS) $(SHARED) multiply.c -o multiply.so
clean:
$(RM) *.o *.so $(TARGET)
The project uses the posix dynamic loading functions dlopen(), etc. They are not part of the MinGW installation, but you can download from here:
http://code.google.com/p/dlfcn-win32/
I hope this helps others who come across the same issue.
Any comments and questions are welcome!
Johannes
Please have a look on this code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *process_fp = popen("make -f -", "w");
if (process_fp == NULL) {
printf("[ERR] make not found!\n");
} else {
char txt[1024] = "all:\n\t#echo Hello World!\n";
fwrite(txt, sizeof(char), strlen(txt), process_fp);
pclose(process_fp);
}
}
This program will print "Hello World!". It works on the Linux platform, but failed on Solaris, where it complains: make: *** fopen (temporary file): No such file or directory. Stop..
How can I solve this problem?
Try to run make -f - manually; it probably doesn't work on Solaris. Try gmake (for GNU make) instead.