Transferring data from a serial Port to a text file - c

I'm using debian and I have to transfer data from a serial port into a text file to then get read into a database. I think how im setting the port up is wrong, and I keep stumbling across so many different examples, My current code (below) keeps giving me 3 warnings, "assignment makes pointer from integer without a cast" I think it has to do with the values that are being returned, I did some reading on what pointers return, but it wasn't too clear to me, I was wondering if someone could give some insight on the issue, or if there are any glaringly obvious issues that I am missing. Any suggestions are much appreciated.
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <termios.h>
#include <string.h>
#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS0"
main()
{
int n;
FILE *file;
file = open(MODEMDEVICE, O_RDWR, O_NOCTTY);
if(file == NULL){
printf("initiation error. \n");
return 1;
}
FILE *fp;
fp = open("testfile.txt", O_RDWR);
while(1){
file = scanf("%d", &n);
fprintf(fp, "%d", n);
fclose(fp);
}
fclose(file);
}
so what i think this does, or what i intend it to do at least is set file to read data from the port, and then store those values in n, which then get printed in a text file.

This:
FILE *fp;
fp = open("testfile.txt", O_RDWR);
is wrong, you meant fopen() on the last line, don't confuse raw I/O with the C runtime library's buffered functions.
This is also one reason for your error, since the file descriptor (not a pointer) returned by open() is an integer (see the open() manual page and compare that to fopen()'s).
UPDATE: I also fail to understand what you're trying to do with the scanf() line.
If you want to read an integer from a FILE *, you should use fscanf(). The return value is the number of successful conversions, which is used in error-checking:
if(fscanf(file, "%d", &n) == 1)
fprintf(fp, "%d", n);
That will read an integer from the serial port file, and if successful print it out to the output file fp.

Related

How to read an integer and a char with read() function in C?

I'm working on linux, I have a file that contains a line like this:
328abc
I would like, in C, to read the integer part (328) and the characters 'a','b','c', using only the function:
ssize_t read (int filedes, void *buffer, size_t size))
This is the only thing the file contains.
I know there are better ways to do that with other functions, but I haven't coded in C for a long time, and trying to help a friend, only this function is alowed.
How do I play with the buffer to do that?
Thanks
edit:
I understand that I need to parse the buffer manually. and my question is how?
If that's the only thing in the file. This will do:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main() {
char buffer[6];
char intBuffer[4];
ssize_t bytesRead;
int number;
int fd;
if ((fd = open("file.txt", O_RDONLY)) == -1) {
perror("Error opening file");
exit(EXIT_FAILURE);
}
if ((bytesRead = read(fd, buffer, 6)) == -1) {
perror("Error reading file");
exit(EXIT_FAILURE);
}
memcpy(intBuffer, buffer, 3);
intBuffer[3] = '\0';
number = atoi(intBuffer);
printf("The number is %d\n", number);
exit(EXIT_SUCCESS);
}
The following code will print "The number is 328".
Is this some kind of homework?
I am asking because there are better ways to do that than using the read function.
Anyway to answer your question, read reads size bytes from the file whose file descriptor is filedes and places them to the buffer.
It does not know anything about line breaks etc. So you need to manually find where a line ends, etc. If you want to only use read, then you need to manually parse the buffer after each call to read (supposing your files contains many lines, that you want to parse).
Beware that a line may be split between two read calls, so you need to handle that case with caution.

glibc double free or corruption (out) without the use of malloc

I keep getting this error
glibc double free or corruption (out) error
and so far everything i've read on it has been due to an improper use of malloc, which would point to memory space, however, i'm not using malloc. I think its Something about how fscanf is accepting the stream. But nothing I'm reading on fscanf makes any sense to me in relation to the error I'm getting. Here's the code.
#include <stdio.h>
#include <fcntl.h>
#include <sys.stat.h>
#inlcude <termios.h>
#inlcude <string.h>
#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS0"
main()
{
int n;
FILE *file
file = fopen(MODEMDEVICE, "a");
if(file == NULL){
printf("initiating error\n);
return 1;
}
FILE *fp;
fp = fopen("testfile.txt", "a");
while(1){
fscanf(file, "%02x", &n);
fprintf(fp, "%d", n);
fclose(fp);
fclose(file);
}
}
my intention of this code is to take data streams from a serial port and and store them in a text file. Any ideas on why i'm getting this error?
The while(1) loop reads data from one file and writes it to the other file, but then closes the files. Once the files are closed you can't read from or write to them anymore, though your while loop tries again.
This code won't compile. It is missing a ";".
It's also opening both files with mode "a"; but surely you meant to open one for reading.
Anyway the bug is that you're calling fclose in the loop.

Multiple fdopen() on a same filedescriptor fd?

I am trying to understand the standard I/O. I met a problem of calling fdopen().
What's the behavior if I call fdopen() on the same file descriptor as follows? Why do I get an ouput of '\377' (-1) ?
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
int fd1, fd2;
char c;
FILE *fp1, *fp2;
fd1 = open("foo.txt", O_RDONLY, 0);
fp1 = fdopen(fd1, "r");
fp2 = fdopen(fd1, "r");
if (fp2 == NULL)
printf("NULL\n");
if (errno)
printf("ERROR\n");
c = fgetc(fp1);
c = fgetc(fp2);
printf("c = %c\n", c);
exit(0);
}
Let's say your stdio buffer size is 4K. The first fgetc reads 4K into the buffer and returns the first byte. The fd is now advanced 4K into the file. The second fgetc reads from there. Your file is smaller than the buffer size, so you're at EOF. You print the EOF with %c and get a funny character.
Multiple fdopen on a single fd gets a vote of don't try it; it will hurt from me. With an exception for creating stdin, stdout, and stderr from a single tty descriptor if you're writing getty.
Multiple problems:
char is not the right type for storing the return value of fgetc. Use int.
You're accessing the same open file description via two different handles without performing the steps necessary to switch between them legally. This invokes undefined behavior.
Checking errno and inferring from it that there was an error is not valid. If you already know there was an error, errno tells you which one. It does not tell you whether or not an error occurred, and in case one did not, any nonzero value may have been written to errno.
We don't know your file contents so we can't know what you expect to be read.

How do i read a file backwards using read() in c? [duplicate]

This question already has answers here:
Reading a text file backwards in C
(5 answers)
Closed 9 years ago.
I am supposed to create a program that takes a given file and creates a file with reversed txt. I wanted to know is there a way i can start the read() from the end of the file and copy it to the first byte in the created file if I dont know the exact size of the file?
Also i have googled this and came across many examples with fread, fopen, etc. However i cant use those for this project i can only use read, open, lseek, write, and close.
here is my code so far its not much but just for reference:
#include<stdio.h>
#include<unistd.h>
int main (int argc, char *argv[])
{
if(argc != 2)/*argc should be 2 for correct execution*/
{
printf("usage: %s filename",argv[0[]);}
}
else
{
int file1 = open(argv[1], O_RDWR);
if(file1 == -1){
printf("\nfailed to open file.");
return 1;
}
int reversefile = open(argv[2], O_RDWR | O_CREAT);
int size = lseek(argv[1], 0, SEEK_END);
char *file2[size+1];
int count=size;
int i = 0
while(read(file1, file2[count], 0) != 0)
{
file2[i]=*read(file1, file2[count], 0);
write(reversefile, file2[i], size+1);
count--;
i++;
lseek(argv[2], i, SEEK_SET);
}
I doubt that most filesystems are designed to support this operation effectively. Chances are, you'd have to read the whole file to get to the end. For the same reasons, most languages probably don't include any special feature for reading a file backwards.
Just come up with something. Try to read the whole file in memory. If it is too big, dump the beginning, reversed, into a temporary file and keep reading... In the end combine all temporary files into one. Also, you could probably do something smart with manual low-level manipulation of disk sectors, or at least with low-level programming directly against the file system. Looks like this is not what you are after, though.
Why don't you try fseek to navigate inside the file? This function is contained in stdio.h, just like fopen and fclose.
Another idea would be to implement a simple stack...
This has no error checking == really bad
get file size using stat
create a buffer with malloc
fread the file into the buffer
set a pointer to the end of the file
print each character going backwards thru the buffer.
If you get creative with google you can get several examples just like this.
IMO the assistance you are getting so far is not really even good hints.
This appears to be schoolwork, so beware of copying. Do some reading about the calls used here. stat (fstat) fread (read)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
struct stat st;
char *buf;
char *p;
FILE *in=fopen(argv[1],"r");
fstat(fileno(in), &st); // get file size in bytes
buf=malloc(st.st_size +2); // buffer for file
memset(buf, 0x0, st.st_size +2 );
fread(buf, st.st_size, 1, in); // fill the buffer
p=buf;
for(p+=st.st_size;p>=buf; p--) // print traversing backwards
printf("%c", *p);
fclose(in);
return 0;
}

How can I use Linux's splice() function to copy a file to another file?

here's another question about splice(). I'm hoping to use it to copy files, and am trying to use two splice calls joined by a pipe like the example on splice's Wikipedia page. I wrote a simple test case which only tries to read the first 32K bytes from one file and write them to another:
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv) {
int pipefd[2];
int result;
FILE *in_file;
FILE *out_file;
result = pipe(pipefd);
in_file = fopen(argv[1], "rb");
out_file = fopen(argv[2], "wb");
result = splice(fileno(in_file), 0, pipefd[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE);
printf("%d\n", result);
result = splice(pipefd[0], NULL, fileno(out_file), 0, 32768, SPLICE_F_MORE | SPLICE_F_MOVE);
printf("%d\n", result);
if (result == -1)
printf("%d - %s\n", errno, strerror(errno));
close(pipefd[0]);
close(pipefd[1]);
fclose(in_file);
fclose(out_file);
return 0;
}
When I run this, the input file seems to be read properly, but the second splice call fails with EINVAL. Anybody know what I'm doing wrong here?
Thanks!
From the splice manpage:
EINVAL Target file system doesn't support splicing; target file is
opened in append mode; neither of the descriptors refers to a
pipe; or offset given for non-seekable device.
We know one of the descriptors is a pipe, and the file's not open in append mode. We also know no offset is given (0 is equivalent to NULL - did you mean to pass in a pointer to a zero offset?), so that's not the problem. Therefore, the filesystem you're using doesn't support splicing to files.
What kind of file system(s) are you copying to/from?
Your example runs on my system when both files are on ext3 but fails when I use an external drive (I forget offhand if it is DOS or NTFS). My guess is that one or both of your files are on a file system that splice does not support.
The splice(2) system call is for copying between files and pipes and not between files, so it can not be used to copy between files, as has been pointed out by the other answers.
As of Linux 4.5 however a new copy_file_range(2) system call is available that can copy between files. In the case of NFS it can even cause server side copying.
The linked man page contains a full example program.

Resources