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

Comparing libeio/eio.c (file contents):
Revision 1.76 by root, Tue Jul 5 09:24:12 2011 UTC vs.
Revision 1.77 by root, Tue Jul 5 14:02:15 2011 UTC

835} 835}
836 836
837/*****************************************************************************/ 837/*****************************************************************************/
838/* work around various missing functions */ 838/* work around various missing functions */
839 839
840#if _POSIX_VERSION < 200809L
841# define realpath(path,resolved_path) (errno = ENOSYS, 0)
842#endif
843
844#if !HAVE_PREADWRITE 840#if !HAVE_PREADWRITE
845# undef pread 841# undef pread
846# undef pwrite 842# undef pwrite
847# define pread eio__pread 843# define pread eio__pread
848# define pwrite eio__pwrite 844# define pwrite eio__pwrite
1119 count -= cnt; 1115 count -= cnt;
1120 } 1116 }
1121 } 1117 }
1122 1118
1123 return res; 1119 return res;
1120}
1121
1122#ifdef PAGESIZE
1123# define eio_pagesize() PAGESIZE
1124#else
1125static intptr_t
1126eio_pagesize (void)
1127{
1128 static intptr_t page;
1129
1130 if (!page)
1131 page = sysconf (_SC_PAGESIZE);
1132
1133 return page;
1134}
1135#endif
1136
1137static void
1138eio_page_align (void **addr, size_t *length)
1139{
1140 intptr_t mask = eio_pagesize () - 1;
1141
1142 /* round down addr */
1143 intptr_t adj = mask & (intptr_t)*addr;
1144
1145 *addr = (void *)((intptr_t)*addr - adj);
1146 *length += adj;
1147
1148 /* round up length */
1149 *length = (*length + mask) & ~mask;
1150}
1151
1152#if !_POSIX_MEMLOCK
1153# define eio__mlockall(a) ((errno = ENOSYS), -1)
1154#else
1155
1156static int
1157eio__mlockall (int flags)
1158{
1159 #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7
1160 extern int mallopt (int, int);
1161 mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */
1162 #endif
1163
1164 if (EIO_MCL_CURRENT != MCL_CURRENT
1165 || EIO_MCL_FUTURE != MCL_FUTURE)
1166 {
1167 flags = 0
1168 | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0)
1169 | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0);
1170 }
1171
1172 return mlockall (flags);
1173}
1174#endif
1175
1176#if !_POSIX_MEMLOCK_RANGE
1177# define eio__mlock(a,b) ((errno = ENOSYS), -1)
1178#else
1179
1180static int
1181eio__mlock (void *addr, size_t length)
1182{
1183 eio_page_align (&addr, &length);
1184
1185 return mlock (addr, length);
1186}
1187
1188#endif
1189
1190#if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
1191# define eio__msync(a,b,c) ((errno = ENOSYS), -1)
1192#else
1193
1194static int
1195eio__msync (void *mem, size_t len, int flags)
1196{
1197 eio_page_align (&mem, &len);
1198
1199 if (EIO_MS_ASYNC != MS_SYNC
1200 || EIO_MS_INVALIDATE != MS_INVALIDATE
1201 || EIO_MS_SYNC != MS_SYNC)
1202 {
1203 flags = 0
1204 | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0)
1205 | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0)
1206 | (flags & EIO_MS_SYNC ? MS_SYNC : 0);
1207 }
1208
1209 return msync (mem, len, flags);
1210}
1211
1212#endif
1213
1214static int
1215eio__mtouch (eio_req *req)
1216{
1217 void *mem = req->ptr2;
1218 size_t len = req->size;
1219 int flags = req->int1;
1220
1221 eio_page_align (&mem, &len);
1222
1223 {
1224 intptr_t addr = (intptr_t)mem;
1225 intptr_t end = addr + len;
1226 intptr_t page = eio_pagesize ();
1227
1228 if (addr < end)
1229 if (flags & EIO_MT_MODIFY) /* modify */
1230 do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req));
1231 else
1232 do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req));
1233 }
1234
1235 return 0;
1236}
1237
1238/*****************************************************************************/
1239/* requests implemented outside eio_execute, because they are so large */
1240
1241static void
1242eio__realpath (eio_req *req, etp_worker *self)
1243{
1244 char *rel = req->ptr1;
1245 char *res;
1246 char *tmp1, *tmp2;
1247#if SYMLOOP_MAX > 32
1248 int links = SYMLOOP_MAX;
1249#else
1250 int links = 32;
1251#endif
1252
1253 req->result = -1;
1254
1255 errno = EINVAL;
1256 if (!rel)
1257 return;
1258
1259 errno = ENOENT;
1260 if (!*rel)
1261 return;
1262
1263 if (!req->ptr2)
1264 {
1265 X_LOCK (wrklock);
1266 req->flags |= EIO_FLAG_PTR2_FREE;
1267 X_UNLOCK (wrklock);
1268 req->ptr2 = malloc (PATH_MAX * 3);
1269
1270 errno = ENOMEM;
1271 if (!req->ptr2)
1272 return;
1273 }
1274
1275 res = req->ptr2;
1276 tmp1 = res + PATH_MAX;
1277 tmp2 = tmp1 + PATH_MAX;
1278
1279 if (*rel != '/')
1280 {
1281 if (!getcwd (res, PATH_MAX))
1282 return;
1283
1284 if (res [1]) /* only use if not / */
1285 res += strlen (res);
1286 }
1287
1288 while (*rel)
1289 {
1290 ssize_t len, linklen;
1291 char *beg = rel;
1292
1293 while (*rel && *rel != '/')
1294 ++rel;
1295
1296 len = rel - beg;
1297
1298 if (!len) /* skip slashes */
1299 {
1300 ++rel;
1301 continue;
1302 }
1303
1304 if (beg [0] == '.')
1305 {
1306 if (len == 1)
1307 continue; /* . - nop */
1308
1309 if (beg [1] == '.' && len == 2)
1310 {
1311 /* .. - back up one component, if possible */
1312
1313 while (res != req->ptr2)
1314 if (*--res == '/')
1315 break;
1316
1317 continue;
1318 }
1319 }
1320
1321 errno = ENAMETOOLONG;
1322 if (res + 1 + len + 1 >= tmp1)
1323 return;
1324
1325 /* copy one component */
1326 *res = '/';
1327 memcpy (res + 1, beg, len);
1328
1329 /* zero-terminate, for readlink */
1330 res [len + 1] = 0;
1331
1332 /* now check if it's a symlink */
1333 linklen = readlink (req->ptr2, tmp1, PATH_MAX);
1334
1335 if (linklen < 0)
1336 {
1337 if (errno != EINVAL)
1338 return;
1339
1340 /* it's a normal directory. hopefully */
1341 res += len + 1;
1342 }
1343 else
1344 {
1345 /* yay, it was a symlink - build new path in tmp2 */
1346 int rellen = strlen (rel);
1347
1348 errno = ENAMETOOLONG;
1349 if (linklen + 1 + rellen >= PATH_MAX)
1350 return;
1351
1352 if (*tmp1 == '/')
1353 res = req->ptr2; /* symlink resolves to an absolute path */
1354
1355 /* we need to be careful, as rel might point into tmp2 already */
1356 memmove (tmp2 + linklen + 1, rel, rellen + 1);
1357 tmp2 [linklen] = '/';
1358 memcpy (tmp2, tmp1, linklen);
1359
1360 rel = tmp2;
1361 }
1362 }
1363
1364 /* special case for the lone root path */
1365 if (res == req->ptr2)
1366 *res++ = '/';
1367
1368 req->result = res - (char *)req->ptr2;
1369 req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */
1124} 1370}
1125 1371
1126static signed char 1372static signed char
1127eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) 1373eio_dent_cmp (const eio_dirent *a, const eio_dirent *b)
1128{ 1374{
1488 break; 1734 break;
1489 } 1735 }
1490 } 1736 }
1491} 1737}
1492 1738
1493#ifdef PAGESIZE
1494# define eio_pagesize() PAGESIZE
1495#else
1496static intptr_t
1497eio_pagesize (void)
1498{
1499 static intptr_t page;
1500
1501 if (!page)
1502 page = sysconf (_SC_PAGESIZE);
1503
1504 return page;
1505}
1506#endif
1507
1508static void
1509eio_page_align (void **addr, size_t *length)
1510{
1511 intptr_t mask = eio_pagesize () - 1;
1512
1513 /* round down addr */
1514 intptr_t adj = mask & (intptr_t)*addr;
1515
1516 *addr = (void *)((intptr_t)*addr - adj);
1517 *length += adj;
1518
1519 /* round up length */
1520 *length = (*length + mask) & ~mask;
1521}
1522
1523#if !_POSIX_MEMLOCK
1524# define eio__mlockall(a) ((errno = ENOSYS), -1)
1525#else
1526
1527static int
1528eio__mlockall (int flags)
1529{
1530 #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7
1531 extern int mallopt (int, int);
1532 mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */
1533 #endif
1534
1535 if (EIO_MCL_CURRENT != MCL_CURRENT
1536 || EIO_MCL_FUTURE != MCL_FUTURE)
1537 {
1538 flags = 0
1539 | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0)
1540 | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0);
1541 }
1542
1543 return mlockall (flags);
1544}
1545#endif
1546
1547#if !_POSIX_MEMLOCK_RANGE
1548# define eio__mlock(a,b) ((errno = ENOSYS), -1)
1549#else
1550
1551static int
1552eio__mlock (void *addr, size_t length)
1553{
1554 eio_page_align (&addr, &length);
1555
1556 return mlock (addr, length);
1557}
1558
1559#endif
1560
1561#if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
1562# define eio__msync(a,b,c) ((errno = ENOSYS), -1)
1563#else
1564
1565static int
1566eio__msync (void *mem, size_t len, int flags)
1567{
1568 eio_page_align (&mem, &len);
1569
1570 if (EIO_MS_ASYNC != MS_SYNC
1571 || EIO_MS_INVALIDATE != MS_INVALIDATE
1572 || EIO_MS_SYNC != MS_SYNC)
1573 {
1574 flags = 0
1575 | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0)
1576 | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0)
1577 | (flags & EIO_MS_SYNC ? MS_SYNC : 0);
1578 }
1579
1580 return msync (mem, len, flags);
1581}
1582
1583#endif
1584
1585static int
1586eio__mtouch (eio_req *req)
1587{
1588 void *mem = req->ptr2;
1589 size_t len = req->size;
1590 int flags = req->int1;
1591
1592 eio_page_align (&mem, &len);
1593
1594 {
1595 intptr_t addr = (intptr_t)mem;
1596 intptr_t end = addr + len;
1597 intptr_t page = eio_pagesize ();
1598
1599 if (addr < end)
1600 if (flags & EIO_MT_MODIFY) /* modify */
1601 do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req));
1602 else
1603 do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req));
1604 }
1605
1606 return 0;
1607}
1608
1609/*****************************************************************************/ 1739/*****************************************************************************/
1610 1740
1611#define ALLOC(len) \ 1741#define ALLOC(len) \
1612 if (!req->ptr2) \ 1742 if (!req->ptr2) \
1613 { \ 1743 { \
1778 case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break; 1908 case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break;
1779 case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break; 1909 case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break;
1780 case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break; 1910 case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break;
1781 case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break; 1911 case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break;
1782 1912
1783 case EIO_REALPATH: req->flags |= EIO_FLAG_PTR2_FREE; 1913 case EIO_REALPATH: eio__realpath (req, self); break;
1784 req->ptr2 = realpath (req->ptr1, 0);
1785 req->result = req->ptr2 ? strlen (req->ptr2) : -1;
1786 break;
1787 1914
1788 case EIO_READLINK: ALLOC (PATH_MAX); 1915 case EIO_READLINK: ALLOC (PATH_MAX);
1789 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; 1916 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break;
1790 1917
1791 case EIO_SYNC: req->result = 0; sync (); break; 1918 case EIO_SYNC: req->result = 0; sync (); break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines