Filehandle, wrappers etc

Discussion in 'Mac Programming' started by mdeh, Feb 16, 2009.

  1. macrumors 6502

    Joined:
    Jan 3, 2009
    #1
    I have been searching the docs, and ( where else) wikipedia for some very basic understanding of exactly **what** a filehandle "is".

    Wikipedia says this.

    and


    As the word "wrapper" seems to pop-up ( often in the documentation in Xcode,without ever formally defining it..well, I could not find it) again, I wonder if someone could just briefly and conceptually define these 2 terms.

    thanks in advance.
     
  2. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    I don't have ready access to an OS X machine, but on a linux machine this is what the definition of _IO_FILE is, which is what FILE is typedef'd to:
    Code:
    struct _IO_FILE {
      int _flags;           /* High-order word is _IO_MAGIC; rest is flags. */
    #define _IO_file_flags _flags
    
      /* The following pointers correspond to the C++ streambuf protocol. */
      /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
      char* _IO_read_ptr;   /* Current read pointer */
      char* _IO_read_end;   /* End of get area. */
      char* _IO_read_base;  /* Start of putback+get area. */
      char* _IO_write_base; /* Start of put area. */
      char* _IO_write_ptr;  /* Current put pointer. */
      char* _IO_write_end;  /* End of put area. */
      char* _IO_buf_base;   /* Start of reserve area. */
      char* _IO_buf_end;    /* End of reserve area. */
      /* The following fields are used to support backing up and undo. */
      char *_IO_save_base; /* Pointer to start of non-current get area. */
      char *_IO_backup_base;  /* Pointer to first valid character of backup area */
      char *_IO_save_end; /* Pointer to end of non-current get area. */
    
      struct _IO_marker *_markers;
    
      struct _IO_FILE *_chain;
    
      int _fileno;
    #if 0
      int _blksize;
    #else
      int _flags2;
    #endif
      _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
    
    #define __HAVE_COLUMN /* temporary */
      /* 1+column number of pbase(); 0 is unknown. */
      unsigned short _cur_column;
      signed char _vtable_offset;
      char _shortbuf[1];
    
      /*  char* _save_gptr;  char* _save_egptr; */
    
      _IO_lock_t *_lock;
    #ifdef _IO_USE_OLD_IO_FILE
    };
    
    In this case, the int _fileno will actually hold a file descriptor. On a unix or unix-like system such as linux or OS X, everything is treated as a file, so any network connection, actual filesystem object, pipe, etc. will have a file descriptor.

    The file descriptor is the "lowest level" description of the file for that process. The library that is responsible for I/O will keep track of other things about the file based on the descriptor, so you don't have to carry all of that info around with you in your own code.

    The FILE structure takes a different approach, in that you will take a lot of information about the file being accessed with you in your own code. A lot of "state" in terms of the file's current offset, etc. is available in the FILE structure for use by I/O routines.

    The term "wrapper" in this case would refer to the FILE structure, as it obscures the low-level file descriptor from the programmer, wrapping it in a structure that for the most part can be unknown to the programmer using it. Generally a wrapper is any additional code, data structures, objects, etc. that abstract something low-level, hopefully with the intent of making it easier to use. An example would be a simple network communication library. The programmer using it would just need to call a few simple methods, and all of the "dirty work" of setting up sockets, etc. would be abstracted away. This would be considered a wrapper for low-level networking code.

    Sometimes a wrapper might also be used to make it easier to call a complex function. Perhaps you have everything you need to call the function in a structure, but don't want to type out the names of all the fields each time you want to invoke the function. You could write a wrapper that takes your structure, then calls the function, and returns the result, etc. This way in your code you'd just call the wrapper with the structure being the sole argument, and it looks much cleaner.

    Other times you might want to use this kind of abstraction would be in making calls between programming languages, etc. You might need to massage values, change any passes by value to passes by reference, etc. that is easier to do correctly once, then reuse in the future, rather than always doing all of the nitty-gritty work for each invocation.

    -Lee
     
  3. thread starter macrumors 6502

    Joined:
    Jan 3, 2009
    #3
     
  4. macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #4
    A path is just a high level representation of where a file is stored. It bears no relation to where the file is actually stored as generally files can be spread out in lots of different areas of the disk.

    Without a file there is no path, as the path is just a way of describing the location of a file. Also a directory is just a file. Unix treats everything as a file. Serial connections, text documents, sockets, all can be read and written too in the same way.

    Hopefully my inane ramblings have been helpful.
     
  5. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #5
    At any given time, each file opened by a process has a unique number, yes. Once a file is closed, the number may be reused, though. This means you should be sure to set the file descriptor in your code to 0 after you close it, so you don't get confused later and reuse the file descriptor that may now be referring to a new file that you've opened since closing the original.

    I included the code to show what was actually being pointed to by a FILE *. There's a lot of extra information available in this structure, so the library doesn't have to keep track of as much internally.

    Yes, and this is a wrapper for a file descriptor. It abstracts the lower-level functions actually used for accessing a file.

    Right.

    A path is pretty much an address. You can write the address 7384 Poppy Lane on a sheet of paper, and that seems like an address, but it doesn't mean there's anything at that address, or that there is such an address, or that there is even a Poppy Lane. That's pretty much what a path is. You can create any path you'd like, but the existence of a file/directory at that location is not assured. The address metaphor sort of breaks down going the other direction... i suppose you could have a house without an address... but basically, yes, once a file or directory exists in the file system, there is a path (perhaps many with symlinks, etc.) to that file (a directory is also a file). As for "creation"... i guess i'd say that the act of creating a file also cements its path. You'd need to know where you wanted to put it, so I guess technically, yes, you'd need to "create" the path first.

    No problem. Everyone starts somewhere. The more knowledge that's out there, the better off we all are, in my opinion.

    -Lee
     
  6. thread starter macrumors 6502

    Joined:
    Jan 3, 2009
    #6
    Lee...thanks again. Your explanations are very helpful.
     
  7. thread starter macrumors 6502

    Joined:
    Jan 3, 2009
    #7
    Don't sell yourself short. Your input to me is very helpful and much appreciated.
     

Share This Page