Open() for output not creating file - c

I have this function that utilizes open to set i/o redirection:
void setOutput(char * buffer){
int file = open(buffer, O_WRONLY || O_CREAT, S_IWUSR);
if(file < 0){ printf("error opening %s for output\n", buffer); }
if(dup2(file, 1) < 0){ printf("error with dup2 opening %s for output\n", buffer); }
}
When I run it, it works fine for files that are already defined but returns -1 when it receives a non-created file. Not sure why

You need to change the following
int file = open(buffer, O_WRONLY || O_CREAT, S_IWUSR);
To
int file = open(buffer, O_WRONLY | O_CREAT, S_IWUSR);
Format :
int open( char *filename, int access, int permission );
access : Should be provided as a bit wise OR operator, that means using | not || which is logical OR

Related

My program for copying one file to another fails

I was trying to copy what is written in a file to a different file (with system calls) but my code seems not to work. I have first tried just printing with printf() the buffer but it also does not work. My guess is that I'm reading the file incorrectly.
#define BUF_SIZE 200
int main(int argc, char *argv[]){
int entrada,salida,leidos;
char buffer[BUF_SIZE];
entrada = open(argv[1],O_RDONLY);
salida = creat(argv[2], 0644);
while( (leidos = read(entrada,buffer,BUF_SIZE)) > 0 ){
write(salida,buffer,leidos);
}
close(salida);
close(entrada);
return 0;
}
What's wrong with my implementation?
I think you're missing the appropriate open flags on the output . Try:
salida = creat(argv[2], O_WRONLY | O_CREAT, 0644);
However, as comments suggest, you're probably getting errors indicated by the return values and/or the errno variable, which you are ignoring.
Also, I would avoid Castellano-specific variable names. Writing C/C++ requires knowing English anyway, so better stick to that for naming; otherwise - people who don't speak Castellano will have trouble understanding your code.
Finally - why are you doing it this way? There are much nicer C++-friendly, or even C-friendly, ways to copy a file - which would also be portable (your code isn't). See:
Copy a file in a sane, safe and efficient way
As #einpoklum stated, the main problem must be probably searched in the way you are opening your output file (flags and permissions). Overall, your code is far from implementing the minimum debugging verbosity and I think that a few code flow controls would help you a lot in detecting the real problem in your code:
#include <stdio.h>
#include <stdlib.h>
#ifndef BUF_SIZE
#define BUF_SIZE 200
#endif
int main(int argc, char *argv[])
{
int entrada = open(argv[1], O_RDONLY);
if (entrada == -1)
{
fprintf(stderr, "Error opening: %s\n", argv[1]);
exit(-1);
}
int openFlags = O_CREAT | O_WRONLY | O_TRUNC;
mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
int salida = open(argv[2], openFlags, filePerms);
if (salida == -1)
{
fprintf(stderr, "Error opening: %s\n", argv[2]);
exit(-1);
}
ssize_t numRead;
char buf[BUF_SIZE];
while ((numRead = read(entrada, buf, BUF_SIZE)) > 0)
{
if (write(salida, buf, numRead) != numRead)
{
fprintf(stderr, "Writing error!\n");
exit(-1);
}
}
if (numRead == -1)
{
fprintf(stderr, "Reading error!\n");
exit(-1);
}
if (close(entrada) == -1)
{
fprintf(stderr, "Input closing error!\n");
exit(-1);
}
if (close(salida) == -1)
{
fprintf(stderr, "Output closing error!\n");
exit(-1);
}
exit(0);
}
Many of the functions you use return values that can provide you an insight on that's going on. Use them.

create new file with system calls

Im trying to create a new file / overwrite an existing file using systemcalls , but for some reason I have two problems:
1. When I'm first running the program it exits with value 0, so it seems like it created the file successfully, but I can't see anything in my project directory.
then when I secondly running the program the file is created, but an error message is printed on the screen.
2. Also after the first iteration of the program, I can't see the prinf message at the end of the main function.
Thanks for helping.
int readFileDesc = 0, writeFiledesc = 0;
int sourceFile = 1, destFile = 2, bufferSize = 3, isOverwrite;
if (argc != 4 && argc != 5) {
printf("Invalid number of arguments\n");
printf("Usage:\n");
printf(" ex1 [-f] SOURCE DEST BUFFER_SIZE");
exit(EXIT_FAILURE);
}
//Checking if -f [OP] is activated.
isOverwrite = (strcmp(argv[1], "-f") == 0);
if (isOverwrite) {
sourceFile++;
destFile++;
bufferSize++;
}
//Opening the source file
readFileDesc = open(argv[sourceFile], O_RDONLY);
if (readFileDesc < 0) {
perror("Unable to open source file for reading: ");
exit(EXIT_FAILURE);
}
//opening the destination file
if (!isOverwrite) {
//Case we dont have the -f [op] so we create the file.
writeFiledesc = open(argv[destFile],
O_CREAT | O_EXCL | O_WRONLY ,
S_IRUSR | S_IWUSR);
if (writeFiledesc < 0) {
perror("Unable to open destination file for reading: ");
exit(EXIT_FAILURE);
}
} else {
//Case we have the -f [op] so we override existing file.
writeFiledesc = open(argv[destFile], O_RDONLY | O_WRONLY | O_TRUNC);
if (writeFiledesc < 0) {
perror("Unable to open destination file for writing: ");
exit(EXIT_FAILURE);
}
}
//Assume the buffersize is legal.
bufferSize = atoi(argv[bufferSize]);
char data[bufferSize];
int nread, nwrite;
while ((nread = read(readFileDesc, data, bufferSize)) > 0) {
if ((nwrite = write(writeFiledesc, data, nread)) != nread) {
printf("write problem: ");
}
}
// cant see this!
printf("File %s was copied to %s" , argv[sourceFile] , argv[destFile]);
//handling errors
close(sourceFile);
close(destFile);
return EXIT_SUCCESS;
}
This is wrong:
writeFiledesc = open(argv[destFile], O_RDONLY | O_WRONLY | O_TRUNC);
Using both O_RDONLY and O_WRONLY is wrong. You need to use O_RDWR.
Per the POSIX standard for open():
SYNOPSIS
#include <sys/stat.h> #include <fcntl.h>
int open(const char *path, int oflag, ...);
...
Values for oflag are constructed by a bitwise-inclusive OR of flags
from the following list, defined in . Applications shall
specify exactly one of the first five values (file access modes)
below in the value of oflag:
O_EXEC
Open for execute only (non-directory files). The result is unspecified if this flag is applied to a directory.
O_RDONLY
Open for reading only.
O_RDWR
Open for reading and writing. The result is undefined if this flag is applied to a FIFO.
O_SEARCH
Open directory for search only. The result is unspecified if this flag is applied to a non-directory file.
O_WRONLY
Open for writing only.
Any combination of the following may be used:
...
Also, read() and write() return ssize_t, not int.

Copying file fails, EBADF on closing output file descriptor

So I was following a little outdated book (2010) and I'm trying to copy a file with Linux system calls. This is what i have:
NOTE: Ignore the tlpi_hdr.h and error_functions.h, they define errExit() and fatal() and some otheres, they just print the error and exit.
#include <stdio.h>
#include <fcntl.h>
#include "lib/tlpi_hdr.h"
#include "lib/error_functions.h"
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
int main(int argc, char *argv[])
{
int inputFd, outputFd, openFlags;
mode_t filePerms;
ssize_t numRead;
char buf[BUF_SIZE];
if (argc != 3 || strcmp(argv[1], "--help") == 0) {
usageErr("%s old-file new-file\n", argv[0]);
}
inputFd = open(argv[1], O_RDONLY);
if (inputFd == -1) {
errExit("Opening file %s", argv[1]);
}
openFlags = O_CREAT | O_WRONLY | O_TRUNC;
filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
outputFd = open(argv[2], openFlags, filePerms);
if (outputFd == -1) {
errExit("Opening file for writing %s", argv[1]);
}
while ((numRead = read(inputFd, buf, BUF_SIZE)) > 0) {
if (write(outputFd, buf, numRead) != numRead))
fatal("I/O Error");
if (numRead == -1)
fatal("Reading error");
}
if (close(outputFd == -1))
errExit("close input");
if (close(inputFd == -1))
errExit("close output");
return EXIT_SUCCESS;
}
I'm failing on closing of the output file descriptor with EBADF Bad file descriptor:
thinkpad :: ~/.tlpi % ./cp.o a b
ERROR [EBADF Bad file descriptor] close output
The file copies fine tho:
thinkpad :: ~/.tlpi % sha1sum a
40a925a93e149ac53d2630cde8adeb63b8134b29 a
thinkpad :: ~/.tlpi % sha1sum b
40a925a93e149ac53d2630cde8adeb63b8134b29 b
thinkpad :: ~/.tlpi %
Why?
Let's take a closer look at your close call:
close(outputFd == -1)
Here you are comparing outputFd to the value -1. The result of that is a boolean value, which in C will be either 0 or 1. This happens to be either standard input or standard output, depending on the result. Not a file you descriptor you should close.
My guess is that you meant
if (close(outputFd) == -1)

Call system UNIX - File copy in C

I try to create a copy of a source file but the target file is always empty.
The algorithm is: read from STDIN and write to source file, then read on this file and write the text in target file.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFFSIZE 8192
int main(){
int fdsource, fdtarget;
int n, nr;
char buff[BUFFSIZE];
fdsource = open("source.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); // Create and open a source file in read/write
if (fdsource < 0){
printf("Source file open error!\n");
exit(1);
}
fdtarget = open("target.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); // Create and open a source file in write only
if (fdtarget < 0){
printf("Target file open error!\n");
exit(1);
}
printf("\nInsert text:\n");
while ((n = read(STDIN_FILENO, buff, BUFFSIZE)) > 0){ // Read from STDIN and write to source file
if ((write(fdsource, buff, n)) != n){
printf("Source file write error!\n");
exit(1);
}
}
while ((read(fdsource, buff, n)) > 0){ // Read from source file and write to target file
if ((write(fdtarget, buff, n)) != n){
printf("Source file open error!\n");
exit(1);
}
}
close(fdsource);
close(fdtarget);
exit(0);
return 0;
}
The problem with your code is "You have opened both the file in initial stage". To solve the problem just open the source file in the write mode and write all the data, then close and reopen the source file in read mode, Then open the target file in the write mode.
The modified code is given below and it was not tested
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFFSIZE 8192
int main(){
int fdsource, fdtarget;
int n;
char buff[BUFFSIZE];
fdsource = open("source.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); // Create and open a source file in read/write
if (fdsource < 0){
printf("Source file open error!\n");
exit(1);
}
printf("\nInsert text:\n");
while ((n = read(STDIN_FILENO, buff, BUFFSIZE)) > 0){ // Read from STDIN and write to source file
if ((write(fdsource, buff, n)) != n){
printf("Source file write error!\n");
exit(1);
}
}
close(fdsource);
fdsource = open("source.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); // Create and open a source file in read/write
if (fdsource < 0){
printf("Source file open error!\n");
exit(1);
}
fdtarget = open("target.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); // Create and open a source file in write only
if (fdtarget < 0){
printf("Target file open error!\n");
exit(1);
}
while ((read(fdsource, buff, n)) > 0){ // Read from source file and write to target file
if ((write(fdtarget, buff, n)) != n){
printf("Source file open error!\n");
exit(1);
}
}
close(fdsource);
close(fdtarget);
exit(0);
return 0;
}
If am wrong anywhere use the logic mentioned above.

What is the default mode for open() calls with O_CREAT and how to properly set it while opening/creating files

I am trying to recreate the basic functionality of fopen() using the I/O system calls. I am somehow suppose to "set the default mode for open() calls with O_CREAT" however am unsure how to go about this. It's not perfect but this is what I've got so far.
MYFILE * myfopen(const char * path, const char * mode){
MYFILE *fp = (MYFILE *)malloc(sizeof(MYFILE)); //EDITED
int fd;
switch(mode[0]){
case 'r':
fd=open(path, O_RDONLY | O_CREAT, 0440);
break;
case 'w':
fd=open(path, O_WRONLY | O_CREAT | O_TRUNC, 0220);
break;
default:
fd=open(path, O_RDWR | O_CREAT | O_TRUNC, 0660);
}
if(fd < 0){
return NULL;
}
fp->fileD=fd;
fp->offset=0;
return fp;
}
fileD will be the file descriptor returned by the open call. I think the rest is self-explanatory.
It compiles but I'm getting a "segmentation fault" error when I try to run it. This function also fails to open a new file and associate a file descriptor to it.
I think the segmentation error might be somewhere in here:
int myfputc(int c, MYFILE * fp){
if(write(fp->fileD, &c, 1) == -1){
return 1;
}
++fp->offset; //how to gain access to the current offset of the stream?
return 0;
}
Where I'm trying to recreate fputc.
Here is the MYFILE struct:
typedef struct {
int fileD; // descriptor
int bufferSz; // buffer size
int bufferCh; // # of bytes in stream
int offset; //current offset position
int errorF; // error flag
int EOFF; // EOF flag
} MYFILE;
The file permissions should probably be 0644, or maybe 0666 (or maybe 0640/0660 to deny others access while allowing your group access), regardless of whether you're creating the file for reading or writing. You should not normally include execute permission (and you don't). I'd be willing to support fewer permissions for group (no write for group seems good to me). You can even make a file readonly for every other process while the current process has write permission with 0444 or tighter permissions. But the standard will use 0666 and let the umask remove permissions.
You might note that your code leaks if you fail to open the file. You should free(fp); before the return on the error path.
Note that you have not set all the fields in your structure, and neither has malloc(), so you have random junk in those fields. Curiously, there isn't a buffer in sight, even though there's a buffer size.
This code works for me. It cleans up, marginally, your myfopen() function, but otherwise, it runs without crashing. I think your problem is in other code.
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
typedef struct
{
int fileD; // descriptor
int bufferSz; // buffer size
int bufferCh; // # of bytes in stream
int offset; // current offset position
int errorF; // error flag
int EOFF; // EOF flag
} MYFILE;
static
MYFILE *myfopen(const char *path, const char *mode)
{
MYFILE *fp = (MYFILE *)malloc(sizeof(*fp));
int fd;
switch (mode[0])
{
case 'r':
fd = open(path, O_RDONLY | O_CREAT, 0640);
break;
case 'w':
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
break;
default:
fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0640);
break;
}
if (fd < 0)
{
free(fp);
return NULL;
}
fp->fileD = fd;
fp->offset = 0;
fp->bufferSz = 0;
fp->bufferCh = 0;
fp->errorF = 0;
fp->EOFF = 0;
return fp;
}
static
int myfputc(int c, MYFILE *fp)
{
if (write(fp->fileD, &c, 1) == -1)
{
return 1;
}
++fp->offset; // how to gain access to the current offset of the stream?
return 0;
}
int main(void)
{
MYFILE *fp = myfopen("./test.txt", "w");
if (fp != 0)
{
const char *src = "The text!\n";
while (*src != '\0')
myfputc(*src++, fp);
}
return 0;
}
Result:
$ ls -l test.txt
-rw-r----- 1 jleffler staff 10 Feb 15 19:11 test.txt
$ cat test.txt
The text!
$

Resources