00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "w_defines.h"
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #if defined(linux) && !defined(_GNU_SOURCE)
00070
00071
00072
00073
00074
00075 #define _GNU_SOURCE
00076 #endif
00077
00078 #include <w.h>
00079 #include <sthread.h>
00080 #include <sdisk.h>
00081 #include <sdisk_unix.h>
00082 #include <sthread_stats.h>
00083 extern class sthread_stats SthreadStats;
00084
00085 #include "os_fcntl.h"
00086 #include <cerrno>
00087 #include <sys/stat.h>
00088
00089 #include <sys/uio.h>
00090
00091 #define HAVE_IO_VECTOR
00092
00093
00094
00095
00096 #include <os_interface.h>
00097
00098
00099 const int stBADFD = sthread_base_t::stBADFD;
00100
00101 int sdisk_unix_t::convert_flags(int sflags)
00102 {
00103 int flags = 0;
00104
00105
00106 switch (modeBits(sflags)) {
00107 case OPEN_RDWR:
00108 flags |= O_RDWR;
00109 break;
00110 case OPEN_WRONLY:
00111 flags |= O_WRONLY;
00112 break;
00113 case OPEN_RDONLY:
00114 flags |= O_RDONLY;
00115 break;
00116 }
00117
00118
00119
00120 if (hasOption(sflags, OPEN_CREATE))
00121 flags |= O_CREAT;
00122 if (hasOption(sflags, OPEN_TRUNC))
00123 flags |= O_TRUNC;
00124 if (hasOption(sflags, OPEN_EXCL))
00125 flags |= O_EXCL;
00126 #ifdef O_SYNC
00127 if (hasOption(sflags, OPEN_SYNC))
00128 flags |= O_SYNC;
00129 #endif
00130 if (hasOption(sflags, OPEN_APPEND))
00131 flags |= O_APPEND;
00132 #ifdef O_DIRECT
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 if (hasOption(sflags, OPEN_RAW))
00148 flags |= O_DIRECT;
00149 #endif
00150
00151 return flags;
00152 }
00153
00154
00155 sdisk_unix_t::~sdisk_unix_t()
00156 {
00157 if (_fd != FD_NONE)
00158 W_COERCE(close());
00159 }
00160
00161
00162 w_rc_t sdisk_unix_t::make(const char *name, int flags, int mode,
00163 sdisk_t *&disk)
00164 {
00165 sdisk_unix_t *ud;
00166 w_rc_t e;
00167
00168 disk = 0;
00169
00170 ud = new sdisk_unix_t(name);
00171 if (!ud)
00172 return RC(fcOUTOFMEMORY);
00173
00174 e = ud->open(name, flags, mode);
00175 if (e.is_error()) {
00176 delete ud;
00177 return e;
00178 }
00179
00180 disk = ud;
00181 return RCOK;
00182 }
00183
00184
00185 w_rc_t sdisk_unix_t::open(const char *name, int flags, int mode)
00186 {
00187 if (_fd != FD_NONE)
00188 return RC(stBADFD);
00189
00190 _fd = ::os_open(name, convert_flags(flags), mode);
00191 if (_fd == -1) {
00192 w_rc_t rc = RC(fcOS);
00193 RC_APPEND_MSG(rc, << "Offending file: " << name);
00194 return rc;
00195 }
00196
00197 return RCOK;
00198 }
00199
00200 w_rc_t sdisk_unix_t::close()
00201 {
00202 if (_fd == FD_NONE)
00203 return RC(stBADFD);
00204
00205 int n;
00206
00207 n = ::os_close(_fd);
00208 if (n == -1)
00209 return RC(fcOS);
00210
00211 _fd = FD_NONE;
00212 return RCOK;
00213 }
00214
00215
00216
00217
00218 w_rc_t sdisk_unix_t::read(void *buf, int count, int &done)
00219 {
00220 if (_fd == FD_NONE)
00221 return RC(stBADFD);
00222
00223 int n;
00224 n = ::os_read(_fd, buf, count);
00225 if (n == -1)
00226 return RC(fcOS);
00227
00228 done = n;
00229
00230 return RCOK;
00231 }
00232
00233 w_rc_t sdisk_unix_t::write(const void *buf, int count, int &done)
00234 {
00235 if (_fd == FD_NONE)
00236 return RC(stBADFD);
00237
00238 int n;
00239
00240 n = ::os_write(_fd, buf, count);
00241 if (n == -1)
00242 return RC(fcOS);
00243
00244 #if defined(USING_VALGRIND)
00245 if(RUNNING_ON_VALGRIND)
00246 {
00247 check_valgrind_errors(__LINE__, __FILE__);
00248 }
00249 #endif
00250
00251 done = n;
00252
00253 return RCOK;
00254 }
00255
00256 #ifdef HAVE_IO_VECTOR
00257 w_rc_t sdisk_unix_t::readv(const iovec_t *iov, int iovcnt, int &done)
00258 {
00259 if (_fd == FD_NONE)
00260 return RC(stBADFD);
00261
00262 int n;
00263
00264 n = ::os_readv(_fd, (const struct iovec *)iov, iovcnt);
00265 if (n == -1)
00266 return RC(fcOS);
00267
00268 done = n;
00269
00270 return RCOK;
00271 }
00272
00273 w_rc_t sdisk_unix_t::writev(const iovec_t *iov, int iovcnt, int &done)
00274 {
00275 if (_fd == FD_NONE)
00276 return RC(stBADFD);
00277
00278 int n;
00279
00280 #ifdef IOVEC_MISMATCH
00281 {
00282 struct iovec _iov[sthread_t::iovec_max];
00283 for (int i = 0; i < iovcnt; i++) {
00284 _iov[i].iov_base = (char *) iov[i].iov_base;
00285 _iov[i].iov_len = iov[i].iov_len;
00286 }
00287 n = ::os_writev(_fd, _iov, iovcnt);
00288 }
00289 #else
00290 n = ::os_writev(_fd, (const struct iovec *)iov, iovcnt);
00291 #endif
00292 if (n == -1)
00293 return RC(fcOS);
00294
00295 #if defined(USING_VALGRIND)
00296 if(RUNNING_ON_VALGRIND)
00297 {
00298 check_valgrind_errors(__LINE__, __FILE__);
00299 }
00300 #endif
00301
00302 done = n;
00303
00304 return RCOK;
00305 }
00306 #endif
00307
00308 w_rc_t sdisk_unix_t::pread(void *buf, int count, fileoff_t pos, int &done)
00309 {
00310 if (_fd == FD_NONE)
00311 return RC(stBADFD);
00312
00313 int n;
00314
00315 n = ::os_pread(_fd, buf, count, pos);
00316 if (n == -1)
00317 return RC(fcOS);
00318
00319 done = n;
00320
00321 return RCOK;
00322 }
00323
00324
00325 w_rc_t sdisk_unix_t::pwrite(const void *buf, int count, fileoff_t pos,
00326 int &done)
00327 {
00328 if (_fd == FD_NONE)
00329 return RC(stBADFD);
00330
00331 int n;
00332
00333 n = ::os_pwrite(_fd, buf, count, pos);
00334 if (n == -1)
00335 return RC(fcOS);
00336 #if defined(USING_VALGRIND)
00337 if(RUNNING_ON_VALGRIND)
00338 {
00339 check_valgrind_errors(__LINE__, __FILE__);
00340 }
00341 #endif
00342
00343 done = n;
00344
00345 return RCOK;
00346 }
00347
00348 w_rc_t sdisk_unix_t::seek(fileoff_t pos, int origin, fileoff_t &newpos)
00349 {
00350 if (_fd == FD_NONE)
00351 return RC(stBADFD);
00352
00353 switch (origin) {
00354 case SEEK_AT_SET:
00355 origin = SEEK_SET;
00356 break;
00357 case SEEK_AT_CUR:
00358 origin = SEEK_CUR;
00359 break;
00360 case SEEK_AT_END:
00361 origin = SEEK_END;
00362 break;
00363 }
00364
00365 fileoff_t l=0;
00366 l = ::os_lseek(_fd, pos, origin);
00367 if (l == -1)
00368 return RC(fcOS);
00369
00370 newpos = l;
00371
00372 return RCOK;
00373 }
00374
00375 w_rc_t sdisk_unix_t::truncate(fileoff_t size)
00376 {
00377 if (_fd == FD_NONE)
00378 return RC(stBADFD);
00379 int n = ::os_ftruncate(_fd, size);
00380 return (n == -1) ? RC(fcOS) : RCOK;
00381 }
00382
00383 w_rc_t sdisk_unix_t::sync()
00384 {
00385 if (_fd == FD_NONE)
00386 return RC(stBADFD);
00387
00388 int n = os_fsync(_fd);
00389
00390
00391 if (n == -1 && (errno == EBADF || errno == EINVAL))
00392 n = 0;
00393
00394 return (n == -1) ? RC(fcOS) : RCOK;
00395 }
00396
00397
00398 w_rc_t sdisk_unix_t::stat(filestat_t &st)
00399 {
00400 if (_fd == FD_NONE)
00401 return RC(stBADFD);
00402
00403 os_stat_t sys;
00404 int n = os_fstat(_fd, &sys);
00405 if (n == -1)
00406 return RC(fcOS);
00407
00408 st.st_size = sys.st_size;
00409 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
00410 st.st_block_size = sys.st_blksize;
00411 #else
00412 st.st_block_size = 512;
00413 #endif
00414
00415 st.st_device_id = sys.st_dev;
00416 st.st_file_id = sys.st_ino;
00417
00418 int mode = (sys.st_mode & S_IFMT);
00419 st.is_file = (mode == S_IFREG);
00420 st.is_dir = (mode == S_IFDIR);
00421 #ifdef S_IFBLK
00422 st.is_device = (mode == S_IFBLK);
00423 #else
00424 st.is_device = false;
00425 #endif
00426 st.is_device = st.is_device || (mode == S_IFCHR);
00427
00428 return RCOK;
00429 }
00430
00431