Errors in header file with function taking structs - c

What's wrong with this header? Gcc throws out:
libmmbox.h:7:29: error: expected ‘)’ before ‘*’ token
libmmbox.h:8:27: error: expected ‘)’ before ‘*’ token
Here's my code:
#ifndef __LIBMMBOX_H__
#define __LIBMMBOX_H__
int mmbox_connect(char *username);
int mmbox_login(int token, char *password);
int mmbox_quit();
int mmbox_stat(mmbox_stat_t *result);
int mmbox_list(mmbox_mail **l, int *num_msg);
int mmbox_send(char *dest, char *obj, void *buf, size_t size);
int mmbox_rcv(int id, void *buf, size_t size);
int mmbox_delete(int id);
int mmbox_resume(int id);
typedef struct
{
char *user;
int used_space;
int free_space;
int num_msg;
} mmbox_stat_t;
typedef struct
{
char *sender, *recipient; /
char *obj, *date;
char flags;
size_t size;
} mmbox_mail;
#endif

mmbox_stat_t struct is declared after it is used into a function signature. So the compiler doesn't still know this type when you declare:
int mmbox_stat(mmbox_stat_t *result);
Put your function prototypes after data structures definition.

Related

Initialization from incompatible pointer type when assigning struct file_operations fields

I'm writing a Linux device drive and I'm confused as to why I'm getting this warning.
error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
.write = file_write,
This is my code that I created, when I use make command I get the above error. I tried changing ssize_t to int but still I get the same error.
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/random.h>
MODULE_LICENSE("NIKS");
static char msg[100]={0};
static short readPos =0;
static int file_open(struct inode * , struct file *);
static int file_release(struct inode * , struct file *);
static ssize_t file_read(struct file *, char *, size_t,loff_t * );
static ssize_t file_write(struct file *, char *, size_t,loff_t * );
static struct file_operations fo =
{
.read = file_read,
.open = file_open,
.write = file_write,
.release = file_release,
};
int init_module(void)
{
int t = register_chrdev(150,"encdev",&fo);
if(t<0)
{
printk("error");
}
else
{
printk("success");
}
return t;
}
void cleanup_module(void)
{
unregister_chrdev(150,"encdev");
}
static int file_open(struct inode *in , struct file *fil)
{
return 0;
}
static ssize_t file_read(struct file *fil, char *buf, size_t len,loff_t *off )
{
short count=0;
printk("here %d",msg[0]!=0);
while(len && (msg[readPos]!=0))
{
printk("read");
put_user(msg[readPos],buf++);
count++;
len--;
readPos++;
}
return count;
}
static ssize_t file_write(struct file *fil, char *buf, size_t len,loff_t *off )
{
short ind = 0;
short count =0;
memset(msg,0,100);
readPos = 0;
int i =0;
char bytes[16];
char rand;
while(i<16)
{
get_random_bytes(&rand, sizeof(rand));
bytes[i]=rand;
++count;
i++;
}
int _len = len+16;
while(_len>0 || count%16){
if(ind<16) msg[ind] = bytes[ind];
else{
msg[ind] = (_len>0?buf[ind-16]:'#')^msg[ind-16];
}
++ind;
--_len;
++count;
}
return count;
}
static int file_release(struct inode *in , struct file *fil)
{
printk("done");
return 0;
}
I'm new to C and I just can't work out why I'm getting this warning. Can anybody explain why I get this warning and what to do about it please?
The correct types for the read and write function pointers of struct file_operations are:
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
Therefore, in your module, the appropriate signatures are:
static ssize_t file_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t file_write(struct file *, const char __user *, size_t, loff_t *);
// ...
static ssize_t file_read(struct file *fil, char __user *buf, size_t len,loff_t *off)
{
// ...
static ssize_t file_write(struct file *fil, const char __user *buf, size_t len, loff_t *off)
{
The important part that was missing was the const qualifier, but it's also important to remember that any pointer passed from userspace should be marked with the __user annotation (even though the compiler will not warn you if you forget it, it's only meant to be used as a static check for Sparse).
You also have several declarations after other stataments, which is invalid in C90. The compiler will warn you about those, follow the warnings and move them to the top of the function body.

Getting an unexpected 'Symbol not found' error when trying to Base64 encode a string with LuaJIT FFI bindings to OpenSSL's BIO_f_base64()

I am trying to convert this example (found here) from the openssl documentation to work with LuaJIT's FFI. Scroll down for complete Lua code.
BIO *bio, *b64;
char message[] = "Hello World \n";
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_fp(stdout, BIO_NOCLOSE);
BIO_push(b64, bio);
BIO_write(b64, message, strlen(message));
BIO_flush(b64);
BIO_free_all(b64);
But when I get to this line in the code ssl.BIO_flush(b64)I am getting the error below (running this from the LuaJIT interpreter and not a file)
stdin:1: Symbol not found: BIO_flush
stack traceback:
[C]: in function '__index'
stdin:1: in main chunk
[C]: at 0x0ac2cdd2f176
I understand that there are many other ways to do base64 encoding and at this point I have switched to a pure Lua solution. I still would like to understand why I'm getting this error because in part I'm working on this project to learn more about the LuaJIT FFI interface and openssl is already a dependency for libcurl which I am already using (hitting various APIs with OAth and I want to keep my dependencies as lean as possible).
I have already been successful at using openssl's HMAC() authentication function (found here) from LuaJIT's FFI so through reading documentation and trial and error I am pretty familiar with LuaJIT's FFI interface. Lua code below. I had to navigate through MANY openssl header files to get to this ffi.cdef[[]] but seems like maybe I'm still missing something. Any help would be appreciated.
EDIT: Just to test if the BIO_flush() is somehow optional, I've also excluded that line and gone all the way through my code with no errors but then I check the output file and it is blank.
ffi = require "ffi"
ffi.cdef[[
typedef struct bio_method_st BIO_METHOD;
typedef struct bio_st BIO;
typedef void bio_info_cb(BIO *, int, const char *, int, long, long);
struct crypto_ex_data_st { struct stack_st_void *sk; };
typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
typedef void CRYPTO_RWLOCK;
typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,long argl, long ret);
typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,size_t len, int argi,long argl, int ret, size_t *processed);
struct bio_st { const BIO_METHOD *method; BIO_callback_fn callback; BIO_callback_fn_ex callback_ex; char *cb_arg;int init; int shutdown; int flags;int retry_reason; int num; void *ptr; struct bio_st *next_bio;struct bio_st *prev_bio;int references; uint64_t num_read; uint64_t num_write; CRYPTO_EX_DATA ex_data; CRYPTO_RWLOCK *lock; };
struct bio_method_st { int type; const char *name; int (*bwrite) (BIO *, const char *, size_t, size_t *); int (*bwrite_old) (BIO *, const char *, int); int (*bread) (BIO *, char *, size_t, size_t *); int (*bread_old) (BIO *, char *, int); int (*bputs) (BIO *, const char *); int (*bgets) (BIO *, char *, int); long (*ctrl) (BIO *, int, long, void *); int (*create) (BIO *); int (*destroy) (BIO *); long (*callback_ctrl) (BIO *, int, bio_info_cb *); };
typedef struct { char *fpos; void *base; unsigned short handle; short flags; short unget; unsigned long alloc; unsigned short buffincrement; } FILE;
BIO *BIO_new(BIO_METHOD *type);
BIO *BIO_new_fp(FILE *stream, int close_flag);
BIO *BIO_push(BIO *b, BIO *append);
int BIO_write(BIO *b, const void *data, int dlen);
int BIO_read(BIO *b, void *buf, int len);
int BIO_flush(BIO *b);
void BIO_free_all(BIO *a);
BIO_METHOD *BIO_f_base64(void);
FILE *fopen(const char *filename, const char *mode);
int fprintf(FILE *stream, const char *format, ...);
int fclose(FILE *stream);
]]
BIO_NOCLOSE = 0 --# define BIO_NOCLOSE 0x00
BIO_CLOSE = 1 --# define BIO_CLOSE 0x01
ssl = ffi.load('/usr/lib/libssl.so')
f = ffi.C.fopen("/tmp/test", "a+")
bio = ffi.new('BIO')
b64 = ffi.new('BIO')
str = "Hello World"
b64 = ssl.BIO_new(ssl.BIO_f_base64())
bio = ssl.BIO_new_fp(f, BIO_NOCLOSE)
ssl.BIO_push(b64, bio)
=ssl.BIO_write(b64, str, #str) --This yields 11 in the Lua interpreter. This function returns an int with the number of bytes successfully written so apparently the string was written to the file.
ssl.BIO_flush(b64)
ssl.BIO_free_all(b64)
ffi.C.fclose(f)

PAM module error (passing argument 1 of ‘snprintf’ discards ‘const’)

I have my PAM module:
I try to compile it, using string:
gcc -fPIC -DPIC -shared -rdynamic -o pam_test.so pam_test.c
But I have errors:
pam_test.c: In function ‘pam_sm_authenticate’:
pam_test.c:74:9: warning: passing argument 1 of ‘snprintf’ discards ‘const’ qualifier from pointer target type [enabled by default]
snprintf(msg[0].msg,60,"Second Password:%d:%d:%d:%d:",x1,x2,x3,x4);
^
In file included from pam_test.c:10:0:
/usr/include/stdio.h:386:12: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
extern int snprintf (char *__restrict __s, size_t __maxlen,
module code:
#include <security/pam_modules.h>
#include <stdarg.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#define PAM_SM_AUTH
#define MAX_V 30
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
unsigned int ctrl;
int retval;
const char *name, *p;
char *right;
int x1,x2,x3,x4,y;
time_t mytime;
struct tm *mytm;
mytime=time(0);
mytm=localtime(&mytime);
srandom(mytime);
x1=random()%MAX_V;
x2=random()%MAX_V;
x3=random()%MAX_V;
x4=random()%MAX_V;
retval = pam_get_user(pamh, &name, "login: ");
{
struct pam_conv *conv;
struct pam_message *pmsg[3],msg[3];
struct pam_response *response;
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
pmsg[0] = &msg[0];
msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
msg[0].msg=malloc(100);
snprintf(msg[0].msg,60,"Second Password:%d:%d:%d:%d:",x1,x2,x3,x4);
retval = conv->conv(1, ( const struct pam_message ** ) pmsg
, &response, conv->appdata_ptr);
y=2*x1*mytm->tm_mday+x3*mytm->tm_hour;
right=malloc(100);
snprintf(right,20,"%d",y);
if (!(strcmp(right,response->resp))){
return PAM_SUCCESS;
}else{
return PAM_AUTH_ERR;
}
}
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags
,int argc, const char **argv)
{
unsigned int ctrl;
int retval;
retval = PAM_SUCCESS;
}
#ifdef PAM_STATIC
struct pam_module _pam_unix_auth_modstruct = {
"pam_test",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL,
NULL,
};
#endif
The problem here is that in struct pam_message, the msg field is declared as const char*; that is, a pointer to an immutable string. So you're not supposed to overwrite it with snprintf.
A simple workaround is to write the string before inserting a pointer to it into msg:
char *s = malloc(100);
snprintf(s, 100, "Second Password:%d:%d:%d:%d:",x1,x2,x3,x4);
msg[0].msg = s;
Note: You should check the return value of snprintf. If the value returned is more than 100, then the string was truncated.

New to C... getting "UArray2.h:19: error: expected ‘)’ before ‘*’ token" on an unfinished function declaration

I'm working on a CS project for school, but I seem to be getting this odd error which is pretty unhelpful. My partner and I can't seem to figure it out.
It says "UArray2.h:18: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute’ before ‘*’ token" on the first function declaration my .h file (UArray2_new).
It's followed by repeated "error: expected ‘)’ before ‘*’ token" on every line with a function declaration. Any ideas? I included a blank main in mine, so you could see that it couldn't have been a compile issue. I used "gcc -Wall -Wextra -Werror UArray2.c" for compiling.
//UArray2.h
#include <stdlib.h>
#include <stdio.h>
#ifndef UARRAY2_INCLUDED
#define UARRAY2_INCLUDED
struct UArray2_T{
int width, height;
};
extern UArray2_T * UArray2_new(int height, int width, int size);
extern void UArray2_free(UArray2_T * uarray2);
extern void * UArray2_at(UArray2_T * uarray2, int column, int row);
extern int UArray2_size(UArray2_T * uarray2);
extern int UArray2_columns(UArray2_T * uarray2);
extern int UArray2_rows(UArray2_T * uarray2);
static int UArray2_index(UArray2_T * uarray2, int col, int row);
#endif
And here is the .c file
//UArray.c
#include <stdlib.h>
#include <stdio.h>
#include "UArray2.h"
int main()
{
return 0;
}
UArray2_T * UArray2_new(int height, int width, int size)
{
T newArray=malloc(sizeof(UArray2_T));
newArray->height=height;
newArray->width=width;
(void) size;
return newArray;
}
void UArray2_free(UArray2_T * uarray2)
{
(void) uarray2;
//need to write
}
void * UArray2_at(UArray2_T * uarray2, int column, int row)
{
(void) uarray2;
int index=UArray2_index(uarray2, column, row);
(void) index;
//if(index>0 && index<=column*row)
//return UArray_at(uarray2->UArray, index);
//else
//throw an error
char * k="hi"; //dummy variables
return k;
}
int UArray2_size(UArray2_T * uarray2)
{
//UArray_size(uarray2->UArray);
return 0;
}
int UArray2_columns(UArray2_T * uarray2){
return uarray2->width;
}
Everywhere you have UArray2_T *, you should replace it with struct UArray2_T *. The struct keyword is required for C (but not in C++), when you refer to a struct type.
The standard way to avoid this is to use typedef, for example:
typedef struct {
int width, height;
} UArray2_T;
In C, saying struct Foo does not introduce a new type called Foo. The type is called struct Foo.
You can create an alias for the type name, like so:
typedef struct UArray2_T UArray2_T;
Doing so should fix your errors.
I would move the structure to the .c file. This will hide the structure's internals.
struct UArray2_T { // move to the .c file
int width, height;
};
Add a forward declaration to the .h file, like this:
struct UArray2_T;
You need to typedef your struct, or use the struct keyword everwhere. I like this style:
typedef struct {
int data1;
char data2;
} newtype;

Function parameters

What I have to put as second parameter in this function? I need to understand the meaning of int (*fn)(const char *, const struct stat *ptr, int flag).
int
ftw(const char *path, int (*fn)(const char *, const struct stat *ptr, int flag),
int depth);
Thank you!!
int (*fn)(const char *, const struct stat *ptr, int flag)
is a pointer to a function that returns an int and takes a const char*, a const struct stat *, and an int.
If you had this function:
int func (const char *s, const struct stat *ptr, int flag)
{
return 0;
}
You could pass func as that argument.

Resources