I am having this code in which I am getting BAD FILE DESCRIPTOR problem at the read system call. However my write call with the same file descriptor is working fine. Please suggest
void Update_Log( )
{
struct logDetails update,update1[30];
struct stat fileData,fileData1;
int file;
int index;
//pthread_t pid;
char writeBuffer[MAX_BUFFER_SIZE];
char readBuffer[MAX_BUFFER_SIZE];
char mBuf[MAX_BUFFER_SIZE],mBuf1[MAX_BUFFER_SIZE];
if((access("/home/team02/DMS/Server/",F_OK))==0) //checking the file/dir existence
puts("file found");
else
puts("file not found");
if((file=open("/home/team02/DMS/Server/filename.txt",O_RDONLY|O_WRONLY|O_APPEND,S_IRWXU))==-1)
perror("file not opened");
if((fstat(file, &fileData))==-1)
perror("structure not filled");
if((stat("/home/team02/DMS/Server/f1",&fileData1))==-1)
perror("structure not filled");
//printf("%d/n",fileData.st_mtime);
//printf("%d",fileData.st_ctime);
struct tm *mytm = localtime(&fileData.st_mtime);
struct tm *mytime=localtime(&fileData1.st_mtime);
strftime(mBuf1,18,"%I:%M:%S-%m%d%y",mytime);
strftime(mBuf, 18, "%I:%M:%S-%m/%d/%y", mytm);
puts(mBuf);
if((strcmp(mBuf,mBuf1)==0))
puts("equal");
else
puts("not equal");
strcpy(update.timestamp,mBuf);
strcpy(update.clientName,mBuf);
strcpy(update.filename,mBuf1);
snprintf(writeBuffer,MAX_BUFFER_SIZE,"%s %s %s",update.clientName,update.filename,update.timestamp);
//printf("%s",writeBuffer);
//if((pthread_create(&pid,&thread_handler,NULL))!=0)
//perror("Thread not created");
if((write(file,writeBuffer,strlen(writeBuffer)))==-1)
perror("write unsuccessful");
**if((read(file,readBuffer,MAX_BUFFER_SIZE))==-1)
perror("read unsuccessful");**
for(index=0;index<strlen(readBuffer);index++)
{
sscanf(readBuffer,"%s %s %s",update1[index].clientName,update1[index].filename,update1[index].timestamp);
printf("%s",update1[index].clientName);
}
close(file);
}
Depending on the run time library, the open mode O_RDONLY|O_WRONLY may be problematic. You probably want O_RDWR to replace that part.
Also, you can get the errno value to find out exactly what the problem is. You are calling perror() in the case of an error. That should be telling you what the issue is. What output does the program generate?
Related
//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.
I'm writing a server with a client and I'm having issues transferring images. I tried to fread the file on a buffer, to send the buffer to the client and to fwrite the buffer on a new file and it worked! Now it doesn't work anymore and I don't know why, when I check the new file, my image opener says that it's impossible to open the JPEG file etc.
My reading code:
int fd=open(pathname, O_RDONLY, 0666);
struct stat fileStat;
if(fstat(fd,&fileStat) < 0)
{
perror("\nfilestat\n");
exit(-1);
}
int fileSize=(int)fileStat.st_size;
//printf("File Size: \t\t%d bytes\n",fileSize);
FILE *f=fdopen(fd, "rb");
if(f==NULL)
{
perror("\nfopen\n");
exit(-1);
}
void *buf=malloc(fileSize);
if(buf==NULL)
{
perror("\nmalloc\n");
return -1;
}
int FR=fread(buf, fileSize, 1, f);
if(FR<0)
{
perror("\nfread\n");
exit(-1);
}
Then I write the body on my server message:
punt+=sprintf(punt, "%s\r\n", (char *)buf);
And after the client has extracted it from the received message, I fwrite it on a new file:
char *clientfile="./qui.jpg";
int fdbis=open(clientfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if(fdbis<=0)
{
perror("\nopen 2\n");
exit(-1);
}
FILE *fbis=fdopen(fdbis, "wb");
if(fbis==NULL)
{
perror("fdopen");
exit(-1);
}
int WR=fwrite((void*)buf, strlen(buf), 1, fbis);
if(WR<=0)
{
perror("\nfwrite\n");
exit(-1);
}
I'm not pasting my server-client code because the code above doesn't work either on a test program without sending/receiving and without string extraction, so the problem has to be in it.
I'm programming in C, with a Posix system, and compiling with gcc.
Thank you for your attention.
Since a jpeg file is binary, you cannot use string function to manipulate it.
strlen(buf) will return the length till the first null termination.
use memcpy.
I am working on a program in C that involves client-server connections and communication between the two parties.
The program involves the client sending a letter to the server and the server getting the letter. The server then searches through the current file directory (in linux) for a file beginning with that letter and sends the client the number of bytes of the file and the text of the file.
The overall program is very long and for the assignment the instructor already did much of the code such as setting up the sockets and creating the entire program for the client side of operations.
For the server side I had to write code for:
getting the file descriptor from the passed memory and casting it
-getting the letter from the client
-Attempting to open the current directory
-Iterating through the directory looking for a file that starts with the letter
-Attempting to open the file and sending the size of the file and number of bytes of file to the client in network endian
-Closing the file and directory after finishing
-Error checking: there are error checking statements if the directory cannot be opened, the file cannot be opened, or no matching file is found
The following is my code with comments
void* handleClient (void* vPtr
)
{
// I. Application validity check:
int fd = *((int *) vPtr);
//casting vPtr to an int//
free(vPtr);
// II. Handle the client:
char buffer[BUFFER_LEN+1];
read(fd, buffer, BUFFER_LEN+1);
//read the letter into a buffer//
const char* dirNamePtr = ".";
DIR* dirPtr = opendir(dirNamePtr);
// Open the current directory
if (dirPtr == NULL)
{
int toSend = htonl(CANT_READ_DIR_CODE);
write(fd,&toSend,sizeof(toSend));
printf("Cannot read directory\n");
return(NULL);
}
// If current directory cannot be opened, it sends a error message in network // endian to the client
struct dirent* entryPtr;
char path[BUFFER_LEN];
struct stat statBuffer;
//implements struct dirent to get info on the directory
//iterates through the directory
while ((entryPtr=readdir(dirPtr)) != NULL)
{
stat(entryPtr->d_name, &statBuffer);
//puts in metaddata of the current directory into statbuffer
if (!S_ISREG(statBuffer.st_mode))
continue;
//if the entry is not a file, continue
// if the first letter of the file is not the character received from the //client, send an error mesage
if(entryPtr->d_name[0]!=buffer[0]) {
int toSend2 = htonl(NO_MATCH_CODE);
write(fd,&toSend2,sizeof(toSend2));
printf("No matching file\n");
return(NULL);
}
int ab;
int numRead;
int numBytes;
char buffer[BUFFER_LEN];
//open the file and send bytes of file and file size to client
if (entryPtr->d_name[0]==buffer[0] &(S_ISREG(statBuffer.st_mode)))
{
ab=open(entryPtr->d_name,O_RDONLY,0660);
if(ab<0) {
int toSend3 = htonl(CANT_READ_FILE_CODE);
write(fd,&toSend3, sizeof(toSend3));
printf("Cannot read <filename>\n");
return(NULL);
}
numBytes=htonl(statBuffer.st_size);
write(fd, &numBytes, sizeof(numBytes));
printf("Sending %s, %d bytes\n",entryPtr >d_name,statBuffer.st_size);
while((numBytes=read(ab,buffer,BUFFER_LEN))>0)
{
printf("We read %d bytes\n", numBytes);
write(fd, buffer, numBytes);
}
//close the fiel
close(ab);
}
break;
//leave the loop
}
// III. Finished:
//
closedir(dirPtr);
return(NULL);
}
My code compiles but does not send the file to the client when I try running it. I have tried several different letters and it has not worked for any of them. I do not quite know what the issue is which makes it difficult to fix my mistakes.
I am not asking for the answer or anything, just help in seeing where I am wrong. I appreciate any help.
Your logic for when to send vs. when to send no-file status seems wrong. I think it should be like this (fair warning, I didn't test this, or even compile it beyond basic syntax checking, but you should get the idea):
void* handleClient(void* vPtr)
{
// I. Application validity check:
int fd = *((int *) vPtr);
free(vPtr);
// II. Handle the client:
char buffer[BUFFER_LEN+1];
read(fd, buffer, BUFFER_LEN+1);
//read the letter into a buffer//
const char* dirNamePtr = ".";
DIR* dirPtr = opendir(dirNamePtr);
// Open the current directory
if (dirPtr == NULL)
{
int toSend = htonl(CANT_READ_DIR_CODE);
write(fd,&toSend,sizeof(toSend));
printf("Cannot read directory\n");
return(NULL);
}
struct dirent* entryPtr;
char path[BUFFER_LEN];
struct stat statBuffer;
//implements struct dirent to get info on the directory
//iterates through the directory
while ((entryPtr=readdir(dirPtr)) != NULL)
{
stat(entryPtr->d_name, &statBuffer);
//puts in metaddata of the current directory into statbuffer
// if this isn't a regular file OR the first char doesn't match...
if (!S_ISREG(statBuffer.st_mode) || entryPtr->d_name[0]!=buffer[0])
continue;
int ab;
int numRead;
int numBytes;
char buffer[BUFFER_LEN];
//open the file and send bytes of file and file size to client
ab = open(entryPtr->d_name,O_RDONLY,0660);
if(ab<0) {
int toSend3 = htonl(CANT_READ_FILE_CODE);
write(fd,&toSend3, sizeof(toSend3));
printf("Cannot read <filename>\n");
closedir(dirPtr);
return(NULL);
}
numBytes=htonl(statBuffer.st_size);
write(fd, &numBytes, sizeof(numBytes));
printf("Sending %s, %d bytes\n",entryPtr >d_name,statBuffer.st_size);
while((numBytes=read(ab,buffer,BUFFER_LEN))>0)
{
printf("We read %d bytes\n", numBytes);
write(fd, buffer, numBytes);
}
//close the file and leave
close(ab);
break;
}
// if this is NULL it means we dind't send anything. we break the loop
// when a file to send it discovered.
if (entryPtr == NULL)
{
printf("No matching file\n");
int toSend2 = htonl(NO_MATCH_CODE);
write(fd, &toSend2, sizeof(toSend2));
}
// III. Finished:
closedir(dirPtr);
return(NULL);
}
I am using the open function like this in my file to get some coordinates from a file :
t_coo *get_buffer(char **av, t_coo **head)
{
int ret;
int fd;
char *line;
int y;
t_coo *cur;
cur = NULL;
*head = NULL;
y = 0;
ret = 0;
fd = open(av[1], O_RDONLY);
while ((ret = get_next_line(fd, &line) > 0))
{
head = get_map(line, head, y);
y++;
}
close(fd);
cur = *head;
return (cur);
}
It is working perfectly but the problem is when I try to make it open a directory, my program segfault. I want to protect it against directory opening so that I dont segault anymore. I tried to look at the flags on the internet and tried many of them but I could not find this one. Can anybody tell me which one it is? Thank you.
You need to use the lstat function to tell you whether the given file name represents a regular file or a directory.
struct stat statbuf;
int rval;
rval = lstat(argv[1], &statbuf);
if (rval == -1) {
perror("error getting file status");
exit(1);
}
if (S_ISREG(statbuf.st_mode)) {
printf("%s is a regular file\n", argv[1]);
} else if (S_ISDIR(statbuf.st_mode)) {
printf("%s is a directory\n", argv[1]);
} else {
printf("%s is something else\n", argv[1]);
}
I would suggest to open the file (which could be a directory) so get a file descriptor, then use fstat(2) on that file descriptor (and check the result of fstat by using statresult.st_mode & S_IFMT == S_IFDIR ...)
This would avoid an (improbable) race condition with the lstat (or stat) then open approach (suggested in Dbush's answer): some other process might (with very bad luck) remove or rename the file between these two system calls. You might also opendir or else open (but that also suffers from a similar race condition).
PS. The race conditions I am suggesting here are so improbable that we can normally ignore them... But they might be a security flaw (than an attacker could use)
code:
int main(int argc, char **argv)
{
int fd = open("test.txt", O_CREAT|O_RDWR, 0200|0400);
if(fd == -1)
{
printf("failure to oepn");
exit(-1);
}
int iRet = write(fd, "aaaaaaaaaa", 10);
if(iRet == -1)
{
printf("failure to writer");
exit(-1);
}
sleep(10);
printf("You must remove");
iRet = write(fd, "bbbbbbbbbb", 10);
if(iRet == -1)
{
printf("failure to after writer");
exit(-1);
}
exit(0);
}
during the sleep(), you delete the test.txt, but the process write successful!why?
if a log ”Singleton“ instance, you remove the file on the disk.write is successful, but you can get nothing.
class log
{
public:
void loggerWriter(std::string str);
int fd;
};
log::log(std::string filename):fd(-1)
{
fd = open(filename.c_str(), O_CREAT|)
//...
}
log::loggerWriter(std::string str)
{
writer(fd, str.c_str(), str.size());
}
int main()
{
log logger("text.txt");
//...
//I want to know the text.txt the text.txt have delete on the disk or not.
//if delete i can create another file to log.
}
"unlink" cann't solve this problem.
The manual page for unlink(2) states clearly:
unlink() deletes a name from the file system. If that name was the
last link to a file and no processes have the file open the file is
deleted and the space it was using is made available for reuse.
If the name was the last link to a file but any processes still have
the file open the file will remain in existence until the last file
descriptor referring to it is closed.
As caf excellently notes in the comments:
The write() is successful because it writes to the file, which still
exists at this point even though it no longer has a name. The filename
and the file itself are distinct, and have separate lifetimes.