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
00102
00103 int sdisk_unix_t::convert_flags(int sflags)
00104 {
00105 int flags = 0;
00106
00107
00108 switch (modeBits(sflags)) {
00109 case OPEN_RDWR:
00110 flags |= O_RDWR;
00111 break;
00112 case OPEN_WRONLY:
00113 flags |= O_WRONLY;
00114 break;
00115 case OPEN_RDONLY:
00116 flags |= O_RDONLY;
00117 break;
00118 }
00119
00120
00121
00122 if (hasOption(sflags, OPEN_CREATE))
00123 flags |= O_CREAT;
00124 if (hasOption(sflags, OPEN_TRUNC))
00125 flags |= O_TRUNC;
00126 if (hasOption(sflags, OPEN_EXCL))
00127 flags |= O_EXCL;
00128 #ifdef O_SYNC
00129 if (hasOption(sflags, OPEN_SYNC))
00130 flags |= O_SYNC;
00131 #endif
00132 if (hasOption(sflags, OPEN_APPEND))
00133 flags |= O_APPEND;
00134 #ifdef O_DIRECT
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 if (hasOption(sflags, OPEN_RAW))
00150 flags |= O_DIRECT;
00151 #endif
00152
00153 return flags;
00154 }
00155
00156
00157 sdisk_unix_t::~sdisk_unix_t()
00158 {
00159 if (_fd != FD_NONE)
00160 W_COERCE(close());
00161 }
00162
00163
00164 w_rc_t sdisk_unix_t::make(const char *name, int flags, int mode,
00165 sdisk_t *&disk)
00166 {
00167 sdisk_unix_t *ud;
00168 w_rc_t e;
00169
00170 disk = 0;
00171
00172 ud = new sdisk_unix_t(name);
00173 if (!ud)
00174 return RC(fcOUTOFMEMORY);
00175
00176 e = ud->open(name, flags, mode);
00177 if (e.is_error()) {
00178 delete ud;
00179 return e;
00180 }
00181
00182 disk = ud;
00183 return RCOK;
00184 }
00185
00186
00187 w_rc_t sdisk_unix_t::open(const char *name, int flags, int mode)
00188 {
00189 if (_fd != FD_NONE)
00190 return RC(stBADFD);
00191
00192 _fd = ::os_open(name, convert_flags(flags), mode);
00193 if (_fd == -1) {
00194 w_rc_t rc = RC(fcOS);
00195 RC_APPEND_MSG(rc, << "Offending file: " << name);
00196 return rc;
00197 }
00198
00199 return RCOK;
00200 }
00201
00202 w_rc_t sdisk_unix_t::close()
00203 {
00204 if (_fd == FD_NONE)
00205 return RC(stBADFD);
00206
00207 int n;
00208
00209 n = ::os_close(_fd);
00210 if (n == -1)
00211 return RC(fcOS);
00212
00213 _fd = FD_NONE;
00214 return RCOK;
00215 }
00216
00217
00218
00219
00220 w_rc_t sdisk_unix_t::read(void *buf, int count, int &done)
00221 {
00222 if (_fd == FD_NONE)
00223 return RC(stBADFD);
00224
00225 int n;
00226 n = ::os_read(_fd, buf, count);
00227 if (n == -1)
00228 return RC(fcOS);
00229
00230 done = n;
00231
00232 return RCOK;
00233 }
00234
00235 w_rc_t sdisk_unix_t::write(const void *buf, int count, int &done)
00236 {
00237 if (_fd == FD_NONE)
00238 return RC(stBADFD);
00239
00240 int n;
00241
00242 n = ::os_write(_fd, buf, count);
00243 if (n == -1)
00244 return RC(fcOS);
00245
00246 #if defined(USING_VALGRIND)
00247 if(RUNNING_ON_VALGRIND)
00248 {
00249 check_valgrind_errors(__LINE__, __FILE__);
00250 }
00251 #endif
00252
00253 done = n;
00254
00255 return RCOK;
00256 }
00257
00258 #ifdef HAVE_IO_VECTOR
00259 w_rc_t sdisk_unix_t::readv(const iovec_t *iov, int iovcnt, int &done)
00260 {
00261 if (_fd == FD_NONE)
00262 return RC(stBADFD);
00263
00264 int n;
00265
00266 n = ::os_readv(_fd, (const struct iovec *)iov, iovcnt);
00267 if (n == -1)
00268 return RC(fcOS);
00269
00270 done = n;
00271
00272 return RCOK;
00273 }
00274
00275 w_rc_t sdisk_unix_t::writev(const iovec_t *iov, int iovcnt, int &done)
00276 {
00277 if (_fd == FD_NONE)
00278 return RC(stBADFD);
00279
00280 int n;
00281
00282 #ifdef IOVEC_MISMATCH
00283 {
00284 struct iovec _iov[sthread_t::iovec_max];
00285 for (int i = 0; i < iovcnt; i++) {
00286 _iov[i].iov_base = (char *) iov[i].iov_base;
00287 _iov[i].iov_len = iov[i].iov_len;
00288 }
00289 n = ::os_writev(_fd, _iov, iovcnt);
00290 }
00291 #else
00292 n = ::os_writev(_fd, (const struct iovec *)iov, iovcnt);
00293 #endif
00294 if (n == -1)
00295 return RC(fcOS);
00296
00297 #if defined(USING_VALGRIND)
00298 if(RUNNING_ON_VALGRIND)
00299 {
00300 check_valgrind_errors(__LINE__, __FILE__);
00301 }
00302 #endif
00303
00304 done = n;
00305
00306 return RCOK;
00307 }
00308 #endif
00309
00310 w_rc_t sdisk_unix_t::pread(void *buf, int count, fileoff_t pos, int &done)
00311 {
00312 if (_fd == FD_NONE)
00313 return RC(stBADFD);
00314
00315 int n;
00316
00317 n = ::os_pread(_fd, buf, count, pos);
00318 if (n == -1)
00319 return RC(fcOS);
00320
00321 done = n;
00322
00323 return RCOK;
00324 }
00325
00326
00327 w_rc_t sdisk_unix_t::pwrite(const void *buf, int count, fileoff_t pos,
00328 int &done)
00329 {
00330 if (_fd == FD_NONE)
00331 return RC(stBADFD);
00332
00333 int n;
00334
00335 n = ::os_pwrite(_fd, buf, count, pos);
00336 if (n == -1)
00337 return RC(fcOS);
00338 #if defined(USING_VALGRIND)
00339 if(RUNNING_ON_VALGRIND)
00340 {
00341 check_valgrind_errors(__LINE__, __FILE__);
00342 }
00343 #endif
00344
00345 done = n;
00346
00347 return RCOK;
00348 }
00349
00350 w_rc_t sdisk_unix_t::seek(fileoff_t pos, int origin, fileoff_t &newpos)
00351 {
00352 if (_fd == FD_NONE)
00353 return RC(stBADFD);
00354
00355 switch (origin) {
00356 case SEEK_AT_SET:
00357 origin = SEEK_SET;
00358 break;
00359 case SEEK_AT_CUR:
00360 origin = SEEK_CUR;
00361 break;
00362 case SEEK_AT_END:
00363 origin = SEEK_END;
00364 break;
00365 }
00366
00367 fileoff_t l=0;
00368 l = ::os_lseek(_fd, pos, origin);
00369 if (l == -1)
00370 return RC(fcOS);
00371
00372 newpos = l;
00373
00374 return RCOK;
00375 }
00376
00377 w_rc_t sdisk_unix_t::truncate(fileoff_t size)
00378 {
00379 if (_fd == FD_NONE)
00380 return RC(stBADFD);
00381 int n = ::os_ftruncate(_fd, size);
00382 return (n == -1) ? RC(fcOS) : RCOK;
00383 }
00384
00385 w_rc_t sdisk_unix_t::sync()
00386 {
00387 if (_fd == FD_NONE)
00388 return RC(stBADFD);
00389
00390 int n = os_fsync(_fd);
00391
00392
00393 if (n == -1 && (errno == EBADF || errno == EINVAL))
00394 n = 0;
00395
00396 return (n == -1) ? RC(fcOS) : RCOK;
00397 }
00398
00399
00400 w_rc_t sdisk_unix_t::stat(filestat_t &st)
00401 {
00402 if (_fd == FD_NONE)
00403 return RC(stBADFD);
00404
00405 os_stat_t sys;
00406 int n = os_fstat(_fd, &sys);
00407 if (n == -1)
00408 return RC(fcOS);
00409
00410 st.st_size = sys.st_size;
00411 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
00412 st.st_block_size = sys.st_blksize;
00413 #else
00414 st.st_block_size = 512;
00415 #endif
00416
00417 st.st_device_id = sys.st_dev;
00418 st.st_file_id = sys.st_ino;
00419
00420 int mode = (sys.st_mode & S_IFMT);
00421 st.is_file = (mode == S_IFREG);
00422 st.is_dir = (mode == S_IFDIR);
00423 #ifdef S_IFBLK
00424 st.is_device = (mode == S_IFBLK);
00425 #else
00426 st.is_device = false;
00427 #endif
00428 st.is_device = st.is_device || (mode == S_IFCHR);
00429
00430 return RCOK;
00431 }
00432
00433