Does dup2(filedescriptor, STDOUT_FILENO) interfere with write and read? - c

I have written this program
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
void redirect(char* filename, char* temp){
chdir("/Users/.....my name..../Desktop");
char buff1[1024];
int fd1, fd2;
if ((fd1 = open(filename, O_RDONLY, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)) == -1){
perror("file problem thomas");
exit(1);
}
if ((fd2 = open(temp, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)) == -1){
perror("file problem temp");
exit(1);
}
int r = read(fd1, buff1, 1024);
write(fd2, buff1, r);
dup2(fd2, STDOUT_FILENO);
char *args[] = {"ls", NULL};
execvp(args[0], args);
dup2(STDOUT_FILENO, fd2);
close(fd1);
close(fd2);
}
void copy_file(char* filename, char* temp){
chdir("/Users/.....my name ..../Desktop");
int fd1, fd2;
char buffer[1024];
long int n1;
if ((fd1 = open(temp, O_RDONLY))==-1 || ((fd2 = open(filename, O_WRONLY|O_CREAT)) == -1)){
perror("file problem");
exit(1);
}
printf("fd1: %d\n", fd1);
printf("fd2: %d\n", fd2);
while((n1 = read(fd1, buffer, 1024)) > 0){
if (write(fd2, buffer, n1) != n1){
perror("writing problem");
exit(3);
}
}
close(fd1);
close(fd2);
}
int main(){
redirect("thomas", "TEMP");
copy_file("thomas", "TEMP");
}
I have two files "thomas" and "TEMP". What I am trying to do is write the contents of "thomas" into "TEMP", and then write the output of "ls" on the command line to "TEMP", and then write the whole "TEMP" file back into "thomas". For some reason, when I run these two files together, the copy_file function does not run – only redirect will. However, when I run this program without redirect(...), the copy_file function works.
Why is copy_file not running in conjunction with redirect?
Is it something with how I am running dup2(STDOUT_FILENO, fd2) and then not changing the STDOUT file descriptor back?
Any help is appreciated!

Related

How can I duplicate time atrributes in C on Linux?

I tried to make a copy program. I made it, but it's hard to implement copying time-atrributes(access time, modify time, change time).
I thought that I can make it using st_atime, st_mtime, st_ctime of struct stat.
But I don't know where should I use them.
Can you help me?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_BUF 64
int main(int argc, char *argv[]) {
char buf[MAX_BUF];
int fd, fd1, read_size, write_size;
struct stat stat; // struct stat variable
// if the number of arguments are not 3, return 0
if(argc != 3) {
printf("\nUSAGE: %s [old_file_name] [new_file_name]\n\n", argv[0]);
return 0;
}
fd = open(argv[1], O_RDONLY); // execute an original file descriptor(read only)
fstat(fd, &stat); // store stats of the original file
// execute a file descripoter to be copied
if(0 < (fd1 = open(argv[2], O_RDWR | O_CREAT | O_EXCL, stat.st_mode))) {
// write data of original in copied
while(1) {
read_size = read(fd, buf, MAX_BUF);
if(read_size == 0) break;
write_size = write(fd1, buf, read_size);
}
} else
printf("\nfile name of [%s] is already exist\n\n", argv[2]);
close(fd);
close(fd1); // close file descriptors
}
The function you're after is called utime().

C Program that makes a copy of a file using standard I/O and system calls

I am trying to write a C program which uses standard I/O and System calls to perform copying of contents of one file to another file.
So far, I have done this :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd1, fd2;
char buffer[1024];
long int n1;
if(((fd1 = open(argv[1], O_RDONLY)) == -1) || ((fd2=open(argv[2],O_CREAT|O_WRONLY|O_TRUNC, 0700)) == -1)){
perror("file problem");
exit(1);
}
while((n1=read(fd1, buffer, 1024) > 0)){
if(write(fd2, buffer, n1) != n1){
perror("writing problem ");
exit(3);
}
}
close(fd1);
close(fd2);
}
When I run the program like this :
cc copyContents.c
./a.out one.txt two.txt
Assuming that one.txt is well defined, what I want is to create a new file called two.txt and copy over all the contents of one.txt
When I look into the contents of two.txt after running the program, it has literally nothing in it. Just a blank file.
Where am I going wrong?
You wrote
while((n1=read(fd1, buffer, 1024) > 0)){
instead of
while ( (n1 = read(fd1, buffer, 1024)) > 0)
In your code the code int the while condition boils down to:
n1 = (read(fd1, buffer, 1024) > 0)
So the read is done correctly, it's return value is compared to 0, the result of the comparision (0 or 1) is assigned to n1.
This shows once more how important it is to format your code in a way that makes it readable.
You could have debugged this easily yourself with a debugger or by inserting one or two printfs in your code.
Input:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
void typefile (char *filename)
{
int fd, nread;
char buf[1024];
fd = open (filename, O_RDONLY);
if (fd == -1) {
perror (filename);
return;
}
while ((nread = read (fd, buf, sizeof (buf))) > 0)
write (1, buf, nread);
close (fd);
}
int main (int argc, char **argv)
{
int argno;
for (argno = 1; argno < argc; argno )
typefile (argv[argno]);
exit (0);
}
Output:
student#ubuntu:~$gcc –o prg10.out prg10.c
student#ubuntu:~$cat > ff
hello`enter code here`
hai
student#ubuntu:~$./prg10.out ff
hello
hai
This is the best solution and easily executable.
input:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int f1, f2;
char buff[50];
long int n;
if(((f1 = open(argv[1], O_RDONLY)) == -1 || ((f2=open(argv[2], O_CREAT |
O_WRONLY | O_TRUNC, 0700))== 1)))
{
perror("problem in file");
exit(1);
}
while((n=read(f1, buff, 50))>0)
if(write(f2, buff, n)!=n)
{
perror("problem in writing");
exit(3);
}
if(n==-1)
{
perror("problem in reading");
exit(2);
}
close(f2);
exit(0);
}
Output:
cc sys.c
./a.out a.txt b.txt
cat b.txt
So, a.txt should have some content and this content is copied to b.txt
by "cat b.txt" you can cross-check the content(which is in "a.txt").
Narenda checks if n==-1 inside the loop, but, the loop test is n>0, so, that'll never happen.
Also, the test for a bad read should precede the attempt to write.

How to redirect program output to text file

I want to redirect the output of a program to a file. How can I do this? At the moment my file doesn't get created, I can only print the output to my console.
int fd[2];
int processId;
int output;
char filename[] = "output.txt";
if((output = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) == -1){
fprintf(stderr, "Unable to create/open file '%s'\n", filename);
return 1;
}
if(pipe(fd) == -1){
fprintf(stderr, "Error creating pipe\n");
return 2;
}
if((processId = fork()) == -1){
fprintf(stderr, "Error forking\n");
return 3;
}
if(processId == 0){
int newFD = dup(STDOUT_FILENO);
char newFileDescriptor[2];
sprintf(newFileDescriptor, "%d", newFD);
dup2(fd[1], output);
close(fd[0]);
execl("./pipetest", "pipetest", newFileDescriptor, NULL);
}else{
close(fd[1]);
char c[10];
int r = read(fd[0], c, sizeof(char) * 10);
if(r > 0){
fprintf(stderr, "PIPE INPUT = %s", c);
fwrite(c, 1, sizeof(c), output);
}
}
A good start is not ignoring compiler warnings:
test.c: In function ‘main’:
test.c:42:13: warning: passing argument 4 of ‘fwrite’ makes pointer from integer without a cast [enabled by default]
fwrite(c, 1, sizeof(c), output);
^
In file included from test.c:1:0:
/usr/include/stdio.h:715:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘int’
extern size_t fwrite (const void *__restrict __ptr, size_t __size,
^
int and FILE* are not interchangable. If you use open, write with write. If you use fopen, write with fwrite.
Additionally, you never modify stdout of your process. Instead you modify output, which doesn't make sense. Here are the minimum changes to your code to make it work:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd[2];
int processId;
int output;
char filename[] = "output.txt";
if((output = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) == -1){
fprintf(stderr, "Unable to create/open file '%s'\n", filename);
return 1;
}
if(pipe(fd) == -1){
fprintf(stderr, "Error creating pipe\n");
return 2;
}
if((processId = fork()) == -1){
fprintf(stderr, "Error forking\n");
return 3;
}
if(processId == 0){
int newFD = dup(STDOUT_FILENO);
char newFileDescriptor[2];
sprintf(newFileDescriptor, "%d", newFD);
dup2(fd[1], STDOUT_FILENO); // You want to modify STDOUT_FILENO
close(fd[0]);
execl("/bin/echo", "echo", newFileDescriptor, NULL); // switched to echo
}else{
close(fd[1]);
char c[10];
int r = read(fd[0], c, sizeof(char) * 10);
if(r > 0){
fprintf(stderr, "PIPE INPUT = %s", c);
write(output, c, r); // use write instead of fwrite
}
}
}
Here's the result of running it:
$ gcc test.c -o test
$ ./test
PIPE INPUT = 6
$ cat output.txt
6
The easiest way is to do this at the bash by calling:
./myprogram > output.txt
This will redirect all of the outputs to output.txt
You can use freopen, it's probably the simplest way:
if (!freopen("out.txt", "w", stdout))
{
// failed to open the file stream, handle the error
}
You can then just use printf to write to that file. You can do the same with stderr, but that's probably a bad idea - by definition stderr is used to report errors, and from what I know the convention is to have it output to console.
Here's simples example how to do this:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(void) {
int out = open("/tmp/output.txt", O_WRONLY | O_CREAT, 0644);
if (out == -1) {
perror("open:");
return -1;
}
int r;
r = close(1); /* this closes stdout */
if (r != 0) {
perror("close:");
return -1;
}
r = dup2(out, 1); /* this duplicates your file descriptor to stdout */
if (r == -1) {
perror("dup2:");
return -1;
}
printf("this should go to the output file\n");
return 0;
}

How to send a file through a named pipe in C?

I have two programs, server and client. Server should read a file and then send its content through a named pipe to client. But my server reads only two chars from file, and then exits. What is wrong with this code?
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char line[300];
int num, fd;
FILE *fp;
fp = fopen("out.txt","r");
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for readers...\n");
fd = open(FIFO_NAME, O_WRONLY);
printf("got a reader--type some stuff\n");
while (fgets(line, sizeof(line), fp)) {
if ((num = write(fd, line, strlen(line))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}
fclose(fp);
return 0;
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char s[300];
int num, fd;
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for writers...\n");
fd = open(FIFO_NAME, O_RDONLY);
printf("got a writer\n");
do {
if ((num = read(fd, s, 300)) == -1)
perror("read");
else {
s[num] = '\0';
printf("tick: read %d bytes: \"%s\"\n", num, s);
}
} while (num > 0);
return 0;
}
When I run the code shown below using the command sequence:
$ ln -s server.c out.txt
$ ./client &
$ ./server
$
I get a copy of the source code printed by the client program. Similarly when I run the commands using:
$ ./server &
$ ./client
$
The revised code is not modified all that significantly. It avoids do { } while(...) loops — they're so seldom really beneficial — and is very careful about not overflowing buffers. The code also has superfluous headers removed.
server.c
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
const char infile[] = "out.txt";
FILE *fp = fopen(infile, "r");
if (fp == 0)
{
fprintf(stderr, "Failed to open %s for reading", infile);
return(1);
}
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for readers...\n");
int fd = open(FIFO_NAME, O_WRONLY);
if (fd > 0)
{
char line[300];
printf("got a reader--type some stuff\n");
while (fgets(line, sizeof(line), fp))
{
int len = strlen(line);
int num = write(fd, line, len);
if (num != len)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}
close(fd);
}
fclose(fp);
return 0;
}
client.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
const char outfile[] = "client.out";
FILE *fp = fopen(outfile, "w");
if (fp == 0)
{
fprintf(stderr, "Failed to open %s for writing\n", outfile);
return 1;
}
printf("waiting for writers...\n");
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
int fd = open(FIFO_NAME, O_RDONLY);
if (fd > 0)
{
int num;
char s[300];
printf("got a writer\n");
while ((num = read(fd, s, sizeof(s))) > 0)
{
printf("tick: read %d bytes: \"%.*s\"\n", num, num, s);
fprintf(fp, "%.*s", num, s);
}
close(fd);
}
fclose(fp);
return 0;
}
Note that this version writes its output to file client.out; even when given a file with some very long lines to process (2049 bytes including the newline at the end), the output in client.out exactly matches the input in out.txt.
Remove the line mknod(FIFO_NAME, S_IFIFO | 0666, 0); from the file client.c. Then the program will work as expected. Server will create a file and sent the content of the file to fifo.

Writing to file descriptor

In the following snippet i am redirecting the output of the ls command to input of wc -l which works perfectly .Now i also want to redirect the output of ls command to a file named "beejoutput.txt" using the following code but its not working. Need help.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pfds[2];
pipe(pfds);
if (!fork())
{
dup2(pfds[1],1);
close(pfds[0]);
execlp("ls", "ls",NULL);
}
else
{
FILE *outputO=fopen ("beejoutput.txt", "w"); //opening file for writing
dup2(pfds[0],0);
dup2(fileno(outputO),pfds[0]);
close(pfds[1]);
execlp("wc", "wc","-l", NULL);
}
return 0;
}
The dup function duplicates a file descriptor, that is, both the old and new file descriptors refer to the same open file afterwards. That is different from having a single file descriptor refer to two different files at the same time.
If you want to send the same data to two different destinations, you need to spawn both commands in separate processes, and do the copying yourself, or spawn a copy of the "tee" command -- either way, you end up with three processes.
This worked for me :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int pfds[2];
pipe(pfds);
pid_t childpid = fork();
if (childpid == 0) {
/* Child */
dup2(pfds[1],1);
close(pfds[0]);
execlp("ls", "ls",NULL);
} else {
/* Parent */
pid_t retpid;
int child_stat;
while ((retpid = waitpid(childpid, &child_stat, 0)) != childpid && retpid != (pid_t) -1)
;
close(pfds[1]);
char buf[100];
ssize_t bytesread;
int fd = open("beejoutput.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd == -1) {
fprintf(stderr, "Opening of beejoutput.txt failed!\n");
exit(1);
}
/* This part writes to beejoutput.txt */
while ((bytesread = read(pfds[0], buf, 100)) > 0) {
write(fd, buf, bytesread);
}
lseek(fd, (off_t) 0, SEEK_SET);
dup2(fd, 0);
execlp("wc", "wc", "-l", NULL);
}
return 0;
}
Try checking the result codes of all the system calls that you do (including dup2). This will possibly lead you to an answer. This is a good habbit, anyway.

Resources