snprintf function not declared? - c

I'm trying to use the snprintf function which based on the manual I've read is apart of the <stdio.h> header however I'm getting an error that it's been implicitly declared. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct users {
char* user_id;
};
typedef struct users users_t;
int save_user_detail(user_t);
int main() {
users_t users;
save_user_detail(users);
return 0;
}
int save_user_detail(users_t users)
{
printf("Type the filename = ");
scanf("%s", users.user_id);
char* extension = ".txt";
char fileSpec[strlen(users.user_id)+strlen(extension)+1];
FILE *file;
snprintf(fileSpec, sizeof(fileSpec), "%s%s", users.user_id, extension);
file = fopen(fileSpec, "w");
if(file==NULL)
{
printf("Error: can't open file.\n");
return 1;
}
else
{
printf("File written successfully.\n");
fprintf(file, "WORKS!\r\n");
}
fclose(file);
return 0;
}

You seem to be using gcc, but this compiler does not necessarily use the glibc, which is compliant with the C Standard and supports snprintf.
On the Windows architecture, you may be using the Microsoft C library, which in older versions did not have snprintf or renamed it as _snprintf.
Here are 2 ways you can try a work around your problem:
try using _snprintf instead of snprintf.
define snprintf manually after including <stdio.h> as
int snprintf(char *buf, size_t size, const char *fmt, ...);
The compiler should stop complaining about the missing prototype and if the runtime library does have a symbol for snprintf with a matching calling convention, it will link to it and the program should behave as expected.

Related

Why Dll can't export a function with parameter type FILE*

THis is the Dll code
#ifdef HELLO_EXPORTS
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
CLASS_DECLSPEC FILE* GetStdout() {
return stdout;
}
CLASS_DECLSPEC void dump_code(FILE* fd, const void* data, size_t len)
{
unsigned char* p = (unsigned char*)data;
size_t i;
for(i = 1; i < len + 1; ++i){
fprintf(fd, "0x%.2x, ", p[i-1]);
if((i%16)==0) fprintf(fd, "\n");
}
fprintf(fd, "\n");
}
This is the test code:
#include <stdio.h>
#include <stdlib.h>
#include "dump.h"
int main(){
char data[] = {
0x1f,0xc2,0x8b,0x08,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xc3,0x8d,0xc2,0x90,0x3d
};
dump_code(GetStdout(), data, 16);
//dump_code(stdout, data, 16);
}
If I directly use stdout: dump_code(stdout, data, 16);, the program will crash in _lock_file.
But it will ok to use GetStdout() instead of stdout.
Don't pass FILE * pointers between two copies of libc. You need to link the exe and the dll against the exact same version of libc as a dynamic link library or it won't work.
The general tradition on Windows is don't even try to make this kind of thing work. For every export that would return allocated memory there is another export to free that memory, and more complex things either aren't done at all or done using COM to provide cleanup routines.
OP has now commented that he built with /MTd, which decodes to multi-threaded, static library, and switching to /MDd, which decodes to multi-threaded dll-version-specific library (which is in a .dll) fixed the problem, as expected. When switching to release, /MD must be used instead of /MT or the same problem will reoccur.

Looking for ways to 'mock' posix functions in C/C++ code

I am trying to find somewhat elegant ways to mock and stub function calls to the standard C library functions.
While stubbing-off calls to C files of the project is easy by just linking other C files in the tests, stubbing the standard C functions is harder.
They are just there when linking.
Currently, my approach is to include the code-under-test from my test.cpp file, and placing defines like this:
#include <stdio.h>
#include <gtest/gtest.h>
#include "mymocks.h"
CMockFile MockFile;
#define open MockFile.open
#define close MockFile.close
#define read MockFile.read
#include "CodeUnderTestClass.cpp"
#undef open
#undef close
#undef read
// test-class here
This is cumbersome, and sometimes I run across code that uses 'open' as member names elsewhere or causes other collisions and issues with it. There are also cases of the code needing different defines and includes than the test-code.
So are there alternatives? Some link-time tricks or runtime tricks to override standard C functions? I thought about run-time hooking the functions but that might go too far as usually binary code is loaded read-only.
My unit-tests run only on Debian-Linux with gcc on amd64. So gcc, x64 or Linux specific tricks are also welcome.
I know that rewriting all the code-under-test to use an abstracted version of the C functions is an option, but that hint is not very useful for me.
Use library preloading to substitute system libraries with your own.
Consider following test program code, mytest.c:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(void) {
char buf[256];
int fd = open("file", O_RDONLY);
if (fd >= 0) {
printf("fd == %d\n", fd);
int r = read(fd, buf, sizeof(buf));
write(0, buf, r);
close(fd);
} else {
printf("can't open file\n");
}
return 0;
}
It will open a file called file from the current directory, print it's descriptor number (usually 3), read its content and then print it on the standard output (descriptor 0).
Now here is your test library code, mock.c:
#include <string.h>
#include <unistd.h>
int open(const char *pathname, int flags) {
return 100;
}
int close(int fd) {
return 0;
}
ssize_t read(int fd, void *buf, size_t count) {
strcpy(buf, "TEST!\n");
return 7;
}
Compile it to a shared library called mock.so:
$ gcc -shared -fpic -o mock.so mock.c
If you compiled mytest.c to the mytest binary, run it with following command:
$ LD_PRELOAD=./mock.so ./mytest
You should see the output:
fd == 100
TEST!
Functions defined in mock.c were preloaded and used as a first match during the dynamic linking process, hence executing your code, and not the code from the system libraries.
Update:
If you want to use "original" functions, you should extract them "by hand" from the proper shared library, using dlopen, dlmap and dlclose functions. Because I don't want to clutter previous example, here's the new one, the same as previous mock.c plus dynamic symbol loading stuff:
#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <gnu/lib-names.h>
// this declares this function to run before main()
static void startup(void) __attribute__ ((constructor));
// this declares this function to run after main()
static void cleanup(void) __attribute__ ((destructor));
static void *sDlHandler = NULL;
ssize_t (*real_write)(int fd, const void *buf, size_t count) = NULL;
void startup(void) {
char *vError;
sDlHandler = dlopen(LIBC_SO, RTLD_LAZY);
if (sDlHandler == NULL) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
real_write = (ssize_t (*)(int, const void *, size_t))dlsym(sDlHandler, "write");
vError = dlerror();
if (vError != NULL) {
fprintf(stderr, "%s\n", vError);
exit(EXIT_FAILURE);
}
}
void cleanup(void) {
dlclose(sDlHandler);
}
int open(const char *pathname, int flags) {
return 100;
}
int close(int fd) {
return 0;
}
ssize_t read(int fd, void *buf, size_t count) {
strcpy(buf, "TEST!\n");
return 7;
}
ssize_t write(int fd, const void *buf, size_t count) {
if (fd == 0) {
real_write(fd, "mock: ", 6);
}
real_write(fd, buf, count);
return count;
}
Compile it with:
$ gcc -shared -fpic -o mock.so mock.c -ldl
Note the -ldl at the end of the command.
So: startup function will run before main (so you don't need to put any initialization code in your original program) and initialize real_write to be the original write function. cleanup function will run after main, so you don't need to add any "cleaning" code at the end of main function either.
All the rest works exactly the same as in the previous example, with the exception of newly implemented write function. For almost all the descriptors it will work as the original, and for file descriptor 0 it will write some extra data before the original content. In that case the output of the program will be:
$ LD_PRELOAD=./mock.so ./mytest
fd == 100
mock: TEST!

How can I create a directory and make a file in %appdata% path of windows in C language

I successfully created a directory or folder and I also managed to create a file in that directory but how can create a directory and a file in the user's appdata local if I don't know what is their username or their user folder name? thanks!
I used codeblocks
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
int check;
char* dirname = "C:/Pyromagne";
check = mkdir(dirname);
FILE* fp;
fp = fopen("C:/Pyromagne/test.pyr", "w+");
fputs("Pyromagne\n", fp);
fputs("qwertyuiop", fp);
fclose(fp);
FILE* ffpp;
char user[25];
char pass[25];
char uuser[25];
ffpp = fopen("C:/Pyromagne/test.pyr", "r");
strcpy(uuser, fgets(user, 255, (FILE*)ffpp));
printf("%s\n", uuser);
strcpy(uuser, fgets(user, 255, (FILE*)ffpp));
printf("%s\n", uuser);
fclose(ffpp);
}
Under MSYS2/UCRT, I recently (like yesterday...) used SHGetFolderPathA() to obtain a user's profile directory in C code.
It's worked so far in limited unit testing on a Windows Server 2016 AWS installation after being compiled with whatever GCC version comes with the latest MSYS2/UCRT installation. (The system is currently shut down and I'm on vacation so i can't check details)
This might work in your environment:
char buffer[ MAX_PATH ] = { 0 };
HRESULT result = SHGetFolderPathA( NULL, CSIDL_APPDATA, NULL, 0, buffer );
if ( result != S_OK )
{
//handle error
}
Somewhat off-topic, I have grown to prefer MSYS2/UCRT over the alternatives.
SHGetKnownFolderPath obtains the Unicode path to AppData, Documents, etc.
KNOWNFOLDERID for "C:\Users\MyName\AppData\Local" is FOLDERID_LocalAppData
This function needs additional libraries for CoTaskMemFree, KNOWNFOLDERID, and SHGetKnownFolderPath
gcc file.c libole32.a libuuid.a libshell32.a
Using MinGW, 64-bit, gcc version 4.8.3, SHGetKnownFolderPath does not appear to be in libshell32.a. The command line nm libshell32.a does not list this function either. So in MinGW, we have to load this function manually as follows:
#define _WIN32_WINNT 0x0600
#include <stdio.h>
#include <Windows.h>
#include <shlobj.h>
//add libraries for libole32.a and libuuid.a
HRESULT MySHGetKnownFolderPath
(const KNOWNFOLDERID* const id, DWORD flags, HANDLE token, PWSTR* str)
{
typedef HRESULT(WINAPI* lpf)(const KNOWNFOLDERID* const, DWORD, HANDLE, PWSTR*);
HMODULE lib = LoadLibraryW(L"shell32.dll");
if (!lib) return E_FAIL;
lpf fnc = (lpf)GetProcAddress(lib, "SHGetKnownFolderPath");
HRESULT result = fnc ? fnc(id, flags, token, str) : E_FAIL;
FreeLibrary(lib);
return result;
}
int main(void)
{
wchar_t* temp;
if SUCCEEDED(MySHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &temp))
{
wchar_t path[1024];
swprintf(path, 1024, L"%s\\_add_new_dir", temp);
CoTaskMemFree(temp); //free this memory as soon as possible
wprintf(L"path: %s\n", path); //CreateDirectoryW(path, NULL);
}
return 0;
}
Additionally, you can use getenv or _wgetenv (Unicode version)
#include <stdio.h>
#include <Windows.h>
int main(void)
{
wprintf(L"%s\n", _wgetenv(L"LOCALAPPDATA"));
wprintf(L"%s\n", _wgetenv(L"APPDATA"));
wprintf(L"%s\n", _wgetenv(L"USERPROFILE"));
wchar_t buf[1024];
swprintf(buf, 1024, L"%s\\_add_new_dir", _wgetenv(L"LOCALAPPDATA"));
wprintf(L"buf: %s\n", buf); //CreateDirectoryW(buf, NULL);
return 0;
}
To add the libraries in Code::Blocks, click Menu -> Settings -> Compiler, it should bring up this window:
Then click the "Add" button, find MinGW installation folder, the libraries should be at
C:\My_MinGW_folder\mingw\lib\libole32.a
or
C:\My_MinGW_folder\mingw\lib32\libole32.a (for 32-bit program)
You can figure out which libraries you need by looking at documentation for the function. For example SHGetKnownFolderPath says it needs "shell32.lib" (for Visual Studio) MinGW uses "libshell32.a" instead.

unable to compile program due to function asprintf

Found this code, it needed to stop throttling the CPU to 20% in Dell laptops, which occurs due to the power adapter failing to be recognized by the computer.
Tried to compile on Kubuntu and got this:
warning: implicit declaration of function ‘asprintf’; did you mean ‘vasprintf’? [-Wimplicit-function-declaration]
47 | if (asprintf(&concat_cmd, "%s %i", cmd, *reg_value) == -1)
| ^~~~~~~~
| vasprintf
I don’t understand why it is happening. I read that asprintf is part of the libiberty-dev. The library is installed but everything does not work. Also I added
#include <libiberty/libiberty.h>
and got the same - implicit declaration of function ‘asprintf’
tell me what to do with it?
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <libiberty/libiberty.h>
#define BUFSIZE (64)
int get_msr_value(uint64_t *reg_value) {
const char *cmd = "rdmsr -u 0x1FC";
char cmd_buf[BUFSIZE];
FILE *fp;
if ((fp = popen(cmd, "r")) == NULL) {
printf("Error opening pipe!\n");
return -1;
}
cmd_buf[strcspn(fgets(cmd_buf, BUFSIZE, fp), "\n")] = 0;
*reg_value = atoi(cmd_buf);
if (pclose(fp)) {
printf("Command not found or exited with error status\n");
return -1;
}
return 0;
}
int main(void) {
const char *cmd = "wrmsr -a 0x1FC";
char *concat_cmd;
int ret;
uint64_t *reg_value = &(uint64_t){ 0 };
if ((ret = get_msr_value(reg_value))) {
return ret;
}
printf("Old register value: %lu\n", *reg_value);
*reg_value = *reg_value & 0xFFFFFFFE; // clear bit 0
printf("New register value: %lu\n", *reg_value);
if (asprintf(&concat_cmd, "%s %i", cmd, *reg_value) == -1)
return -1;
printf("Executing: %s\n", concat_cmd);
system(concat_cmd);
free(concat_cmd);
return 0;
}
asprintf is part of stdio.h, but you need to add #define _GNU_SOURCE at the top of your file and use -std=gnu99 when compiling.
The function asprintf() is not yet part of the C Standard. It is available in the GNU libc and most likely supported on your system since it uses this C library, with a declaration in <stdio.h>.
You might need to define __GNU_SOURCE or __USE_GNU before including <stdio.h> for this declaration to be parsed by the compiler. Run man asprintf to see which feature macro to use or look inside the file /usr/include/stdio.h on your system.
Either modify the source code or add a -D__GNU_SOURCE command line argument in your CFLAGS in the Makefile.

Conflicting types for 'sleep'

Why do I keep getting the error message "Conflicting types for 'sleep'" when I try running my program?
#include <stdio.h>
#include <stdlib.h>
void congratulateStudent (char *student, char *course, int numDays)
{
printf("%s has done as much %s Programming as I could fit into %d days. \n", student, course, numDays);
}
int main(int argc, const char * argv[])
{
congratulateStudent("Mark", "Cocoa", 5);
sleep(2);
congratulateStudent("Bo", "Objective-C", 2);
sleep(2);
congratulateStudent("Mike", "Python", 5);
sleep(2);
congratulateStudent("Ted", "iOS", 5);
return 0;
}
Every library function has a corresponding header file that declares the function. For the sleep function, that header file is unistd.h. The documentation for each function tells you which header file to use.
If you don't include the correct header file, then the compiler will complain bitterly. Don't make the compiler unhappy, always include the correct header file.

Resources