00001 /* 00002 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00003 May be copied only for purposes and under conditions described 00004 on the Web page www.basepath.com/aup/copyright.htm. 00005 00006 The Example Files are provided "as is," without any warranty; 00007 without even the implied warranty of merchantability or fitness 00008 for a particular purpose. The author and his publisher are not 00009 responsible for any damages, direct or incidental, resulting 00010 from the use or non-use of these Example Files. 00011 00012 The Example Files may contain defects, and some contain deliberate 00013 coding mistakes that were included for educational reasons. 00014 You are responsible for determining if and how the Example Files 00015 are to be used. 00016 00017 */ 00018 #include "ux.hpp" 00019 00020 using namespace Ux; 00021 00022 /** 00023 Calls malloc to allocate the path. 00024 */ 00025 void File::alloc(ssize_t n) 00026 { 00027 if (n == -1) 00028 size = get_max_name(); 00029 else 00030 size = n; 00031 // use malloc instead of new so errno will be set 00032 if ((path = (char *)::malloc(size)) == NULL) 00033 throw Error(errno); 00034 } 00035 00036 /** 00037 Calls free to free the path. 00038 */ 00039 void File::free(void) 00040 { 00041 ::free((void *)path); 00042 path = NULL; 00043 size = -1; 00044 } 00045 00046 /** 00047 Calls pathconf to get _PC_PATH_MAX. 00048 */ 00049 size_t File::get_max_name(const char *p) 00050 { 00051 return (size_t)File(p).pathconf(_PC_PATH_MAX, 4096); 00052 } 00053 00054 //////////////////////////////////////////////// 00055 00056 /** 00057 Calls access. 00058 */ 00059 int File::access(int what, bool want_throw) 00060 { 00061 int r; 00062 00063 if ((r = ::access(path, what)) == -1 && want_throw) 00064 throw Error(errno); 00065 return r; 00066 } 00067 00068 /** 00069 Calls chmod or fchmod. 00070 */ 00071 void File::chmod(mode_t mode) 00072 { 00073 int r; 00074 00075 if (fd == -1) 00076 r = ::chmod(path, mode); 00077 else 00078 r = ::fchmod(fd, mode); 00079 if (r == -1) 00080 throw Error(errno); 00081 } 00082 00083 /** 00084 Calls chown or fchown. 00085 */ 00086 void File::chown(uid_t uid, gid_t gid) 00087 { 00088 int r; 00089 00090 if (fd == -1) 00091 r = ::chown(path, uid, gid); 00092 else 00093 r = ::fchown(fd, uid, gid); 00094 if (r == -1) 00095 throw Error(errno); 00096 } 00097 00098 /** 00099 Calls close. 00100 */ 00101 void File::close(void) 00102 { 00103 if (::close(fd) == -1) 00104 throw Error(errno); 00105 } 00106 00107 /** 00108 Calls dup. 00109 */ 00110 File File::dup(void) 00111 { 00112 int fd2; 00113 00114 if ((fd2 = ::dup(fd)) == -1) 00115 throw Error(errno); 00116 return File(fd2); 00117 } 00118 00119 /** 00120 Calls dup2. 00121 */ 00122 File File::dup2(int fd2) 00123 { 00124 if (::dup2(fd, fd2) == -1) 00125 throw Error(errno); 00126 return File(fd2); 00127 } 00128 00129 /** 00130 Calls fcntl. Works only if the single optional argument is an int or pointer. 00131 */ 00132 int File::fcntl(int op, ...) 00133 { 00134 int n; 00135 00136 va_list ap; 00137 va_start(ap, op); 00138 if ((n = ::fcntl(fd, op, va_arg(ap, intptr_t))) == -1) 00139 throw Error(errno); 00140 va_end(ap); 00141 return n; 00142 } 00143 00144 /** 00145 Calls fsync or fdatasync. 00146 */ 00147 void File::fsync(int op) 00148 { 00149 int r; 00150 00151 switch (op) { 00152 #if _POSIX_SYNCHRONIZED_IO > 0 00153 case O_SYNC: 00154 #endif 00155 r = ::fsync(fd); 00156 #if _POSIX_SYNCHRONIZED_IO > 0 && O_SYNC != O_DSYNC 00157 break; 00158 case O_DSYNC: 00159 r = ::fdatasync(fd); 00160 #endif 00161 } 00162 if (r == -1) 00163 throw Error(errno); 00164 } 00165 00166 /** 00167 Calls lchown. 00168 */ 00169 void File::lchown(uid_t uid, gid_t gid) 00170 { 00171 if (::lchown(path, uid, gid) == -1) 00172 throw Error(errno); 00173 } 00174 00175 /** 00176 Calls link. 00177 */ 00178 void File::link(const char *newpath) 00179 { 00180 if (::link(path, newpath) == -1) 00181 throw Error(errno); 00182 } 00183 00184 /** 00185 Calls lockf. 00186 */ 00187 void File::lockf(int op, off_t len) 00188 { 00189 if (::lockf(fd, op, len) == -1) 00190 throw Error(errno); 00191 } 00192 00193 /** 00194 Calls lstat. 00195 */ 00196 void File::lstat(struct stat *buf) 00197 { 00198 if (::lstat(path, buf) == -1) 00199 throw Error(errno); 00200 } 00201 00202 /** 00203 Calls mkfifo. 00204 */ 00205 void File::mkfifo(mode_t perms) 00206 { 00207 if (::mkfifo(path, perms) == -1) 00208 throw Error(errno); 00209 } 00210 00211 /** 00212 Calls mknod. 00213 */ 00214 void File::mknod(mode_t perms, dev_t dev) 00215 { 00216 if (::mknod(path, perms, dev) == -1) 00217 throw Error(errno); 00218 } 00219 00220 /** 00221 Calls mkstemp. 00222 */ 00223 void File::mkstemp(void) 00224 { 00225 // overriding const -- user better have supplied buffer! 00226 if ((fd = ::mkstemp((char *)path)) == -1) 00227 throw Error(errno); 00228 } 00229 00230 /** 00231 Calls open. 00232 */ 00233 void File::open(int flags, mode_t perms) 00234 { 00235 if ((fd = ::open(path, flags, perms)) == -1) 00236 throw Error(errno); 00237 } 00238 00239 /** 00240 Calls pathconf or fpathconf, with a default value to be used if the value is unspecified. 00241 */ 00242 long File::pathconf(int name, long default_val) 00243 { 00244 long r; 00245 00246 errno = 0; 00247 if (fd == -1) 00248 r = ::pathconf(path, name); 00249 else 00250 r = ::fpathconf(fd, name); 00251 if (r == -1) { 00252 if (errno != 0) 00253 throw Error(errno); 00254 else 00255 r = default_val; 00256 } 00257 return r; 00258 } 00259 00260 /** 00261 Calls pipe. 00262 */ 00263 /* static */ void File::pipe(File pf[2]) 00264 { 00265 int pfd[2]; 00266 00267 if (::pipe(pfd) == -1) 00268 throw Error(errno); 00269 pf[0].set(pfd[0]); 00270 pf[1].set(pfd[1]); 00271 } 00272 00273 /** 00274 Calls poll. 00275 */ 00276 /* static */ int poll(struct pollfd fdinfo[], nfds_t nfds, int timeout) 00277 { 00278 int r; 00279 00280 if ((r = ::poll(fdinfo, nfds, timeout)) == -1) 00281 throw Error(errno); 00282 return r; 00283 } 00284 00285 /** 00286 Calls pselect. 00287 */ 00288 /* static */ int pselect(int nfds, fd_set *readset, fd_set *writeset, fd_set *errorset, const struct timespec *timeout, const sigset_t *sigmask) 00289 { 00290 int r; 00291 00292 if ((r = ::pselect(nfds, readset, writeset, errorset, timeout, sigmask)) == -1) 00293 throw Error(errno); 00294 return r; 00295 } 00296 00297 /** 00298 Calls read or pread. 00299 */ 00300 ssize_t File::read(void *buf, size_t nbytes, off_t offset) 00301 { 00302 ssize_t n; 00303 00304 if (offset == -1) 00305 n = ::read(fd, buf, nbytes); 00306 else 00307 n = ::pread(fd, buf, nbytes, offset); 00308 if (n == -1) 00309 throw Error(errno); 00310 return n; 00311 } 00312 00313 /** 00314 Calls readlink. 00315 */ 00316 ssize_t File::readlink(char *buf, size_t bufsize) 00317 { 00318 ssize_t n; 00319 00320 if ((n = ::readlink(path, buf, bufsize)) == -1) 00321 throw Error(errno); 00322 return n; 00323 } 00324 00325 /** 00326 Calls readv. 00327 */ 00328 ssize_t File::readv(const struct iovec *iov, int iovcnt) 00329 { 00330 ssize_t n; 00331 00332 if ((n = ::readv(fd, iov, iovcnt)) == -1) 00333 throw Error(errno); 00334 return n; 00335 } 00336 00337 /** 00338 Calls rename. 00339 */ 00340 void File::rename(const char *newpath) 00341 { 00342 if (::rename(path, newpath) == -1) 00343 throw Error(errno); 00344 } 00345 00346 /** 00347 Calls lseek. 00348 */ 00349 off_t File::seek(off_t pos, int whence) 00350 { 00351 off_t p; 00352 00353 if ((p = ::lseek(fd, pos, whence)) == -1) 00354 throw Error(errno); 00355 return p; 00356 } 00357 00358 /** 00359 Calls select. 00360 */ 00361 /* static */ int select(int nfds, fd_set *readset, fd_set *writeset, fd_set *errorset, struct timeval *timeout) 00362 { 00363 int r; 00364 00365 if ((r = ::select(nfds, readset, writeset, errorset, timeout)) == -1) 00366 throw Error(errno); 00367 return r; 00368 } 00369 00370 /** 00371 Calls stat or fstat. 00372 */ 00373 void File::stat(struct stat *buf) 00374 { 00375 int r; 00376 00377 if (fd == -1) 00378 r = ::stat(path, buf); 00379 else 00380 r = ::fstat(fd, buf); 00381 if (r == -1) 00382 throw Error(errno); 00383 } 00384 00385 /** 00386 Calls statvfs or fstatvfs, or whatever nonportable substitute has been defined. 00387 */ 00388 void File::statvfs(struct STATVFS_NAME *buf) 00389 { 00390 int r; 00391 00392 if (fd == -1) 00393 r = ::STATVFS_NAME(path, buf); 00394 else 00395 r = ::FSTATVFS_NAME(fd, buf); 00396 if (r == -1) 00397 throw Error(errno); 00398 } 00399 00400 /** 00401 Calls symlink. 00402 */ 00403 void File::symlink(const char *newpath) 00404 { 00405 if (::symlink(path, newpath) == -1) 00406 throw Error(errno); 00407 } 00408 00409 /** 00410 Calls sync. 00411 */ 00412 /* static */ void File::sync(void) 00413 { 00414 ::sync(); 00415 } 00416 00417 /** 00418 Calls truncate or ftruncate. 00419 */ 00420 void File::truncate(off_t length) 00421 { 00422 int r; 00423 00424 if (fd == -1) 00425 r = ::truncate(path, length); 00426 else 00427 r = ::ftruncate(fd, length); 00428 if (r == -1) 00429 throw Error(errno); 00430 } 00431 00432 /** 00433 Calls unlink. 00434 */ 00435 void File::unlink(void) 00436 { 00437 if (::unlink(path) == -1) 00438 throw Error(errno); 00439 } 00440 00441 /** 00442 Calls utime. 00443 */ 00444 void File::utime(const struct utimbuf *timbuf) 00445 { 00446 if (::utime(path, timbuf) == -1) 00447 throw Error(errno); 00448 } 00449 00450 /** 00451 Calls write or pwrite. 00452 */ 00453 ssize_t File::write(const void *buf, size_t nbytes, off_t offset) 00454 { 00455 ssize_t n; 00456 00457 if (offset == -1) 00458 n = ::write(fd, buf, nbytes); 00459 else 00460 n = ::pwrite(fd, buf, nbytes, offset); 00461 if (n == -1) 00462 throw Error(errno); 00463 return n; 00464 } 00465 00466 /** 00467 Calls writev. 00468 */ 00469 ssize_t File::writev(const struct iovec *iov, int iovcnt) 00470 { 00471 ssize_t n; 00472 00473 if ((n = ::writev(fd, iov, iovcnt)) == -1) 00474 throw Error(errno); 00475 return n; 00476 }