Suppose I am asked to output an error if a certain file exist.
for example
I am asked to create a file called "del.txt", however, I have to check if such file exist first, and if it does I have to output an error of code 2.
So I know I have to use the O_EXCL to check if the file exist or not, and if it does I should give an error. however the error code is undefined, but I want to set it to 2.
Any idea how?
Here is my current code:
char *filename = "del.txt";
int n;
if((n = open(filename, O_EXCL) > 0){
perror(filename);
exit(1);
};
I am currently getting this:
del.txt: Undefined error: 0
The error check should be < 0, not > 0, the flags are missing an access mode (O_RDONLY/O_WRONLY/O_RDWR), and an O_CREAT needs to be used with O_EXCL (or else, POSIX says, the behavior is undefiend).
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
char const *filename = "del.txt";
int n;
if((n = open(filename, O_RDONLY|O_CREAT|O_EXCL) < 0)){
perror(filename);
exit(1);
};
}
Related
I tried to use the system call lseek() to get back the beginning of a file or reach the end of the file.
The exact code I used is:
int location = lseek(fd, 0, SEEK_SET) //get back to the beginning
int location = lseek(fd, 0, SEEK_END) //reach to the end
However, after the file location has been reset, whenever I tried to use read(), the return value of read() is always set to -1, which means something was wrong. Furthermore, the errno message I got was Bad file descriptor. Does anyone know what should I do?
PS: I tried to close and reopen the file to help me get back to the beginning of the file and it worked. But I have no ideas on how should I get to the end of the file and read the entire file in the reverse order without using lseek().
Plus: a reproducible example would be:
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
int fd;
char buffer[1000];
fd = creat("newFile", 0777);
memset(buffer, 'a', 500);
write(fd, buffer, 500); // fill up
int location = lseek(fd, 0, SEEK_SET); //get back to the beginning
int read_bytes = read(fd, buffer, 500);
// this should return the bytes it reads but it actually returns -1
printf("%d\n", read_bytes);
return 0;
}
The creat function does not allow you to read from the file. It only allows you to write to it.
From creat(2):
creat()
A call to creat() is equivalent to calling open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC.
The important part here is O_WRONLY. That means "write only".
If you want to open the file (and create it) for reading and writing, then you can use open like so:
int fd = open("newFile", O_CREAT|O_RDWR|O_TRUNC, 0777);
The important part here is O_RDWR. That means "read and write".
If you want to have open give an error if the file already exists, add the O_EXCL flag; this causes -1 to be returned and errno to be set to EEXIST if the file already exists when you try to create it.
The following proposed code:
cleanly compiles
properly declares the variable types
properly creates the file
properly includes the needed header files
properly checks for error indications from C library functions (and properly handles any error)
And now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
int fd;
char buffer[1000];
// fd = creat("newFile", 0777);
fd = open("newFile", O_CREAT|O_RDWR|O_TRUNC, 0777);
if( fd < 0 )
{
perror( "open failed" );
exit( EXIT_FAILURE );
}
memset(buffer, 'a', 500);
write(fd, buffer, 500); // fill up
off_t location = lseek(fd, 0, SEEK_SET); //get back to the beginning
printf( "%ld\n", location );
ssize_t read_bytes = read(fd, buffer, 500);
if( read_bytes < 0 )
{
perror( "read failed" );
exit( EXIT_FAILURE );
}
// this should return the bytes it reads but it actually returns -1
printf("%ld\n", read_bytes);
return 0;
}
A run of the program results in:
0
500
Suggest reading/understanding the MAN pages for any C library functions your code uses
I need to find the name of a file using * in a C program. There is exactly 1 file in the specific folder that has the extension .UBX. I can do this in terminal but it doesn't work in C. Can anyone give me example code to do this?
//There is exactly 1 file that ends in .UBX
#define FILE_TO_SEND "/home/root/logs/*.UBX"
fd = open(FILE_TO_SEND, O_RDONLY);
This should do the trick:
#include <glob.h>
#include <stdlib.h>
#include <fcntl.h>
#define FILE_TO_SEND "/home/root/logs/*.UBX"
int
main (void)
{
glob_t globbuf;
glob(FILE_TO_SEND, 0, NULL, &globbuf);
if (globbuf.gl_pathc > 0)
{
int fd = open(globbuf.gl_pathv[0], O_RDONLY);
// ...
}
globfree(&globbuf);
return 0;
}
I am attempting to open files and append to them using C. I am dynamically naming the directory based on process Id and creating the filenames based on the "room" that has been randomly selected in the loop. My intention is to open the file, append the room name into the file, and then close the file and move to the next room and perform the same function. The issue I am having is with "open". It seems to only be returning -1, which indicates an error. The error message is stating "Permission denied". I am confused by this because I appear to be setting the proper permissions in the open function. I tried using fopen(), but that kept producing a segmentation fault 11. Is there an issue with my roomFilePath declaration and usage or is my usage of open incorrect? Here is the portion of the code that contains the issue. The makeRooms() function is where I check to see if the file was opened correctly. Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#define NUM_ROOMS 10
#define NUM_USED_ROOMS 7
#define MAX_CONNECTIONS 6
time_t t;
char* usedRooms[NUM_USED_ROOMS];
int i;
char directoryName[100];
char* baseDirectory = "walterer.rooms.";
int processId;
char roomFilePath[75];
int adjacencyMatrix[7][7] = {0};
int useableConnections;
int e;
int totConnections = 0;
int openRoom;
int file_descriptor;
char* roomNames[] = {
"cleveland",
"columbus",
"dallas",
"toledo",
"miami",
"sarasota",
"boston",
"chicago",
"denver",
"phoenix"
};
int connections[10] = {
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
};
void makeDirectory() {
processId = getpid();
sprintf(directoryName, "%s%d", baseDirectory,processId);
//printf("%s\n", directoryName);
mkdir(directoryName, 777);
}
void makeRooms() {
/* Initializes random number generator */
srand((unsigned) time(&t));
/* Create 7 rooms */
for(i = 0; i < NUM_USED_ROOMS; ){
/* Generate random number between 0 to 10 */
int randomNumber = rand() % NUM_ROOMS;
/* Loop as long the array does not contain any connections at the index */
while(connections[randomNumber] == 0) {
/* Append the room path to the end of my ONID path */
sprintf(roomFilePath,"%s/%s", directoryName, roomNames[randomNumber]);
printf("%s\n",roomFilePath);
/* Create file */
FILE *filePointer;
/* Open file to append*/
//filePointer = open(roomFilePath, O_WRONLY | O_CREAT, 0600);
//!!!Returning -1
file_descriptor = open(roomFilePath, O_APPEND, 0600);
printf("%d\n",file_descriptor);
if (file_descriptor == -1)
{
printf("open() failed on \"%s\"\n", roomFilePath);
perror("In createRooms()");
exit(1);
}
/*if (filePointer == NULL)
{
fprintf(stderr, "Error Creating File\n");
printf("something went wrong with read()! %s\n", strerror(errno));
}*/
/* Print the room name in the file */
/* SEG FAULT HERE!!!! */
fprintf(filePointer, "ROOM NAME: %s\n", roomNames[randomNumber]);
/* Close the file */
//fclose(filePointer);
usedRooms[i] = roomNames[randomNumber];
connections[randomNumber] = 1;
//printf("Room %d is %s \n", i+1, roomNames[randomNumber]);
i++;
}
}
}
First, you're missing part of the required flags argument to open() in this line:
file_descriptor = open(roomFilePath, O_APPEND, 0600);
The only open() flag you're passing is O_APPEND, but open() also requires at least one of the O_RDONLY, O_WRONLY, O_RDWR, O_EXEC, or O_SEARCH flags. (the last two are rarely used.)
Your code should be something like
file_descriptor = open(roomFilePath, O_RDONLY | O_APPEND, 0600);
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 <fcntl.h>. 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.
In your posted code, of course you get a segmentation fault at this line:
/* SEG FAULT HERE!!!! */
fprintf(filePointer, "ROOM NAME: %s\n", roomNames[randomNumber]);
The filePointer variable has not been initialized in your posted code, so using the value causes a segmentation fault.
I created a file named "test" but I'm unable to open it using fopen.
Here is the code-
#include<stdio.h>
int main()
{
FILE *fp;
fp=fopen("test.txt","r");
if(fp==NULL)
{
perror("Error: ");
}
fclose(fp);
return 0;
}
When I run the above code, I get the following output:
Error: Invalid argument
What could be the reason? When does perror return "Invalid argument" error message?
Have a look at man fopen:
EINVAL The mode provided to fopen(), fdopen(), or freopen() was invalid.
Probably test.txt is not readable.
Try compiling with -g. This lets you use gdb to debug the program step by step; look up how to use it. Probably a better way of doing this is with stat(2). Here is a sample of code that will return an error if the file does not exist, or is not a regular file:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
struct stat s;
int check = stat("test.txt", &s);
if(check != 0){
printf("ERROR: File does not exist!\n");
return -1;
}
return 0;
}
Stat stores a lot of information about a file (such as lenght, type, etc.) in the struct stat, which in this case is named "s". It also returns an integer value, which is non-zero if the file does not exist.
I'm currently learning the C language in college so this is a homework assignment but I have a small problem. I'm guessing I've just misjudged the syntax or are missing something really obvious. My compiler is telling me that there is:
expected declaration specifiers or "..." before constant
and pointing to the O_RDWR.
I've googled and searched on Stack Exchange but there doesn't seem anything specific to it. Following the syntax in a C reference it's fine. I've looked around and it says I have not predefined the typedef but I've tried that to no avail.
I've starred the section that is causing the problem according to the compiler with **
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
int count;
printf ("This program was called \"%s\".\n",argv[0]);
if (argc > 1)
{
for (count = 1; count < argc; count++)
{
printf("argv[%d] = %s\n", count, argv[count]);
}
}
else
{
printf("The command had no arguments.\n");
}
if (argc == 4)
{
printf("There are the correct number of arguments(4)");
}
else
{
printf("Not enough arguments! please try again");
}
**int open(const char *argv[1], O_RDWR);
return 0;**
}
int open(const char *argv[1], O_RDWR);
What are you trying to do by this statement? Compiler treats this as function declaration, not function call. And it fails because O_RDWR is not a type name. If you need to call open(), syntax shall be like this:
int fd = open(argv[1], O_RDWR);
if(fd != -1)
{
// File opened OK. Proceed with file operations.
}
else
{
// File failed to open. Handle error occured
}
Try open(argv[1], O_RDWR); - you don't need to specify the arg's type or the return value.
... and I'm assuming the **'s are just to highlight the problem area - if not, they should go too... edit: just noticed you said that in the question!
The open call returns a HANDLE to the specified file of type int. So you only have to declare an int type HANDLE to collect from open. So,
int FileDesc ;
FileDesc = open( argv[1], O_RDWRD ) ;
// Check for Errors here