I am trying to read following file from C code.
file: /sys/bus/iio/devices/iio\:device0/in_voltage7_raw
but file pointer I am getting is -1.
Using cat command it is able to read the file.
But I am trying to read the same from my code as follows:
nos_int32 nos_adc_read_port (ADC_PORT_DB *p_port, nos_int32 *data)
{
char file_name[VALUE_MAX];
int value;
char buffer[BUFFER_LENGTH];
char intBuffer[INT_BUFFER_LENGTH];
int fd;
sprintf(file_name, "/sys/bus/iio/devices/iio\\:device0/in_voltage7_raw");
fd = open(file_name, O_RDONLY);
if (fd == -1) {
return(-1);
}
if (read(fd, buffer, BUFFER_LENGTH) == -1) {
return(-1);
}
close(fd);
memcpy(intBuffer, buffer, BUFFER_LENGTH);
intBuffer[INT_BUFFER_LENGTH-1] = '\0';
value = atoi(intBuffer);
*data = value;
return(0);
}
After the line:
fd = open(file_name, O_RDONLY);
value of fd is -1. How can it be solved?
Most command line shells use some characters for special actions and if you're trying to use them as their actual character, you need to prefix them with a backslash to escape them. In this case, your shell needs you to escape the colon when accessing that filename.
In C you don't have this issue so you can put in your code the filename as it truly is, such as:
"/sys/bus/iio/devices/iio:device0/in_voltage7_raw"
Related
//error handle
void my_err(const char* errno_string,int line){
fprintf(stderr,"line:%d ",line);
perror(errno_string);
exit(1);
}
//self-definded read data function
int my_read(int fd){
int len;
int ret;
int i;
char read_buf[64];
//get length of file and keep point of file at the srart
if(lseek(fd,0,SEEK_END) == -1){
my_err("lseek",__LINE__);
}
if((len = lseek(fd,0,SEEK_CUR)) == -1){
my_err("lseek",__LINE__);
}
if(lseek(fd,0,SEEK_SET) == -1){
my_err("lseek",__LINE__);
}
printf("len:%d\n",len);
//read data
if((ret = read(fd,read_buf,len)) < 0){
my_err("read",__LINE__);
}
//print data
for(i = 0;i<len;i++){
printf("%c",read_buf[i]);
}
printf("\n");
return ret;
}
int main()
{
int fd;
char write_buf[32] = "hello boy!";
//create example2 in current directory
if((fd = creat("example2.c",S_IRWXU)) == -1){
// if((fd = open("example2.c",O_RDWR|O_CREAT|O_TRUNC,S_IRWXU)) == -1){
my_err("open",__LINE__);
}else{
printf("craete file success\n");
}
//write data
if(write(fd,write_buf,strlen(write_buf)) != strlen(write_buf)){
my_err("write",__LINE__);
}
my_read(fd);
//Spacing of presentation files
printf("/*------------*/\n");
if(lseek(fd,10,SEEK_END) == -1){
my_err("lseek",__LINE__);
}
if(write(fd,write_buf,strlen(write_buf)) != strlen(write_buf)){
my_err("write",__LINE__);
}
my_read(fd);
close(fd);
return 0;
}
Line 43 is this part of main
//create example2 in current directory
if((fd = creat("example2.c",S_IRWXU)) == -1){
my_err("open",__LINE__);
}else{
printf("craete file success\n");
}
When I use creat, I get an error line:43 read: Bad file descriptor, but I get the correct result with open. Shouldn't both functions return file descriptors? Why should creat return the wrong file descriptor
When I use creat, I get an error line:43 read: Bad file descriptor, but I get the correct result with open. Shouldn't both functions return file descriptors? Why should creat return the wrong file descriptor
Shouldn't both functions return file descriptors?
They should and they do.
Why should creat return the wrong file descriptor
It shouldn't and it doesn't. read fails with Bad file descriptor error, not creat.
creat opens file write-only, so you can't read from it. It's a bad file descriptor if you want to read from it.
The call creat(path, mode) behaves the same as the call open(path, O_CREAT | O_WRONLY | O_TRUNC, mode). On success, the file is opened for writing only. The file descriptor passed to read needs to be open for either reading and writing or for reading only. If the file descriptor is open for writing only, calls to read with that file descriptor will fail. When read fails, the error number EBADF means that the file descriptor is not a valid file descriptor open for reading.
I am trying to write a struct to a .dat file and when I open it it shows me this:
"1^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#041720881^#^#^#^#^#^#^#^#^#^#^#Denko^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#Brenko^#^#^#^#^#^#^#^#^#^#^#^#^#^#13.07.2000^#^#^#^#^#^#^#^#^#^#
"
It adds random symbols between the actual values. And now when I at least try to read and print some values, it just doesn't work. It's like the buffer is empty. But I followed the instructions and guides I read.
Using fwrite or similar is not an option since I have to work with these specific functions write() and read().
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
struct info{
char id[20];
char telefon[20];
char ime[20];
char priimek[20];
char datum[20];
};
int main(int argc, char* argv[]) {
struct info dude =
{
"01",
"041720881",
"Denko",
"Brenko",
"13.07.2000"
};
struct info dude2 =
{
"02",
"041581734",
"Denko",
"Badenko",
"13.07.1990"
};
if(strcmp(argv[1], "-c") == 0){
int fd = open("xpo.dat", O_CREAT| O_APPEND | S_IRWXG, 0666);
if(fd == -1){
perror("Error while creating file");
exit(EXIT_FAILURE);
}
}
else if(strcmp(argv[1], "-o") == 0){
struct stat sizefile;
int fd = open("xpo.dat", O_RDWR);
if(fd == -1){
perror("Error while opening file");
exit(EXIT_FAILURE);
}
fstat(fd,&sizefile);
int wr = write(fd, &dude,sizeof(struct info));
char buf[101];
int sz = read(fd, buf, 100);
buf[sz] = '\0';
if(sz == -1) {
perror("Error while creating file");
exit(EXIT_FAILURE);
}
printf("%s", buf);
int cl = close(fd);
}
return 0;
}
The struct contains 100 chars of data. But you are setting only some of them. When you set ime as Denko, the first six chars are set as 'D', 'e', 'n', 'k', 'o','\0'. The remaining 14 are not initialized (or rather initialized implicitly, see #dave_thompson_085's comment below).
If you want to omit those chars, you cannot write the struct as one block. Either write each field separately, or concatenate the fields into a string and write it instead.
As stated in the comments and in the accepted answer, you have some issues, the why and the what is already talked about and explained.
I would like to add some more information:
And now when I at least try to read and print some values, it just doesn't work. It's like the buffer is empty.
What happens is that you are reading from the end of the file, if you want to read after you write without closing and reopening the file, you can, but you'll need to reposition the offset of the opened file to the beginning using lseek.
Another thing to note is that if you want to write the data as a structure you then need to read it as a structure as well, not as a string.
Taking that in consideration your code could look more or less like this (skipping return value validations, but you should do it, as you know):
//...
else if(strcmp(argv[1], "-o") == 0){
int fd = open("xpo.dat", O_RDWR);
int wr = write(fd, &dude, sizeof dude);
lseek(fd, 0, SEEK_SET); // set the reading position to the beginning of the file
struct info buf;
wr = read(fd, &buf, sizeof buf);
int cl = close(fd);
printf("%s %s %s %s %s", buf.id, buf.telefon, buf.ime, buf.priimek, buf.datum);
}
//...
If you prefer it as a string you can easily concatenate it using something like snprintf or similar.
I've written a simplified "cat" function in C. It is working fine, except when one of my argument is the name of a directory.
As it is an assignement, I'm only allowed to use "open", "read" and "close" functions in my code.
When "-1" is returned by function open(file, O_RDONLY), I call function ft_display_error to display error messages such as "No such file or directory".
Yet it doesn't work when "file" is a directory: in this case open will not return "-1". It will go on some kind of infinite loop.
void ft_display_file(char *file)
{
int fd;
char buf[BUF_SIZE + 1];
int ret;
fd = open(file, O_RDONLY);
if (fd == -1)
ft_display_error(file);
else
{
ret = read(fd, buf, BUF_SIZE);
while(ret)
{
buf[ret] = 0;
write(1, buf, ret);
ret = read(fd, buf, BUF_SIZE);
}
}
close(fd);
}
int main(int ac, char **av)
{
int i;
i = 1;
while (i < ac)
{
ft_display_file(av[i]);
i++;
}
}
Instead, I would like my program to identify that my argument is a directory, and then display the following message "cat: file: Is a directory.
Opening a directory for reading with open is the low level way of accessing its contents. Not very useful for you, but it doesn't allow to test for a directory.
If you cannot use stat (which is the best option) there seems to be another trick:
According to the documentation of open
The open() function shall fail if:
...
EISDIR
The named file is a directory and oflag includes O_WRONLY or O_RDWR.
So first try to open your file with O_RDWR (read-write) and if it fails, check if errno is equal to EISDIR
Code (untested)
fd = open(file, O_RDWR);
if ((fd == -1) && (errno == EISDIR))
{
// this is a directory
}
I have a function which take filename as input and do "open" and "read" calls to perform some operation. This filename is received via command line argument.
Now, I am trying to make this function generic so that it can receive string as well and perform the same operations. In other way I am passing the content of file directly as string.
I don't know how to stream the string data to the "open" function.
Also, please note that I am restricted to use the open function for file read.
I tried "pipe" function to stream data to open function, but was not successful.
int sopen(char *s) {
int p[2], ret;
int fd=-1;
int len = strlen(s);
if (pipe(p) != 0) {
fprintf(stderr, "Error in creating pipe");
return -1;
}
if ((fd = open(p[0], O_RDONLY)) < 0) {
fprintf(stderr, "Error in open");
close(p[0]);
close(p[1]);
return -1;
}
ret = write(p[1], s, len);
if (ret != len) {
fprintf(stderr, "Error in writing to pipe");
close(p[1]);
close(fd);
return -1;
}
close(p[1]);
return fd;
}
I expect a file descriptor so that it can be used by the open function, but it is returning -1.
As others said, the pipe() function returns two descriptors that are already ready-to-use. That means, the pipe() already opens them for you. Otherwise it could not guarantee that these are conected to each other.
Remember that you are responsible for closing both of them!
Your whole solution should like something close to this pseudocode below:
main
variable: fileDescriptor
detect if command line contains a filename, or file content
if it was a filename
fileDecriptor = openFile(some arguments...)
if it was a filecontent
fileDecriptor = openAndFillPipe(some other arguments...)
doWhetever(fileDescriptor) // here's the 'operations' on the 'file'
close(fileDescriptor) // whatever we got, we need to clean it up
openFile(filename)
// simply: any file-opening will do
descriptor = open(filename, ...)
openAndFillPipe(filecontent)
// first, make a pipe: two connected descriptors
int pairOfDescriptors[2];
pipe(pairOfDescriptors);
// [0] is for reading, [1] is for writing
write(pairOfDescriptors[1], filecontent, ...) // write as if to a file
close(pairOfDescriptors[1]) // we DONT need the 'write' side anymore
descriptor = pairOfDescriptors[0] // return the 'read' as if it was a file
I tried to write basic program in C which copy data from file to another with given source path, destination path and buffer size as input.
my problem is the destination file filled with junk or something because its way larger than the source (get bigger depending on buffer size) and can't be open.
How do i read and write just the bytes in the source?
i'm working in linux, and this is the actually copying part:
char buffer[buffer_size];
int readable=1;
int writeable;
while(readable != 0){
readable = read(sourcef, buffer, buffer_size);
if(readable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not read.");
}
writeable = write(destf, buffer, buffer_size);
if(writeable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not write.");
}
}
writeable = write(destf, buffer, buffer_size);
must be
writeable = write(destf, buffer, readable);
Currently you do not write the number of characters you read but all the buffer, so the output file is too large
You also manage wrongly the end of the input file
The return value of read is :
On success, the number of bytes read is returned (zero indicates end of file)
On error, -1 is returned
A proposal :
/* you already check input and output file was open with success */
char buffer[buffer_size];
for(;;){
ssize_t readable = read(sourcef, buffer, buffer_size);
if(readable <= 0){
close(sourcef);
close(destf);
if (readable != 0)
/* not EOF */
exit_with_usage("Could not read.");
/* EOF */
break;
}
if (write(destf, buffer, n) != n) {
close(sourcef);
close(destf);
exit_with_usage("Could not write.");
}
}
I suppose exit_with_usage calls exit() so does not return
Note in theory write may write less than the expected number of characters without being an error, and the write has to be done in a loop, but in that case it is useless to manage that
read function returns how many bytes were read to buffer(which has buffer_size). Its not always the case actual bytes read has same value as buffer size(consider scenario if there are not enough bytes left in source file to fully fill your buffer). So you should write to destination file not buffer_size(third argument of the write function), but how many bytes have you read - that is readable variable in your code
You should exit when readable returns an error.So
while(readable != 0){
should be
while(readable != -1){
So that loop could be terminataed when an readfile is exhausted.
You see currently after the whole readfile has been read, calling read fails but write is being called repeatedly since execution has no exit path for failure on read. Also write should only write the number of bytes read. So the code would look like this:
char buffer[buffer_size];
int readable=1;
int writeable;
while(readable != -1){
readable = read(sourcef, buffer, buffer_size);
if(readable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not read.");
}
writeable = write(destf, buffer, readable);
if(writeable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not write.");
}
}
Simple code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 4096
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("Usage %s Src_file Dest_file\n", argv[0]);
exit(1);
}
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t ReadByte = 0;
int src_fd, dst_fd;
// open file in read mode
if ((src_fd = open(argv[1], O_RDONLY)) == -1) {
printf("Failed to open input file %s\n", argv[1]);
exit(1);
}
// open file in write mode and already exists to overwrite
if ((dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 644)) == -1) {
printf("Failed to create output file %s\n", argv[2]);
exit(1);
}
// loop
while (1) {
// read buffer
ReadByte = read(src_fd, buffer, sizeof(buffer));
// error with reading
if (ReadByte == -1) {
printf("Encountered an error\n");
break;
} else if (ReadByte == 0) {
// file end exit loop
printf("File copying successful.\n");
break;
}
// error with writing
if (write(dst_fd, buffer, ReadByte) == -1) {
printf("Failed to copying file\n");
break;
}
}
// Close file
close(src_fd);
close(dst_fd);
exit(0);
}
Run
./program src_file dest_file