summaryrefslogtreecommitdiff
path: root/src/lib/eina/eina_file.c
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@samsung.com>2013-03-15 16:05:05 +0900
committerCedric BAIL <cedric.bail@samsung.com>2013-03-15 16:05:39 +0900
commit0dde9a65745ea1bdf42a28933c659c160cb671b1 (patch)
tree9e2fdf9eb0f2849873247162ee30514761cfb660 /src/lib/eina/eina_file.c
parent3728c603115e00bce734f967825250d2662c692a (diff)
eina: share eina_file_copy code accross platform.
Diffstat (limited to 'src/lib/eina/eina_file.c')
-rw-r--r--src/lib/eina/eina_file.c280
1 files changed, 1 insertions, 279 deletions
diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
index d54b703..4e622e5 100644
--- a/src/lib/eina/eina_file.c
+++ b/src/lib/eina/eina_file.c
@@ -67,30 +67,6 @@
67 * @cond LOCAL 67 * @cond LOCAL
68 */ 68 */
69 69
70#ifndef EINA_LOG_COLOR_DEFAULT
71#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
72#endif
73
74#ifdef ERR
75#undef ERR
76#endif
77#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__)
78
79#ifdef WRN
80#undef WRN
81#endif
82#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__)
83
84#ifdef INF
85#undef INF
86#endif
87#define INF(...) EINA_LOG_DOM_INFO(_eina_file_log_dom, __VA_ARGS__)
88
89#ifdef DBG
90#undef DBG
91#endif
92#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__)
93
94#define EINA_SMALL_PAGE 4096 70#define EINA_SMALL_PAGE 4096
95#define EINA_HUGE_PAGE 16 * 1024 * 1024 71#define EINA_HUGE_PAGE 16 * 1024 * 1024
96 72
@@ -107,7 +83,7 @@ struct _Eina_File_Iterator
107}; 83};
108#endif 84#endif
109 85
110static int _eina_file_log_dom = -1; 86int _eina_file_log_dom = -1;
111 87
112/* 88/*
113 * This complex piece of code is needed due to possible race condition. 89 * This complex piece of code is needed due to possible race condition.
@@ -1216,257 +1192,3 @@ eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *st)
1216 return 0; 1192 return 0;
1217} 1193}
1218 1194
1219static Eina_Bool
1220_eina_file_copy_write_internal(int fd, char *buf, size_t size)
1221{
1222 size_t done = 0;
1223 while (done < size)
1224 {
1225 ssize_t w = write(fd, buf + done, size - done);
1226 if (w >= 0)
1227 done += w;
1228 else if ((errno != EAGAIN) && (errno != EINTR))
1229 {
1230 ERR("Error writing destination file during copy: %s",
1231 strerror(errno));
1232 return EINA_FALSE;
1233 }
1234 }
1235 return EINA_TRUE;
1236}
1237
1238static Eina_Bool
1239_eina_file_copy_read_internal(int fd, char *buf, off_t bufsize, ssize_t *readsize)
1240{
1241 while (1)
1242 {
1243 ssize_t r = read(fd, buf, bufsize);
1244 if (r == 0)
1245 {
1246 ERR("Premature end of source file during copy.");
1247 return EINA_FALSE;
1248 }
1249 else if (r < 0)
1250 {
1251 if ((errno != EAGAIN) && (errno != EINTR))
1252 {
1253 ERR("Error reading source file during copy: %s",
1254 strerror(errno));
1255 return EINA_FALSE;
1256 }
1257 }
1258 else
1259 {
1260 *readsize = r;
1261 return EINA_TRUE;
1262 }
1263 }
1264}
1265
1266#ifdef HAVE_SPLICE
1267static Eina_Bool
1268_eina_file_copy_write_splice_internal(int fd, int pipefd, size_t size)
1269{
1270 size_t done = 0;
1271 while (done < size)
1272 {
1273 ssize_t w = splice(pipefd, NULL, fd, NULL, size - done, SPLICE_F_MORE);
1274 if (w >= 0)
1275 done += w;
1276 else if (errno == EINVAL)
1277 {
1278 INF("Splicing is not supported for destination file");
1279 return EINA_FALSE;
1280 }
1281 else if ((errno != EAGAIN) && (errno != EINTR))
1282 {
1283 ERR("Error splicing to destination file during copy: %s",
1284 strerror(errno));
1285 return EINA_FALSE;
1286 }
1287 }
1288 return EINA_TRUE;
1289}
1290
1291static Eina_Bool
1292_eina_file_copy_read_splice_internal(int fd, int pipefd, off_t bufsize, ssize_t *readsize)
1293{
1294 while (1)
1295 {
1296 ssize_t r = splice(fd, NULL, pipefd, NULL, bufsize, SPLICE_F_MORE);
1297 if (r == 0)
1298 {
1299 ERR("Premature end of source file during splice.");
1300 return EINA_FALSE;
1301 }
1302 else if (r < 0)
1303 {
1304 if (errno == EINVAL)
1305 {
1306 INF("Splicing is not supported for source file");
1307 return EINA_FALSE;
1308 }
1309 else if ((errno != EAGAIN) && (errno != EINTR))
1310 {
1311 ERR("Error splicing from source file during copy: %s",
1312 strerror(errno));
1313 return EINA_FALSE;
1314 }
1315 }
1316 else
1317 {
1318 *readsize = r;
1319 return EINA_TRUE;
1320 }
1321 }
1322}
1323#endif
1324
1325static Eina_Bool
1326_eina_file_copy_splice_internal(int s, int d, off_t total, Eina_File_Copy_Progress cb, const void *cb_data, Eina_Bool *splice_unsupported)
1327{
1328#ifdef HAVE_SPLICE
1329 off_t bufsize = COPY_BLOCKSIZE;
1330 off_t done;
1331 Eina_Bool ret;
1332 int pipefd[2];
1333
1334 *splice_unsupported = EINA_TRUE;
1335
1336 if (pipe(pipefd) < 0) return EINA_FALSE;
1337
1338 done = 0;
1339 ret = EINA_TRUE;
1340 while (done < total)
1341 {
1342 size_t todo;
1343 ssize_t r;
1344
1345 if (done + bufsize < total)
1346 todo = bufsize;
1347 else
1348 todo = total - done;
1349
1350 ret = _eina_file_copy_read_splice_internal(s, pipefd[1], todo, &r);
1351 if (!ret) break;
1352
1353 ret = _eina_file_copy_write_splice_internal(d, pipefd[0], r);
1354 if (!ret) break;
1355
1356 *splice_unsupported = EINA_FALSE;
1357 done += r;
1358
1359 if (cb)
1360 {
1361 ret = cb((void *)cb_data, done, total);
1362 if (!ret) break;
1363 }
1364 }
1365
1366 close(pipefd[0]);
1367 close(pipefd[1]);
1368
1369 return ret;
1370#endif
1371 *splice_unsupported = EINA_TRUE;
1372 return EINA_FALSE;
1373 (void)s;
1374 (void)d;
1375 (void)total;
1376 (void)cb;
1377 (void)cb_data;
1378}
1379
1380static Eina_Bool
1381_eina_file_copy_internal(int s, int d, off_t total, Eina_File_Copy_Progress cb, const void *cb_data)
1382{
1383 void *buf = NULL;
1384 off_t bufsize = COPY_BLOCKSIZE;
1385 off_t done;
1386 Eina_Bool ret, splice_unsupported;
1387
1388 ret = _eina_file_copy_splice_internal(s, d, total, cb, cb_data,
1389 &splice_unsupported);
1390 if (ret)
1391 return EINA_TRUE;
1392 else if (!splice_unsupported) /* splice works, but copy failed anyway */
1393 return EINA_FALSE;
1394
1395 /* make sure splice didn't change the position */
1396 lseek(s, 0, SEEK_SET);
1397 lseek(d, 0, SEEK_SET);
1398
1399 while ((bufsize > 0) && ((buf = malloc(bufsize)) == NULL))
1400 bufsize /= 128;
1401
1402 EINA_SAFETY_ON_NULL_RETURN_VAL(buf, EINA_FALSE);
1403
1404 done = 0;
1405 ret = EINA_TRUE;
1406 while (done < total)
1407 {
1408 size_t todo;
1409 ssize_t r;
1410
1411 if (done + bufsize < total)
1412 todo = bufsize;
1413 else
1414 todo = total - done;
1415
1416 ret = _eina_file_copy_read_internal(s, buf, todo, &r);
1417 if (!ret) break;
1418
1419 ret = _eina_file_copy_write_internal(d, buf, r);
1420 if (!ret) break;
1421
1422 done += r;
1423
1424 if (cb)
1425 {
1426 ret = cb((void *)cb_data, done, total);
1427 if (!ret) break;
1428 }
1429 }
1430
1431 free(buf);
1432 return ret;
1433}
1434
1435EAPI Eina_Bool
1436eina_file_copy(const char *src, const char *dst, Eina_File_Copy_Flags flags, Eina_File_Copy_Progress cb, const void *cb_data)
1437{
1438 struct stat st;
1439 int s, d;
1440 Eina_Bool success;
1441
1442 EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
1443 EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
1444
1445 s = open(src, O_RDONLY);
1446 EINA_SAFETY_ON_TRUE_RETURN_VAL (s < 0, EINA_FALSE);
1447
1448 success = (fstat(s, &st) == 0);
1449 EINA_SAFETY_ON_FALSE_GOTO(success, end);
1450
1451 d = open(dst, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
1452 EINA_SAFETY_ON_TRUE_GOTO(d < 0, end);
1453
1454 success = _eina_file_copy_internal(s, d, st.st_size, cb, cb_data);
1455 if (success)
1456 {
1457#ifdef HAVE_FCHMOD
1458 if (flags & EINA_FILE_COPY_PERMISSION)
1459 fchmod(d, st.st_mode);
1460#endif
1461 if (flags & EINA_FILE_COPY_XATTR)
1462 eina_xattr_fd_copy(s, d);
1463 }
1464
1465 end:
1466 close(s);
1467
1468 if (!success)
1469 unlink(dst);
1470
1471 return success;
1472}