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

Comparing libeio/eio.c (file contents):
Revision 1.120 by root, Tue Apr 24 18:47:50 2012 UTC vs.
Revision 1.128 by root, Mon Feb 18 03:16:30 2013 UTC

4 * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann <libeio@schmorp.de> 4 * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann <libeio@schmorp.de>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without modifica- 7 * Redistribution and use in source and binary forms, with or without modifica-
8 * tion, are permitted provided that the following conditions are met: 8 * tion, are permitted provided that the following conditions are met:
9 * 9 *
10 * 1. Redistributions of source code must retain the above copyright notice, 10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer. 11 * this list of conditions and the following disclaimer.
12 * 12 *
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19 * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
132 #define sync() EIO_ENOSYS () 132 #define sync() EIO_ENOSYS ()
133 #define readlink(path,buf,s) EIO_ENOSYS () 133 #define readlink(path,buf,s) EIO_ENOSYS ()
134 #define statvfs(path,buf) EIO_ENOSYS () 134 #define statvfs(path,buf) EIO_ENOSYS ()
135 #define fstatvfs(fd,buf) EIO_ENOSYS () 135 #define fstatvfs(fd,buf) EIO_ENOSYS ()
136 136
137 #define pread(fd,buf,count,offset) eio__pread (fd, buf, count, offset)
138 #define pwrite(fd,buf,count,offset) eio__pwrite (fd, buf, count, offset)
139
140 #if __GNUC__
141 typedef long long eio_off_t; /* signed for compatibility to msvc */
142 #else
143 typedef __int64 eio_off_t; /* unsigned not supported by msvc */
144 #endif
145
146 static eio_ssize_t
147 eio__pread (int fd, void *buf, eio_ssize_t count, eio_off_t offset)
148 {
149 OVERLAPPED o = { 0 };
150 DWORD got;
151
152 o.Offset = offset;
153 o.OffsetHigh = offset >> 32;
154
155 return ReadFile ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd), buf, count, &got, &o)
156 ? got : -1;
157 }
158
159 static eio_ssize_t
160 eio__pwrite (int fd, void *buf, eio_ssize_t count, eio_off_t offset)
161 {
162 OVERLAPPED o = { 0 };
163 DWORD got;
164
165 o.Offset = offset;
166 o.OffsetHigh = offset >> 32;
167
168 return WriteFile ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd), buf, count, &got, &o)
169 ? got : -1;
170 }
171
137 /* rename() uses MoveFile, which fails to overwrite */ 172 /* rename() uses MoveFile, which fails to overwrite */
138 #define rename(old,neu) eio__rename (old, neu) 173 #define rename(old,neu) eio__rename (old, neu)
139 174
140 static int 175 static int
141 eio__rename (const char *old, const char *neu) 176 eio__rename (const char *old, const char *neu)
196 231
197#else 232#else
198 233
199 #include <sys/time.h> 234 #include <sys/time.h>
200 #include <sys/select.h> 235 #include <sys/select.h>
201 #include <sys/statvfs.h>
202 #include <unistd.h> 236 #include <unistd.h>
203 #include <signal.h> 237 #include <signal.h>
204 #include <dirent.h> 238 #include <dirent.h>
239
240 #ifdef ANDROID
241 #include <sys/vfs.h>
242 #define statvfs statfs
243 #define fstatvfs fstatfs
244 #include <asm/page.h> /* supposedly limits.h does #define PAGESIZE PAGESIZE */
245 #else
246 #include <sys/statvfs.h>
247 #endif
205 248
206 #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES 249 #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES
207 #include <sys/mman.h> 250 #include <sys/mman.h>
208 #endif 251 #endif
209 252
281#endif 324#endif
282 325
283/* buffer size for various temporary buffers */ 326/* buffer size for various temporary buffers */
284#define EIO_BUFSIZE 65536 327#define EIO_BUFSIZE 65536
285 328
286#define dBUF \ 329#define dBUF \
287 char *eio_buf = malloc (EIO_BUFSIZE); \ 330 char *eio_buf = malloc (EIO_BUFSIZE); \
288 errno = ENOMEM; \ 331 errno = ENOMEM; \
289 if (!eio_buf) \ 332 if (!eio_buf) \
290 return -1 333 return -1
291 334
379static xmutex_t wrklock; 422static xmutex_t wrklock;
380static xmutex_t reslock; 423static xmutex_t reslock;
381static xmutex_t reqlock; 424static xmutex_t reqlock;
382static xcond_t reqwait; 425static xcond_t reqwait;
383 426
384#if !HAVE_PREADWRITE
385/*
386 * make our pread/pwrite emulation safe against themselves, but not against
387 * normal read/write by using a mutex. slows down execution a lot,
388 * but that's your problem, not mine.
389 */
390static xmutex_t preadwritelock;
391#endif
392
393typedef struct etp_worker 427typedef struct etp_worker
394{ 428{
395 struct tmpbuf tmpbuf; 429 struct tmpbuf tmpbuf;
396 430
397 /* locked by wrklock */ 431 /* locked by wrklock */
576 /*TODO*/ 610 /*TODO*/
577 assert (("unable to allocate worker thread data", wrk)); 611 assert (("unable to allocate worker thread data", wrk));
578 612
579 X_LOCK (wrklock); 613 X_LOCK (wrklock);
580 614
581 if (thread_create (&wrk->tid, etp_proc, (void *)wrk)) 615 if (xthread_create (&wrk->tid, etp_proc, (void *)wrk))
582 { 616 {
583 wrk->prev = &wrk_first; 617 wrk->prev = &wrk_first;
584 wrk->next = wrk_first.next; 618 wrk->next = wrk_first.next;
585 wrk_first.next->prev = wrk; 619 wrk_first.next->prev = wrk;
586 wrk_first.next = wrk; 620 wrk_first.next = wrk;
943} 977}
944 978
945/*****************************************************************************/ 979/*****************************************************************************/
946/* work around various missing functions */ 980/* work around various missing functions */
947 981
948#if !HAVE_PREADWRITE
949# undef pread
950# undef pwrite
951# define pread eio__pread
952# define pwrite eio__pwrite
953
954static eio_ssize_t
955eio__pread (int fd, void *buf, size_t count, off_t offset)
956{
957 eio_ssize_t res;
958 off_t ooffset;
959
960 X_LOCK (preadwritelock);
961 ooffset = lseek (fd, 0, SEEK_CUR);
962 lseek (fd, offset, SEEK_SET);
963 res = read (fd, buf, count);
964 lseek (fd, ooffset, SEEK_SET);
965 X_UNLOCK (preadwritelock);
966
967 return res;
968}
969
970static eio_ssize_t
971eio__pwrite (int fd, void *buf, size_t count, off_t offset)
972{
973 eio_ssize_t res;
974 off_t ooffset;
975
976 X_LOCK (preadwritelock);
977 ooffset = lseek (fd, 0, SEEK_CUR);
978 lseek (fd, offset, SEEK_SET);
979 res = write (fd, buf, count);
980 lseek (fd, ooffset, SEEK_SET);
981 X_UNLOCK (preadwritelock);
982
983 return res;
984}
985#endif
986
987#ifndef HAVE_UTIMES 982#ifndef HAVE_UTIMES
988 983
989# undef utimes 984# undef utimes
990# define utimes(path,times) eio__utimes (path, times) 985# define utimes(path,times) eio__utimes (path, times)
991 986
1429 1424
1430 if (fd >= 0) 1425 if (fd >= 0)
1431 { 1426 {
1432 sprintf (tmp1, "/proc/self/fd/%d", fd); 1427 sprintf (tmp1, "/proc/self/fd/%d", fd);
1433 req->result = readlink (tmp1, res, PATH_MAX); 1428 req->result = readlink (tmp1, res, PATH_MAX);
1429 /* here we should probably stat the open file and the disk file, to make sure they still match */
1434 close (fd); 1430 close (fd);
1435
1436 /* here we should probably stat the open file and the disk file, to make sure they still match */
1437 1431
1438 if (req->result > 0) 1432 if (req->result > 0)
1439 goto done; 1433 goto done;
1440 } 1434 }
1441 else if (errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EIO) 1435 else if (errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EIO)
1442 return; 1436 return -1;
1443 } 1437 }
1444#endif 1438#endif
1445#endif 1439#endif
1446 1440
1447 if (*rel != '/') 1441 if (*rel != '/')
1931 #ifdef DT_FIFO 1925 #ifdef DT_FIFO
1932 case DT_FIFO: ent->type = EIO_DT_FIFO; break; 1926 case DT_FIFO: ent->type = EIO_DT_FIFO; break;
1933 #endif 1927 #endif
1934 #ifdef DT_CHR 1928 #ifdef DT_CHR
1935 case DT_CHR: ent->type = EIO_DT_CHR; break; 1929 case DT_CHR: ent->type = EIO_DT_CHR; break;
1936 #endif 1930 #endif
1937 #ifdef DT_MPC 1931 #ifdef DT_MPC
1938 case DT_MPC: ent->type = EIO_DT_MPC; break; 1932 case DT_MPC: ent->type = EIO_DT_MPC; break;
1939 #endif 1933 #endif
1940 #ifdef DT_DIR 1934 #ifdef DT_DIR
1941 case DT_DIR: ent->type = EIO_DT_DIR; break; 1935 case DT_DIR: ent->type = EIO_DT_DIR; break;
1942 #endif 1936 #endif
1943 #ifdef DT_NAM 1937 #ifdef DT_NAM
1944 case DT_NAM: ent->type = EIO_DT_NAM; break; 1938 case DT_NAM: ent->type = EIO_DT_NAM; break;
1945 #endif 1939 #endif
1946 #ifdef DT_BLK 1940 #ifdef DT_BLK
1947 case DT_BLK: ent->type = EIO_DT_BLK; break; 1941 case DT_BLK: ent->type = EIO_DT_BLK; break;
1948 #endif 1942 #endif
1949 #ifdef DT_MPB 1943 #ifdef DT_MPB
1950 case DT_MPB: ent->type = EIO_DT_MPB; break; 1944 case DT_MPB: ent->type = EIO_DT_MPB; break;
1951 #endif 1945 #endif
1952 #ifdef DT_REG 1946 #ifdef DT_REG
1953 case DT_REG: ent->type = EIO_DT_REG; break; 1947 case DT_REG: ent->type = EIO_DT_REG; break;
1954 #endif 1948 #endif
1955 #ifdef DT_NWK 1949 #ifdef DT_NWK
1956 case DT_NWK: ent->type = EIO_DT_NWK; break; 1950 case DT_NWK: ent->type = EIO_DT_NWK; break;
1957 #endif 1951 #endif
1958 #ifdef DT_CMP 1952 #ifdef DT_CMP
1959 case DT_CMP: ent->type = EIO_DT_CMP; break; 1953 case DT_CMP: ent->type = EIO_DT_CMP; break;
1960 #endif 1954 #endif
1961 #ifdef DT_LNK 1955 #ifdef DT_LNK
1962 case DT_LNK: ent->type = EIO_DT_LNK; break; 1956 case DT_LNK: ent->type = EIO_DT_LNK; break;
1963 #endif 1957 #endif
1964 #ifdef DT_SOCK 1958 #ifdef DT_SOCK
1965 case DT_SOCK: ent->type = EIO_DT_SOCK; break; 1959 case DT_SOCK: ent->type = EIO_DT_SOCK; break;
2240 free (req); 2234 free (req);
2241 2235
2242 X_LOCK (wrklock); 2236 X_LOCK (wrklock);
2243 etp_worker_free (self); 2237 etp_worker_free (self);
2244 X_UNLOCK (wrklock); 2238 X_UNLOCK (wrklock);
2239
2240 return 0;
2245} 2241}
2246 2242
2247/*****************************************************************************/ 2243/*****************************************************************************/
2248 2244
2249int ecb_cold 2245int ecb_cold
2250eio_init (void (*want_poll)(void), void (*done_poll)(void)) 2246eio_init (void (*want_poll)(void), void (*done_poll)(void))
2251{ 2247{
2252#if !HAVE_PREADWRITE
2253 X_MUTEX_CREATE (preadwritelock);
2254#endif
2255
2256 return etp_init (want_poll, done_poll); 2248 return etp_init (want_poll, done_poll);
2257} 2249}
2258 2250
2259ecb_inline void 2251ecb_inline void
2260eio_api_destroy (eio_req *req) 2252eio_api_destroy (eio_req *req)
2261{ 2253{
2262 free (req); 2254 free (req);
2263} 2255}
2264 2256
2265#define REQ(rtype) \ 2257#define REQ(rtype) \
2266 eio_req *req; \ 2258 eio_req *req; \
2267 \ 2259 \
2268 req = (eio_req *)calloc (1, sizeof *req); \ 2260 req = (eio_req *)calloc (1, sizeof *req); \
2269 if (!req) \ 2261 if (!req) \
2270 return 0; \ 2262 return 0; \
2284 { \ 2276 { \
2285 eio_api_destroy (req); \ 2277 eio_api_destroy (req); \
2286 return 0; \ 2278 return 0; \
2287 } 2279 }
2288 2280
2281#define SINGLEDOT(ptr) (0[(char *)(ptr)] == '.' && !1[(char *)(ptr)])
2282
2289static void 2283static void
2290eio_execute (etp_worker *self, eio_req *req) 2284eio_execute (etp_worker *self, eio_req *req)
2291{ 2285{
2292#if HAVE_AT 2286#if HAVE_AT
2293 int dirfd; 2287 int dirfd;
2348 case EIO_CHMOD: req->result = fchmodat (dirfd, req->ptr1, (mode_t)req->int2, 0); break; 2342 case EIO_CHMOD: req->result = fchmodat (dirfd, req->ptr1, (mode_t)req->int2, 0); break;
2349 case EIO_TRUNCATE: req->result = eio__truncateat (dirfd, req->ptr1, req->offs); break; 2343 case EIO_TRUNCATE: req->result = eio__truncateat (dirfd, req->ptr1, req->offs); break;
2350 case EIO_OPEN: req->result = openat (dirfd, req->ptr1, req->int1, (mode_t)req->int2); break; 2344 case EIO_OPEN: req->result = openat (dirfd, req->ptr1, req->int1, (mode_t)req->int2); break;
2351 2345
2352 case EIO_UNLINK: req->result = unlinkat (dirfd, req->ptr1, 0); break; 2346 case EIO_UNLINK: req->result = unlinkat (dirfd, req->ptr1, 0); break;
2353 case EIO_RMDIR: req->result = unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break; 2347 case EIO_RMDIR: /* complications arise because "." cannot be removed, so we might have to expand */
2348 req->result = req->wd && SINGLEDOT (req->ptr1)
2349 ? rmdir (req->wd->str)
2350 : unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break;
2354 case EIO_MKDIR: req->result = mkdirat (dirfd, req->ptr1, (mode_t)req->int2); break; 2351 case EIO_MKDIR: req->result = mkdirat (dirfd, req->ptr1, (mode_t)req->int2); break;
2355 case EIO_RENAME: req->result = renameat (dirfd, req->ptr1, WD2FD ((eio_wd)req->int3), req->ptr2); break; 2352 case EIO_RENAME: /* complications arise because "." cannot be renamed, so we might have to expand */
2353 req->result = req->wd && SINGLEDOT (req->ptr1)
2354 ? rename (req->wd->str, req->ptr2)
2355 : renameat (dirfd, req->ptr1, WD2FD ((eio_wd)req->int3), req->ptr2); break;
2356 case EIO_LINK: req->result = linkat (dirfd, req->ptr1, WD2FD ((eio_wd)req->int3), req->ptr2, 0); break; 2356 case EIO_LINK: req->result = linkat (dirfd, req->ptr1, WD2FD ((eio_wd)req->int3), req->ptr2, 0); break;
2357 case EIO_SYMLINK: req->result = symlinkat (req->ptr1, dirfd, req->ptr2); break; 2357 case EIO_SYMLINK: req->result = symlinkat (req->ptr1, dirfd, req->ptr2); break;
2358 case EIO_MKNOD: req->result = mknodat (dirfd, req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break; 2358 case EIO_MKNOD: req->result = mknodat (dirfd, req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break;
2359 case EIO_READLINK: ALLOC (PATH_MAX); 2359 case EIO_READLINK: ALLOC (PATH_MAX);
2360 req->result = readlinkat (dirfd, req->ptr1, req->ptr2, PATH_MAX); break; 2360 req->result = readlinkat (dirfd, req->ptr1, req->ptr2, PATH_MAX); break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines