Thread: What mean filedescriptor error-codes?

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    26

    What mean filedescriptor error-codes?

    Hi,
    I have written the following code:
    Code:
    #include <stdio.h>
    
    int main(void) {
    
            char *myfile = "/home/username/Desktop/testfile";
            FILE *fd;
     
            fd=fopen(myfile, "r");
            printf("%i\n",fd);
            fclose(fd);
            return 0;
    
    }
    Executed I get this here: 134520840, which looks like a valid filedescriptor.

    If I try now the same with syscalls:
    Code:
    #include </usr/include/linux/unistd.h>
    #include <stdio.h>
    
    int main(void) {
    
            char *myfile = "/home/username/Desktop/testfile";
            int fd;
    
            fd = syscall(__NR_open,myfile,"O_RDONLY") ;
            printf("%i\n",fd);
      
            return 0;
    }
    I always get -1 and if I use &myfile in the syscall I get 3 ? What are -1 and 3 meaning?

    Can someone see the mistake in my second code?

    bye

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Executed I get this here: 134520840, which looks like a valid filedescriptor.
    It isn't, it's just a pointer mushed into an integer.

    I'd be surprised if the flags were passed as a string, and not as a direct copy of the flags passed to the regular open() call at the API level.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    26
    okay I did so now like I would do the same in assembler:
    Code:
    fd = syscall(__NR_open,myfile,00,04000) ;
    in asm I do this an it works:
    Code:
    	mov eax,5
            mov ebx, myfile
    	mov ecx,00
    	mov edx,04000
    	int 80h
    But in my C-code I now always get 3 printed out, which is an error-code or? 3 is no pointer to a filedescriptor..

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    3 sounds like a perfectly valid file descriptor to me.
    0 being stdin
    1 being stdout
    2 being stderr
    3 being the next lowest available integer for a file descriptor.

    I'll say it again so you're clear, a FILE* is NOT the same thing as a file descriptor. It is a file handle.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    26
    Ahh thank you I thought FILE would be a fd type or something like this. 3 was really the correct fd. This here is working fine for me:
    Code:
    #include </usr/include/linux/unistd.h>
    #include <string.h>
    
    int main(void) {
    
            char *myfile = "testfile",buffer[100];
            int fd;
    
            fd = syscall(__NR_open,myfile,00,04000) ;
            syscall(__NR_read,fd,buffer,100);
            syscall(__NR_write,1,&buffer,strlen(buffer));
        
            return 0;
    }
    But I have one last question. The syscall_write expects:
    eax 4
    ebx Device descriptor.
    ecx Pointer to the buffer containing the data to be written.
    edx Number of bytes to be written.
    A pointer is an adress pointing to the value of a variable. Now the &buffer above in my code snippet gives us the adress where the content of buffer starts on the stack. But why is buffer without the & also working exactly the same way? So the code above also works without the & before the buffer in the syscall_write?

    And why is *buffer not working? I mean k buffer is no pointer typ or, but at least a compiler-error should be given for using it as such or?

    greets

  6. #6
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by lilcoder View Post
    I mean k buffer is no pointer typ or, but at least a compiler-error should be given for using it as such or?
    The name of an array becomes a pointer to it's first element -> buffer is a pointer to char -> *buffer is the same as buffer[0] -> not a pointer -> compile error
    Kurt

  7. #7
    Registered User
    Join Date
    Sep 2007
    Posts
    26
    Quote Originally Posted by ZuK View Post
    The name of an array becomes a pointer to it's first element
    Ahh so buffer and &buffer are exactly the same? Because also &buffer points to the first element of this char array.

    Quote Originally Posted by ZuK View Post
    *buffer is the same as buffer[0] -> not a pointer -> compile error
    But is * not the symbol for the pointer-type? And next to that I don't get a compiler error for using it.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Ahh so buffer and &buffer are exactly the same? Because also &buffer points to the first element of this char array.
    Not exactly. buffer is an array, &buffer is the address of the array, which is a pointer. They may both point to the same place in memory, but they are not the same.

    But is * not the symbol for the pointer-type?
    Yes, but the meaning of * depends on context.

    Code:
    int *x = NULL; // * used such that x is a pointer.
    int a = *b;    // * used such that *b is an int.
    And next to that I don't get a compiler error for using it.
    How did you use it?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Sep 2007
    Posts
    26
    Code:
    int *x = NULL; // * used such that x is a pointer.
    makes sense

    Code:
    int a = *b;    // * used such that *b is an int.
    Aha this makes a containing the hexcode of the first field of b[]:
    Code:
            char *b="test";
            int a;
            a = *b;
            printf("%i",a) ;
    Prints: 116 so is it that char *b="test" tells push test on the stack and make b a pointer to it. While *b points to the content which start with 116, b and &b are just the memory adresses ?

    Quote Originally Posted by laserlight View Post
    How did you use it?
    In this code:
    Code:
    #include </usr/include/linux/unistd.h>
    
    int main(void) {
    
            char *myfile = "testfile",buffer[100];
            int fd,buffer_len;
       
            fd = syscall(__NR_open,myfile,00,04000) ;
            syscall(__NR_read,fd,buffer,100);
            syscall(__NR_close,fd);
            for ( buffer_len=1; buffer[buffer_len] != '\0'; buffer_len++);
            syscall(__NR_write,1,*buffer,buffer_len);
        
            return 0;
    }
    I don't get any errors for *buffer. Normally compiled with gcc -o test test.c and gcc version 4.1.2 . The program simply doesn't work but compiles nice. *buffer exchanged with buffer or &buffer and the program works fine.

  10. #10
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by lilcoder View Post
    I don't get any errors for *buffer.
    That is because syscall is a function that takes a variable number of arguments. That's why the compiler can't check the type of the arguments.
    Kurt

  11. #11
    Registered User
    Join Date
    Sep 2007
    Posts
    26
    ah okay thank you for your answers

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Your mistake is believing that a FILE object and a file descriptor have anything to do with each other. They don't. The only problem I see here is attempting to print a FILE pointer as an integer -- why would you do that?

    EDIT: I'm still clueless as to why you are calling system calls like that. Why not just call open()? Calling a syscall directly is not guaranteed to behave anything like the manual says it should.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    And you should DEFINITELY close the file after it's been opened. The C runtime keeps track of regular files, and I expect there to be some safeguards on system calls too, but just in case.

    [I agree with brewbuck - you are gaining ABSOLUTELY NOTHING by doing this, but risking that your code will be incompatible in a future version of Linux, as well as that the C library is "fixing" bugs that are in some varieties of Linux].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > for ( buffer_len=1; buffer[buffer_len] != '\0'; buffer_len++);
    The ; at the end renders this for loop useless.

    > syscall(__NR_write,1,&buffer,strlen(buffer));
    read doesn't append a \0, so it's wrong to use strlen() to go looking for it.
    Since read() returns a result (which you're ignoring), perhaps you could pick that up and use that to determine how much to write.

    Ditto what others have said, you've gained nothing over using the standard POSIX API.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Salem View Post
    > for ( buffer_len=1; buffer[buffer_len] != '\0'; buffer_len++);
    The ; at the end renders this for loop useless.
    Isn't this just a "strlen()" re-implemented.

    Althouhg, of course, there's no guarantee from read that there's a zero at the end of the buffer - there could be, but that depends on the content of the filel and/or the content fo buffer before the read. If you read a string from a binary file, it would be OK. If it's a text file and there's more than 100 bytes in the file, it will fail to have a zero at the end. [And of course, the string could be EMPTY, in whcih case starting at 1 could give the wrong result.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed