WvStreams
wvfile.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2004 Net Integration Technologies, Inc.
00004  * 
00005  * A simple class to access filesystem files using WvStreams.
00006  */
00007 #include "wvfile.h"
00008 #include "wvmoniker.h"
00009 
00010 WvFile::WvFile()
00011 {
00012     readable = writable = false;
00013 }
00014 
00015 #ifndef _WIN32 // meaningless to do this on win32
00016 /*
00017  * The Win32 runtime library doesn't provide fcntl so we can't
00018  * set readable and writable reliably. Use the other constructor.
00019  */
00020 WvFile::WvFile(int rwfd) : WvFDStream(rwfd)
00021 {
00022     if (rwfd > -1)
00023     {
00024         /* We have to do it this way since O_RDONLY is defined as 0
00025             in linux. */
00026         mode_t xmode = fcntl(rwfd, F_GETFL);
00027         xmode = xmode & (O_RDONLY | O_WRONLY | O_RDWR);
00028         readable = (xmode == O_RDONLY) || (xmode == O_RDWR);
00029         writable = (xmode == O_WRONLY) || (xmode == O_RDWR);
00030     }
00031     else
00032         readable = writable = false;
00033 }
00034 #endif
00035 
00036 
00037 WvFile::WvFile(WvStringParm filename, int mode, int create_mode)
00038 {
00039 #ifdef _WIN32
00040     mode |= O_BINARY; // WvStreams users aren't expecting crlf mangling
00041 #endif
00042     open(filename, mode, create_mode);
00043 }
00044 
00045 
00046 static IWvStream *increator(WvStringParm s, IObject*)
00047 {
00048     return new WvFile(s, O_RDONLY, 0666);
00049 }
00050 
00051 static IWvStream *outcreator(WvStringParm s, IObject*)
00052 {
00053     return new WvFile(s, O_WRONLY|O_CREAT|O_TRUNC, 0666);
00054 }
00055 
00056 static IWvStream *creator(WvStringParm s, IObject*)
00057 {
00058     return new WvFile(s, O_RDWR|O_CREAT, 0666);
00059 }
00060 
00061 static WvMoniker<IWvStream> reg0("infile", increator);
00062 static WvMoniker<IWvStream> reg1("outfile", outcreator);
00063 static WvMoniker<IWvStream> reg3("file", creator);
00064 
00065 
00066 bool WvFile::open(WvStringParm filename, int mode, int create_mode)
00067 {
00068     noerr();
00069     
00070     /* We have to do it this way since O_RDONLY is defined as 0
00071        in linux. */
00072     int xmode = (mode & (O_RDONLY | O_WRONLY | O_RDWR));
00073     readable = (xmode == O_RDONLY) || (xmode == O_RDWR);
00074     writable = (xmode == O_WRONLY) || (xmode == O_RDWR);
00075 
00076     // don't do the default force_select of read if we're not readable!
00077     if (!readable)
00078         undo_force_select(true, false, false);
00079     
00080     close();
00081     #ifndef _WIN32
00082     int rwfd = ::open(filename, mode | O_NONBLOCK, create_mode);
00083     #else
00084     int rwfd = ::_open(filename, mode | O_NONBLOCK, create_mode);
00085     #endif
00086     if (rwfd < 0)
00087     {
00088         seterr(errno);
00089         return false;
00090     }
00091     setfd(rwfd);
00092     fcntl(rwfd, F_SETFD, 1);
00093 
00094     closed = stop_read = stop_write = false;
00095     return true;
00096 }
00097 
00098 
00099 #ifndef _WIN32  // since win32 doesn't support fcntl
00100 bool WvFile::open(int _rwfd)
00101 {
00102     noerr();
00103     if (_rwfd < 0)
00104         return false;
00105 
00106     noerr();
00107     close();
00108     
00109     int mode = fcntl(_rwfd, F_GETFL);
00110     int xmode = (mode & (O_RDONLY | O_WRONLY | O_RDWR));
00111     readable = (xmode == O_RDONLY) || (xmode == O_RDWR);
00112     writable = (xmode == O_WRONLY) || (xmode == O_RDWR);
00113 
00114     if (!readable)
00115         undo_force_select(true, false, false);
00116 
00117     setfd(_rwfd);
00118     fcntl(_rwfd, F_SETFL, mode | O_NONBLOCK);
00119     fcntl(_rwfd, F_SETFD, 1);
00120 
00121     closed = stop_read = stop_write = false;
00122     return true;
00123 }
00124 #endif 
00125 
00126 
00127 // files not open for read are never readable; files not open for write
00128 // are never writable.
00129 void WvFile::pre_select(SelectInfo &si)
00130 {
00131     if (!readable) si.wants.readable = false;
00132     if (!writable) si.wants.writable = false;
00133 
00134     WvFDStream::pre_select(si);    
00135 }
00136 
00137 
00138 bool WvFile::post_select(SelectInfo &si)
00139 {
00140     return WvFDStream::post_select(si);
00141 }