open() and write() functions in C - c

I'm trying to write in a .txt file the content of the variable environ.
int archivo = open(argv[1], "rw");
int i=0;
while(environ[i]!=NULL){
write(archivo, environ[i], 1024);
i++;
}
The file is created but no content is added. Does anyone know why?

consult man 2 open to get the right arguments for open. It should be:
open(argv[1], O_WRONLY | O_CREAT | O_TRUNC);
You should only write ad much as you actually have:
write(archivo, environ[i], strlen(environ[i]));
You have to make sure that what you wrote actually left the buffer:
size_t string_length = strlen(environ[i]);
size_t wrote = 0;
while (wrote < string_length) {
size_t bytes_wrote = write(archivo, environ[i] + wrote, string_length - wrote);
if (bytes_wrote >= 0)
wrote += bytes_wrote;
else {
perror("write");
abort();
}
}
write does not guarantee that all that you submit will be written.
Ideally you should look for the far more programmer friendly stdio calls fopen and fwrite.
FILE * fp = fopen(argv[1], "w");
// loop i
if (!fwrite(environ[i], strlen(environ[i]), 1, fp)) {
perror("fwrite");
abort();
}

I believe you've got to change your flags for opening a file. "rw" isn't for open(), it is for fopen().
open(argv[1], O_WRONLY);
I think is the minimum required for writing to a file using open
EDIT: I found a link http://pubs.opengroup.org/onlinepubs/009696899/functions/open.html

Related

When I program in Linux using C, I use the open or creat functions and end up behaving differently

//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.

How can I detect that I open()ed a directory in C, without using stat()?

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
}

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.

Program doesn't write on the standard output and gets stuck instead

I'm writing this software that should open a file, that must be passed as an argument, and write the content of the file on the standard output using the open and write system calls. (It's a bit like the cat command)
The problem is that once I run the program as
./a.out /example/pattern/file
it writes on the standard output the pattern of the file and then it gets stuck, without writing anything or terminating, allowing me even to write on the terminal.
I've tried using the ddd debugger, but I wasn't able to find the problem.
All the necessary headers are included.
int main(int argc,char * argv[]){
printf("%s\n", argv[1]);
int fd, lung;
char buf[10];
if(fd = open(argv[1], O_RDONLY)==-1){
perror("argv[1], in apertura");
exit(EXIT_FAILURE);
}
while(lung = read(fd,buf,10)>0){
if( (write(1, buf, lung))==-1) perror("error");
}
if (lung==-1) {perror("error");exit(EXIT_FAILURE);}
fflush(NULL);
close(fd);
return 0;
}
Isn't that suspicious?
if(fd = open(argv[1], O_RDONLY)==-1) {
According to operator precedence, == will be executed before =.
Then:
while(lung = read(fd,buf,10)>0){
will similarly suffer from > been executed before =.
Tip: When in doubt, use parentheses! ;)
while(lung = read(fd,buf,10)>0){
if( (write(1, buf, lung))==-1) perror("error");
}
is the same as (due to operator precedence ):
while(lung = (read(fd,buf,10)>0) ){
if( (write(1, buf, lung))==-1) perror("error");
}
The value of lung will be either 1 or 0. When it is 0, the loop will break When it is 1, only 1 character will be written to stdout.
What you need is:
while( (lung = read(fd,buf,10)) > 0 ){

Cannot simulate the write() system call in C

I have written the following code to simulate the write() system call in C.
The program executes without errors, but the new content is not written to myfile.
What is the problem?
#include<stdio.h>
int main(int ac, char* av[])
{
int fd;
int i = 1;
char *sep = "";
if(ac < 1)
{
printf("Insuff arguments\n");
exit(1);
}
if((fd = open("myfile", 0660)) == -1)
{
printf("Cannot open file");
exit(1);
}
while(i<ac)
{
write(fd, av[i], strlen(av[i]));
write(fd, sep, strlen(sep));
i++;
}
close (fd);
}
you should check the return value of write and see what's going on with perror (for exemple),
anyway you are not calling open in the correct way
try
if ((fd=open("myfile", O_WRONLY | O_CREAT, 0660))==-1)
{
printf("Cannot open file");
exit(1);
}
while(i<ac)
{
write(fd,av[i],strlen(av[i])); //check the return value of write
write(fd,sep,strlen(sep));
perror("write");
i++;
}
close (fd);
and include unistd.h fcntl.h
You need to specify mode(read or write) of the open when you are opening a file. In your open call you didn't specify any mode and you are giving file permission flags. For more information refer manual page of open system call.
You can try this in open call
fd=open("myfile", O_WRONLY | O_CREAT, 0660);
check return value of your write call, it is failing because you didn't specify any mode and you are trying to write data in to that file.

Resources