Reading and searching files using systemcalls in C - c

I tried reading from the file "hello.txt" but it doesn't enter the while loop at all. The read function returns 0 on EOF and -1 on error. I'm trying to search for the word in w if it exists in the file or not. I'm reading characters from the file and comparing them to w[].
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
char c;
int i=0;
int bytesread;
int flag=1;
char w[]={'h','e','l','l','o'};
if((fd=open("hello.txt",O_RDONLY,0))!=-1){ //if 1
bytesread = read(fd,&c,0);
if(bytesread!=-1){ //if 2
while(bytesread!=0)
{ //while
if(c==w[i])
{ //if 3
i++;
flag=0;
} //end of f3
else if(flag==0&&i!=0)
{ // else 3
i=0;
flag=1;
} // end of else 3
bytesread = read(fd,&c,0);
} //end of while
}else //end of if 2
printf("couldn't read file.\n");
}else //end of if 1
printf("Couldn't open file for read.\n");
} //end of main

ssize_t read(int fd, void *buf, size_t count);
read reads count bytes from the file. You're asking it to read zero bytes when doing bytesread = read(fd,&c,0);. Change it to bytesread = read(fd,&c,1);
Try this:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
int fd;
char c;
int bytesread;
if ((fd = open("hello.txt", O_RDONLY, 0)) != -1) {
while ((bytesread = read(fd, &c, 1)) == 1)
printf("read %d bytes [%c]\n", bytesread, c);
} else
printf("Couldn't open file for read.\n");
return 0;
}

read(fd,&c,0) asks the system to read zero bytes, and it shouldn't be what you want to do.
You should ask the system to read one byte by read(fd,&c,1).

Related

Reading a file character by character using system calls in c

I have no idea how to use system calls but after some search on internet I came up with this code. Can you please correct my code ?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
char ch;
int file;
open(file, "input.txt", O_RDONLY);
read(file, ch, 1);
while (ch != '\0')
{
printf("%c", ch);
fseek(file, 1, SEEK_CUR);
read(file, ch, 1);
}
return 0;
}
you are almost right in doing, dont need to use fseek inside ,it will be automatically moved.
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int retVal = 0;
unsigned char ch;
int fdr = open(argv[1],O_RDONLY);
if( fdr )
{
while(read(fdr,&ch,1) == 1)
printf("%c", ch);
retVal = 0;
}
else
{
printf("File open failed\n");
retVal = -1;
}
return retVal;
}

One of the child processes can't read from pipe

I am trying to implement a small IPC in C, but I have an issue that I can't solve.
My main process have two children, child A and child B; Child A gets created first.
I have two pipes to pass information to these processes, pipefd and pipefd2.
First, parent process reads a file's content, and writes to both pipes these two values:
1-length of the string
2-string itself
Once they get the length of string, they create a char array with the given length, and then read the string into this array.
Then both children read from their pipes. Child B can get these values correctly from the pipe, but child A gets 0 as size.
Here's my code, thanks for your time!
Output :
Child A here, input read, size is: 0
Size is 45169child reads input, size : 45169
Child B here, input read, size is: 45169
//
// Created by Dilara on 16.02.2020.
//
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MESSAGESIZE 10
#define READ_END 0
#define WRITE_END 1
int fsize(FILE *fp){
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
int sz=ftell(fp);
fseek(fp,prev,SEEK_SET); //go back to where we were
return sz;
}
void writeToPipe(int fd[2], char string[], long stell){
close(fd[READ_END]);
write(fd[WRITE_END], stell, sizeof(stell));
write(fd[WRITE_END], string, strlen(string)+1);
close(fd[WRITE_END]);
}
static void readFromPipe(int pipefd[2], char input[],long size){
// wait(NULL);
close(pipefd[WRITE_END]);
read(pipefd[READ_END], input, size);
printf("child reads input, size : %d \n",size);
close(pipefd[READ_END]);
}
static long readSize(int pipefd[2]){
long size;
close(pipefd[WRITE_END]);
read(pipefd[READ_END], size, sizeof(size));
printf("Size is %d",size);
close(pipefd[READ_END]);
return size;
}
int main()
{
int pipefd[2];
int pipefd2[2];
  int childA_pid;
int childB_pid;
if (pipe(pipefd) == -1)
{
perror(" pipe");
return 0;
}
if (pipe(pipefd2) == -1)
{
perror(" pipe");
return 0;
}
childA_pid = fork();
    if(childA_pid == 0){
//childA
long SIZE = readSize(pipefd);
char input[SIZE];
readFromPipe(pipefd, input, SIZE);
printf("Child A here, input read, size is: %d \n",SIZE);
}
else{
childB_pid = fork();
if(childB_pid == 0){
long SIZE = readSize(pipefd2);
char input[SIZE];
readFromPipe(pipefd2, input, SIZE);
printf("Child B here, input read, size is: %d \n",SIZE);
}else{
//parent
char *buffer;
FILE *fp = fopen("try.txt", "r");
if (fp != NULL)
{
fseek(fp, 0L, SEEK_END);
long stell = ftell(fp);
rewind(fp);
char str[stell];
buffer = (char *)malloc(stell);
if (buffer != NULL)
{
//fread(buffer, stell, 1, fp);
fread(str,stell,1, fp);
// printf("%s", str);
fclose(fp);
fp = NULL;
free(buffer);
}
printf("SIZE: %d", stell);
writeToPipe(pipefd2, str,stell);
writeToPipe(pipefd, str,stell);
}
}
   
}
 return 0;
}
write(fd[WRITE_END], stell, sizeof(stell));
I think your code lacks an ampersand here. Instead of the stell variable you should use its address:
write(fd[WRITE_END], &stell, sizeof(stell));

Reading a line and removing Spaces from matrix in a file

OK so I manage to write to the file char by char but it writes twice the numbers and it it still write it with spaces. Any advice and solution?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
extern int errno;
#define MAX_LEN 18
int main(int argc, char *argv[]) {
int fd[2], des, bytes, target;
char buffer[161];
int fdr, fdw; // file descriptors
char c;
fdr = open(argv[1], O_RDONLY); // open files
fdw = open("gg.txt", O_WRONLY | O_CREAT);
if (fdr < 0 || fdw < 0) {
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
while (read(fdr, &c, 1)) { // read/write a single char from/to the files
if (c != ' ' && c != EOF) {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
exit(EXIT_FAILURE);
}
} // echo char to stdout
}
close(fdr); // close the files
close(fdw);
exit(EXIT_SUCCESS);
}
EDIT SECTION
hey again,
i managed to read the file and write it to new one without spaces but i'm trying to insert the values to matrix but im getting an error trying to open the new file.
i have changed the permissions
fdw = open("gg.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
the function
void removeSpaces(int matrix[SIZE][SIZE],int fdr, int fdw) {
char c;
char matBuffer={0};
while (read(fdr, &c, 1)) // read/write a single char
{ // from/to the files
if (c != ' ') {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
exit(EXIT_FAILURE);
}
}
}
int i;
int j;
int k=0;
while(read(fdw, &matBuffer, 1))
{
for(i=0;i<SIZE;i++)
{
for(j=0;j<SIZE;j++)
{
matrix[i][j]=matBuffer-'0';
k++;
}
k=0;
}
}
}
The whole program
// C program to illustrate
// open system call
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#define MAX_LEN 18
#define SIZE 9
void removeSpaces(int matrix[SIZE][SIZE],int fdr, int fdw) {
char c;
char matBuffer={0};
while (read(fdr, &c, 1)) // read/write a single char
{ // from/to the files
if (c != ' ') {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
exit(EXIT_FAILURE);
}
}
}
int i;
int j;
int k=0;
while(read(fdw, &matBuffer, 1))
{
for(i=0;i<SIZE;i++)
{
for(j=0;j<SIZE;j++)
{
matrix[i][j]=matBuffer-'0';
k++;
}
k=0;
}
}
}
int is_safe(int matrix[9][9],int n, int r, int c)
{
int i,j;
//checking in row
for(i=0;i<9;i++)
{
//there is a cell with same value
if(matrix[r][i] == n)
return 0;
}
//checking column
for(i=0;i<SIZE;i++)
{
//there is a cell with the value equal to i
if(matrix[i][c] == n)
return 0;
}
//checking sub matrix
int row_start = (r/3)*3;
int col_start = (c/3)*3;
for(i=row_start;i<row_start+3;i++)
{
for(j=col_start;j<col_start+3;j++)
{
if(matrix[i][j]==n)
return 0;
}
}
return 1;
}
int main(int argc, char * argv[]) {
int pipe_descs[2];
int matrix[SIZE][SIZE];
int fdr, fdw; // file descriptors
int i,j;
/* if (pipe(pipe_descs) == -1) {
fprintf(stderr, "cannot open");
exit(1);
}
pid_t status = fork();
if(status ==0 )
{
}*/
fdr = open(argv[1], O_RDONLY); // open files
fdw = open("gg.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fdr < 0 || fdw < 0) { //validation for error
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
removeSpaces(matrix,fdr, fdw);
for(i=0; i<9; i++){ /* Iterate of each row */
for(j=0; j<9; j++){ /* In each row, go over each col element */
printf("%c ",matrix[i][j]); /* Print each row element */
}
printf("\n"); /* Finish a row, start a new line */
}
close(fdr); // close the files
close(fdw);
exit(EXIT_SUCCESS);
}
There are multiple problems in the code:
you do not test for read errors, read can return -1 for error, which would not stop the while loop.
testing c != EOF is meaningless. EOF is returned by getc() to indicate end of stream or input error, read indicates these conditions in its return value, c is always a byte value if read succeeded and returned 1.
gg.txt is not truncated by open with the given flags. Chances are you are overwriting the beginning of the file and for some reason the file is longer from previous attempts and still contains previously written data. You must also pass the mode bits for the file creation as the third argument to open. Use this:
// open the file for writing, truncate if it exists or create with
// read/write permission for user, read permission for group and others
fdw = open("gg.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
the comment // echo char to stdout does not seem to refer to any code.
Here is a corrected version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fdr, fdw; // file descriptors
char c;
fdr = open(argv[1], O_RDONLY); // open files
if (fdr < 0) {
fprintf(stderr, "failed to open input file %s: %s\n", argv[1], strerror(errno));
return EXIT_FAILURE;
}
// open the output file for writing, truncate if it exists or create with
// read/write permission for user, read permission for group and others
fdw = open("gg.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fdw < 0) {
fprintf(stderr, "failed to open output file %s: %s\n", "gg.txt", strerror(errno));
return EXIT_FAILURE;
}
// read/write a single char from/to the files
while (read(fdr, &c, 1) == 1) {
if (c != ' ') {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
return EXIT_FAILURE;
}
}
}
close(fdr); // close the files
close(fdw);
return EXIT_SUCCESS;
}

How to write and read from a named pipe in C?

I have 2 programs (write.c and read.c). I want to continuously write to the named pipe from standard input, and read from it on the other end (and write to standard output). I've made something work, but it isn't working right. The program on the other end reads in the wrong order or reads special characters (so it reads more then it needs?). I also want to be able to compare the named pipe output to a certain string.
Anyways, here's the code from both files:
write.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFSIZE 512
#define err(mess) { fprintf(stderr,"Error: %s.", mess); exit(1); }
void main()
{
int fd, n;
char buf[BUFFSIZE];
mkfifo("fifo_x", 0666);
if ( (fd = open("fifo_x", O_WRONLY)) < 0)
err("open")
while( (n = read(STDIN_FILENO, buf, BUFFSIZE) ) > 0) {
if ( write(fd, buf, strlen(buf)) != strlen(buf)) {
err("write");
}
}
close(fd);
}
read.c:
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 512
#define err(mess) { fprintf(stderr,"Error: %s.", mess); exit(1); }
void main()
{
int fd, n;
char buf[BUFFSIZE];
if ( (fd = open("fifo_x", O_RDONLY)) < 0)
err("open")
while( (n = read(fd, buf, BUFFSIZE) ) > 0) {
if ( write(STDOUT_FILENO, buf, n) != n) {
exit(1);
}
}
close(fd);
}
Example of input:
hello how are you
123
test
Example of incorrect output:
hello how are you
b123
o how are you
btest
how are you
b
Another example of input:
test
hi
And output:
test
hi
t
The buffer modify by read is not a valid c string so
write(fd, buf, strlen(buf)) != strlen(buf) // write.c
is undefined behaviour. You should do
write(fd, buf, n) != n
because you read n octet with read().
It's funny because you do it for read.c but not for write.c
The type of n must but ssize_t and not int, man read.
main() must return a int Declare main prototype

Read last 20 bytes from a file

int fd, read_byte;
char *c;
fd = open("foo.txt", O_RDONLY);
read_byte = read(fd, c, 20);
printf("");
How to read last 20 bytes from a file and print the read_byte to the screen.
Use lseek(2)
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
int fd, read_byte;
char c[21];
fd = open("foo.txt", O_RDONLY);
if (fd == -1) {
printf("Error opening file\n");
return -1;
}
// reposition fd to position `-20` from the end of file.
lseek(fd, -20L, SEEK_END);
read_byte = read(fd, c, 20); // Read 20 bytes
c[read_byte] = '\0';
printf("%s\n", c);
close(fd);
return 0;
}

Resources