ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libeio/eio.c
(Generate patch)

Comparing libeio/eio.c (file contents):
Revision 1.104 by root, Mon Sep 26 16:54:25 2011 UTC vs.
Revision 1.106 by root, Mon Sep 26 20:19:08 2011 UTC

58#include <sys/stat.h> 58#include <sys/stat.h>
59#include <limits.h> 59#include <limits.h>
60#include <fcntl.h> 60#include <fcntl.h>
61#include <assert.h> 61#include <assert.h>
62 62
63#if _POSIX_VERSION >= 200809L
64# define HAVE_AT 1
65#else
66# define HAVE_AT 0
67#endif
68
63/* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */ 69/* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */
64/* intptr_t only comes from stdint.h, says idiot openbsd coder */ 70/* intptr_t only comes from stdint.h, says idiot openbsd coder */
65#if HAVE_STDINT_H 71#if HAVE_STDINT_H
66# include <stdint.h> 72# include <stdint.h>
67#endif 73#endif
584} 590}
585 591
586static void ecb_cold 592static void ecb_cold
587etp_end_thread (void) 593etp_end_thread (void)
588{ 594{
589 eio_req *req = calloc (1, sizeof (eio_req)); 595 eio_req *req = calloc (1, sizeof (eio_req)); /* will be freed by worker */
590 596
591 req->type = -1; 597 req->type = -1;
592 req->pri = ETP_PRI_MAX - ETP_PRI_MIN; 598 req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
593 599
594 X_LOCK (reqlock); 600 X_LOCK (reqlock);
1963/*****************************************************************************/ 1969/*****************************************************************************/
1964/* working directory stuff */ 1970/* working directory stuff */
1965 1971
1966#if HAVE_AT 1972#if HAVE_AT
1967 1973
1968#define WD2FD(wd) (wd ? ((int)wd) - 1 : AT_FDCWD) 1974#define WD2FD(wd) ((wd) ? ((int)(long)(wd)) - 1 : AT_FDCWD)
1975
1976#ifndef O_SEARCH
1977# define O_SEARCH O_RDONLY
1978#endif
1969 1979
1970eio_wd 1980eio_wd
1971eio_wd_open_sync (eio_wd wd, const char *path) 1981eio_wd_open_sync (eio_wd wd, const char *path)
1972{ 1982{
1973 int fd = openat (WD2FD (wd), path, O_CLOEXEC | O_SEARCH | O_DIRECTORY); 1983 int fd = openat (WD2FD (wd), path, O_CLOEXEC | O_SEARCH | O_DIRECTORY);
1974 1984
1975 return fd >= 0 ? (eio_wd)(fd + 1) : EIO_INVALID_WD; 1985 return fd >= 0 ? (eio_wd)(long)(fd + 1) : EIO_INVALID_WD;
1986}
1987
1988static eio_wd
1989eio__wd_open_sync (struct tmpbuf *tmpbuf, eio_wd wd, const char *path)
1990{
1991 return eio_wd_open_sync (wd, path);
1976} 1992}
1977 1993
1978void 1994void
1979eio_wd_close_sync (eio_wd wd) 1995eio_wd_close_sync (eio_wd wd)
1980{ 1996{
1981 int fd = WD2FD (wd); 1997 int fd = WD2FD (wd);
1982 1998
1983 if (fd >= 0) 1999 if (fd >= 0)
1984 close (fd); 2000 close (fd);
2001}
2002
2003static int
2004eio__truncateat (int dirfd, const char *path, off_t length)
2005{
2006 int fd = openat (dirfd, path, O_WRONLY | O_CLOEXEC);
2007 int res;
2008
2009 if (fd < 0)
2010 return fd;
2011
2012 res = ftruncate (fd, length);
2013 close (fd);
2014 return res;
2015}
2016
2017static int
2018eio__statvfsat (int dirfd, const char *path, struct statvfs *buf)
2019{
2020 int fd = openat (dirfd, path, O_SEARCH | O_CLOEXEC);
2021 int res;
2022
2023 if (fd < 0)
2024 return fd;
2025
2026 res = fstatvfs (fd, buf);
2027 close (fd);
2028 return res;
2029
1985} 2030}
1986 2031
1987#else 2032#else
1988 2033
1989/* on legacy systems, we represent the working directories simply by their path strings */ 2034/* on legacy systems, we represent the working directories simply by their path strings */
2006 2051
2007 return res; 2052 return res;
2008 } 2053 }
2009} 2054}
2010 2055
2011eio_wd 2056static eio_wd
2012eio__wd_open_sync (struct tmpbuf *tmpbuf, eio_wd wd, const char *path) 2057eio__wd_open_sync (struct tmpbuf *tmpbuf, eio_wd wd, const char *path)
2013{ 2058{
2014 if (*path == '/') /* absolute paths ignore wd */ 2059 if (*path == '/') /* absolute paths ignore wd */
2015 path = strdup (path); 2060 path = strdup (path);
2016 else if (path [0] == '.' && !path [1]) /* special case '.', as it is common */ 2061 else if (path [0] == '.' && !path [1]) /* special case '.', as it is common */
2231 switch (req->type) 2276 switch (req->type)
2232 { 2277 {
2233 case EIO_WD_OPEN: req->wd = eio__wd_open_sync (&self->tmpbuf, req->wd, req->ptr1); 2278 case EIO_WD_OPEN: req->wd = eio__wd_open_sync (&self->tmpbuf, req->wd, req->ptr1);
2234 req->result = req->wd == EIO_INVALID_WD ? -1 : 0; 2279 req->result = req->wd == EIO_INVALID_WD ? -1 : 0;
2235 break; 2280 break;
2236 case EIO_WD_CLOSE: eio_wd_close_sync (req->wd); break; 2281 case EIO_WD_CLOSE: req->result = 0;
2282 eio_wd_close_sync (req->wd); break;
2237 2283
2238 case EIO_READ: ALLOC (req->size); 2284 case EIO_READ: ALLOC (req->size);
2239 req->result = req->offs >= 0 2285 req->result = req->offs >= 0
2240 ? pread (req->int1, req->ptr2, req->size, req->offs) 2286 ? pread (req->int1, req->ptr2, req->size, req->offs)
2241 : read (req->int1, req->ptr2, req->size); break; 2287 : read (req->int1, req->ptr2, req->size); break;
2245 2291
2246 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break; 2292 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
2247 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break; 2293 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;
2248 2294
2249#if HAVE_AT 2295#if HAVE_AT
2250 case EIO_GETPATH: abort (); 2296
2251 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2297 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2252 req->result = fstatat (dirfd, path, (EIO_STRUCT_STAT *)req->ptr2); break; 2298 req->result = fstatat (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, 0); break;
2253 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2299 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2254 req->result = lstat (dirfd, path, (EIO_STRUCT_STAT *)req->ptr2); break; 2300 req->result = fstatat (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, AT_SYMLINK_NOFOLLOW); break;
2255#if 0/*D*/ 2301 case EIO_CHOWN: req->result = fchownat (dirfd, req->ptr1, req->int2, req->int3, 0); break;
2302 case EIO_CHMOD: req->result = fchmodat (dirfd, req->ptr1, (mode_t)req->int2, 0); break;
2303 case EIO_TRUNCATE: req->result = eio__truncateat (dirfd, req->ptr1, req->offs); break;
2304 case EIO_OPEN: req->result = openat (dirfd, req->ptr1, req->int1, (mode_t)req->int2); break;
2305
2306 case EIO_UNLINK: req->result = unlinkat (dirfd, req->ptr1, 0); break;
2307 case EIO_RMDIR: req->result = unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break;
2308 case EIO_MKDIR: req->result = mkdirat (dirfd, req->ptr1, (mode_t)req->int2); break;
2309 case EIO_RENAME: req->result = renameat (dirfd, req->ptr1, WD2FD (req->int3), req->ptr2); break;
2310 case EIO_LINK: req->result = linkat (dirfd, req->ptr1, WD2FD (req->int3), req->ptr2, 0); break;
2311 case EIO_SYMLINK: req->result = symlinkat (req->ptr1, dirfd, req->ptr2); break;
2312 case EIO_MKNOD: req->result = mknodat (dirfd, req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break;
2313 case EIO_READLINK: ALLOC (PATH_MAX);
2314 req->result = readlinkat (dirfd, req->ptr1, req->ptr2, PATH_MAX); break;
2256 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS)); 2315 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2257 req->result = statvfs (dirfd, path, (EIO_STRUCT_STATVFS *)req->ptr2); break; 2316 req->result = eio__statvfsat (dirfd, req->ptr1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
2258#endif 2317 case EIO_UTIME:
2259 case EIO_CHOWN: req->result = chown (dirfd, path, req->int2, req->int3); break; 2318 case EIO_FUTIME:
2260 case EIO_CHMOD: req->result = chmod (dirfd, path, (mode_t)req->int2); break; 2319 {
2261 case EIO_TRUNCATE: req->result = truncate (dirfd, path, req->offs); break; 2320 struct timespec ts[2];
2262 case EIO_OPEN: req->result = open (dirfd, path, req->int1, (mode_t)req->int2); break; 2321 struct timespec *times;
2263 2322
2264 case EIO_UNLINK: req->result = unlink (dirfd, path); break; 2323 if (req->nv1 != -1. || req->nv2 != -1.)
2265 case EIO_RMDIR: req->result = rmdir (dirfd, path); break; 2324 {
2266 case EIO_MKDIR: req->result = mkdir (dirfd, path, (mode_t)req->int2); break; 2325 ts[0].tv_sec = req->nv1;
2267 case EIO_RENAME: req->result = rename (dirfd, path, req->ptr2); break; 2326 ts[0].tv_nsec = (req->nv1 - ts[0].tv_sec) * 1e9;
2268 case EIO_LINK: req->result = link (dirfd, path, req->ptr2); break; 2327 ts[1].tv_sec = req->nv2;
2269 case EIO_SYMLINK: req->result = symlink (dirfd, path, req->ptr2); break; 2328 ts[1].tv_nsec = (req->nv2 - ts[1].tv_sec) * 1e9;
2270 case EIO_MKNOD: req->result = mknod (dirfd, path, (mode_t)req->int2, (dev_t)req->offs); break; 2329
2330 times = ts;
2331 }
2332 else
2333 times = 0;
2334
2335 req->result = req->type == EIO_FUTIME
2336 ? futimens (req->int1, times)
2337 : utimensat (dirfd, req->ptr1, times, 0);
2338 }
2339 break;
2340
2271#else 2341#else
2342
2272 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2343 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2273 req->result = stat (path , (EIO_STRUCT_STAT *)req->ptr2); break; 2344 req->result = stat (path , (EIO_STRUCT_STAT *)req->ptr2); break;
2274 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2345 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2275 req->result = lstat (path , (EIO_STRUCT_STAT *)req->ptr2); break; 2346 req->result = lstat (path , (EIO_STRUCT_STAT *)req->ptr2); break;
2276 case EIO_CHOWN: req->result = chown (path , req->int2, req->int3); break; 2347 case EIO_CHOWN: req->result = chown (path , req->int2, req->int3); break;
2283 case EIO_MKDIR: req->result = mkdir (path , (mode_t)req->int2); break; 2354 case EIO_MKDIR: req->result = mkdir (path , (mode_t)req->int2); break;
2284 case EIO_RENAME: req->result = rename (path , req->ptr2); break; 2355 case EIO_RENAME: req->result = rename (path , req->ptr2); break;
2285 case EIO_LINK: req->result = link (path , req->ptr2); break; 2356 case EIO_LINK: req->result = link (path , req->ptr2); break;
2286 case EIO_SYMLINK: req->result = symlink (path , req->ptr2); break; 2357 case EIO_SYMLINK: req->result = symlink (path , req->ptr2); break;
2287 case EIO_MKNOD: req->result = mknod (path , (mode_t)req->int2, (dev_t)req->offs); break; 2358 case EIO_MKNOD: req->result = mknod (path , (mode_t)req->int2, (dev_t)req->offs); break;
2288
2289 case EIO_READLINK: ALLOC (PATH_MAX); 2359 case EIO_READLINK: ALLOC (PATH_MAX);
2290 req->result = readlink (path, req->ptr2, PATH_MAX); break; 2360 req->result = readlink (path, req->ptr2, PATH_MAX); break;
2361 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2362 req->result = statvfs (path , (EIO_STRUCT_STATVFS *)req->ptr2); break;
2363
2364 case EIO_UTIME:
2365 case EIO_FUTIME:
2366 {
2367 struct timeval tv[2];
2368 struct timeval *times;
2369
2370 if (req->nv1 != -1. || req->nv2 != -1.)
2371 {
2372 tv[0].tv_sec = req->nv1;
2373 tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1e6;
2374 tv[1].tv_sec = req->nv2;
2375 tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1e6;
2376
2377 times = tv;
2378 }
2379 else
2380 times = 0;
2381
2382 req->result = req->type == EIO_FUTIME
2383 ? futimes (req->int1, times)
2384 : utimes (req->ptr1, times);
2385 }
2386 break;
2387
2291#endif 2388#endif
2292 2389
2293 case EIO_REALPATH: if (0 <= (req->result = eio__realpath (&self->tmpbuf, req->wd, req->ptr1))) 2390 case EIO_REALPATH: if (0 <= (req->result = eio__realpath (&self->tmpbuf, req->wd, req->ptr1)))
2294 { 2391 {
2295 ALLOC (req->result); 2392 ALLOC (req->result);
2296 memcpy (req->ptr2, self->tmpbuf.ptr, req->result); 2393 memcpy (req->ptr2, self->tmpbuf.ptr, req->result);
2297 } 2394 }
2298 break; 2395 break;
2299
2300 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS)); /*D*/
2301 req->result = statvfs (path , (EIO_STRUCT_STATVFS *)req->ptr2); break;
2302 2396
2303 case EIO_FSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2397 case EIO_FSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2304 req->result = fstat (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break; 2398 req->result = fstat (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;
2305 2399
2306 case EIO_FSTATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS)); 2400 case EIO_FSTATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2338 req->result = select (0, 0, 0, 0, &tv); 2432 req->result = select (0, 0, 0, 0, &tv);
2339 } 2433 }
2340#endif 2434#endif
2341 break; 2435 break;
2342 2436
2343 case EIO_UTIME:
2344 case EIO_FUTIME:
2345 {
2346 struct timeval tv[2];
2347 struct timeval *times;
2348
2349 if (req->nv1 != -1. || req->nv2 != -1.)
2350 {
2351 tv[0].tv_sec = req->nv1;
2352 tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1000000.;
2353 tv[1].tv_sec = req->nv2;
2354 tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1000000.;
2355
2356 times = tv;
2357 }
2358 else
2359 times = 0;
2360
2361 req->result = req->type == EIO_FUTIME
2362 ? futimes (req->int1, times)
2363 : utimes (req->ptr1, times);
2364 }
2365 break;
2366
2367 case EIO_GROUP: 2437 case EIO_GROUP:
2368 abort (); /* handled in eio_request */ 2438 abort (); /* handled in eio_request */
2369 2439
2370 case EIO_NOP: 2440 case EIO_NOP:
2371 req->result = 0; 2441 req->result = 0;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines