IOCTL call and checking return value - ioctl

if((err = ioctl(fd, IOC_CARD_LOCK, &lock)) < 0)
{
printf("ioctl failed and returned errno %d \n",err);
}
Is the above code correct and a good programming practice? It does compile on my PC.
i.e does it populate err with the return value of ioctl and check if err is < 0
Is the above method a standard way to return "err" returned by IOCTL.
There seem to be some standard variable called errno?
what is it? Will that be the same as above?

I found out a better way to do this.
if(ioctl(fd, IOC_CARD_LOCK, &lock) < 0)
{
printf("ioctl failed and returned errno %s \n",strerror(errno));
}
errno is a global variable that is set for system calls.and strerror converts the code (a negative integer) into a meaningful string ("Invalid argument" for example.)

Just stumbled over this response. The answer is only partly correct, as printf might overwrite errno - according to the man pages it's mandatory to save errno. So a more robust answer is:
if(ioctl(fd, IOC_CARD_LOCK, &lock) < 0)
{
int errsv = errno;
printf("ioctl failed and returned errno %s \n",strerror(errsv));
}

Related

error: use of undeclared identifier 'LP_c_uint'

I am using cppyy in my project to call C APIs.
I get below error log captured by capfd plugin in pytest, when an exception happens:
input_line_33:2:11: error: use of undeclared identifier 'LP_c_uint'
(sizeof (LP_c_uint))
It is coming from below code block, specifically logger.error() call:
try:
....
except Exception as e:
out, err = capfd.readouterr()
if err:
logger.error(err)
Now, if I grep my python source code, I don't any hits to 'LP_c_uint'.
Any pointers on how to debug this (like what may be causing this)?
Edit:
simple reproducer:
from ctypes import c_uint32, pointer, byref
import cppyy
from cppyy import sizeof
cppyy.cppdef(
"""
void func(uint32_t *param) {
std::cout << "param: " << *param << std::endl;
}
"""
)
if __name__ == "__main__":
param = pointer(c_uint32(17))
cppyy.gbl.func(param)
print(sizeof(param))
Output:
param: 17
input_line_22:2:11: error: use of undeclared identifier 'LP_c_uint'
(sizeof (LP_c_uint))
^
0
Yes, using ctypes.sizeof would solve it. I see the need for using ctypes.c_uint32 here (although using ctypes.pointer is not necessary) as there is no way of creating a pointer type from cppyy.gbl.uint32_t (which is basically Python's int, so internals to take a pointer to are not exposed).
cppyy.sizeof is now changed to forward to ctypes.sizeof as necessary. That'll make your code work and will be part of next release. As a current workaround, you can do something similar. For example:
def my_sizeof(tt):
try:
return ctypes.sizeof(tt)
except TypeError:
pass
return cppyy.sizeof(tt)

Passing a pipefd through execlp in C

I have looked all over and I cannot seem to figure out how to do this.
I have a parent process that has created a pipe()
Now, I want to fork() the parent and then execlp() and pass the pipe() to the new program as a command line argument.
Then from inside the new program I need to be able to read the pipefd.
I've seen a bunch of stuff on how to do it from inside the same process, but nothing on how to do it like this.
Edit: Initial post is/was rather vague.
What I have so far is:
int pfd[2];
if(pipe(pfd) == -1) {
perror("Creating pipe\n");
exit(1);
}
pid_t pid = fork();
if(pid == -1) {
fprintf (stderr, "Initiator Error Message : fork failed\n");
return -1;
}
else if(pid == 0) { // child process
close(pipe0[1]); // close(write);
execlp("program", "program", pipe0[0], NULL);
}
but then I don't really understand what I should do from inside "program" to get the FD. I tried assigning it to all sorts of things, but they all seem to error.
Thank you in advance!
The forked and execed child automatically inherit the open pipe descriptors and the pipe output is usually fed as standard input so that a command line argument to find the pipe is pretty redundant:
if(!pipe(&pipefd))
switch(fork()) {
case 0: !dup2(pipefd[0],0)&&
execlp("cat","cat","-n","/dev/fd/0",0);
case -1: return perror("fork");
default: write(pipefd[1],"OK\n",3);
}

tftpGet error from tftpLib in VxWorks

I'm writing a little function that downloads a file from a TFTP server using VxWork's tftpLib (http://www.vxdev.com/docs/vx55man/vxworks/ref/tftpLib.html) - now I realized that my tftpGet() command is returning an error 1 but I'm not sure what errorcode 1 means. On the posted website it says:
ERRNO
S_tftpLib_INVALID_DESCRIPTOR
S_tftpLib_INVALID_ARGUMENT
S_tftpLib_NOT_CONNECTED
But how do I know what 1 corresponds with?
The get portion of my code looks like this:
/* Initialize and createlocal file handle */
pFile = fopen("ngfm.bin","wb");
if (pFile != NULL)
{
/* Get file from TFTP server and write it to the file descriptor */
status = tftpGet (pTftpDesc, pFilename, pFile, TFTP_CLIENT);
printf("GOT %s\n",pFilename);
}
else
{
printf("Error in tftpGet()\nfailed to get %s from %s\nERRNO %d",pFilename,pHost, status);
}
Try this code:
int status;
if (OK == (status = tftpGet (pTftpDesc, pFilename, fd, TFTP_CLIENT))) {
printf("tftpGet() successful\n");
} else {
printf("Error has occurred: %d\n", errno); // errno is where the error is stored
}
No,The problem in fact was, that I didn';t get a valid file pointer but NULL because there's no such thing as a "current directory" like in Linux in VxWorks but I had to change my fopen to say something like pFile = fopen("flash:/ngfm.bin","wb"); instead.

Error handling after doing strtol

I am trying to read several numbers on stdin, one number on each line. I want to ignore any trailing text after number and strings if any on any line. To implement this I used the below code:
while (getline(cin, str)) {
num = strtol(str.c_str(), NULL, 0);
if (errno != ERANGE && errno != EINVAL) {
arr[i++] = num;
req_pages_size++;
cout << arr[i-1] << "\t";
}
str.clear();
}
ISSUE: After unsuccessful conversion, errno doesn't get updated with an error value for successful conversion case. It's value remains the same for previous calls which was unsuccessful.
Please let me know how to handle this issue?
The manpage of errno states:
errno is never set to zero by any system call or library function
but you can set it to zero as stated in the manpage of strtol()
the calling program should set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a nonzero value after the call.
so just add
errno = 0;
before calling strtol()

When will fcntl in solaris return a value less then -1 for F_SETLKW

Fromt he Mannul of fcntl in solaris, Upon successful completion, value returned for F_SETLKW will be "Value other than -1".
But Apache httpd 1.3.41 source code (http_main.c) check if the returned value is positive like:
int ret;
while ((ret = fcntl(lock_fd, F_SETLKW, &unlock_it)) < 0 && errno == EINTR) {
/* nop */
}
if (ret < 0) {
ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
"fcntl: F_SETLKW: Error getting accept lock, exiting! "
"Perhaps you need to use the LockFile directive to place "
"your lock file on a local disk!");
clean_child_exit(APEXIT_CHILDFATAL);
}
In very rare case, apache in one of our system will exit beacuse of this failed test. I suspect this was caused by a negative value less than -1 returned by fcntl.
So when will fcntl in solaris return a value less than -1?
in your code sample, fcntl returns <0 (e.g. -1 you know) means might have errors if errno was not EINTR, and if errno == EINTR (interrupted), it is not an error, just suggest retrying again.
"Fromt he Mannul of fcntl in solaris, Upon successful completion, value returned for F_SETLKW will be Value other than -1", meant returns 0 or >0 when success, ">=0" is a value other than -1, not <-1 as you guessed.