From 36810a810a2e4ee26f1d2afa7fcc418748124001 Mon Sep 17 00:00:00 2001 From: Alexis Svinartchouk Date: Thu, 9 Mar 2017 17:50:04 +0100 Subject: [PATCH] Implement writeBuffers using writev and pwritev syscalls. Change-Type: patch --- lib/binding.js | 19 ++++++++++++++++--- lib/syscall.js | 4 +++- src/bindings.cc | 1 + src/node_lkl.cc | 16 ++++++++++++++++ src/node_lkl.h | 1 + test/fixtures/disk.img | Bin 42991616 -> 42991616 bytes test/index.js | 26 ++++++++++++++++++++++++++ 7 files changed, 63 insertions(+), 4 deletions(-) diff --git a/lib/binding.js b/lib/binding.js index c75cc95..341bd54 100644 --- a/lib/binding.js +++ b/lib/binding.js @@ -15,7 +15,7 @@ function getCallback(req) { } function addNullTerminationIfNeeded(s) { - // If the s is a Buffer, we need to add a NULL termination byte. + // If s is a Buffer, we need to add a NULL termination byte. if (Buffer.isBuffer(s)) { const nullTerminated = Buffer.allocUnsafe(s.length + 1); s.copy(nullTerminated); @@ -193,8 +193,21 @@ exports.writeBuffer = function(fd, buffer, offset, length, position, req) { } } -exports.writeBuffers = function() { - throw new Error('Unimplemented'); +exports.writeBuffers = function(fd, buffers, position, req) { + const callback = getCallback(req); + const iovecs = bindings.buffersToIoVecs(buffers); + if (typeof position === 'number' && position !== -1) { + return syscall.pwritev( + fd, + iovecs, + buffers.length, + position & 0xffffffff, // 32 lower bits + Math.floor(position / Math.pow(2, 32)), // high bits + callback + ); + } else { + return syscall.writev(fd, iovecs, buffers.length, callback); + } } exports.writeString = function() { diff --git a/lib/syscall.js b/lib/syscall.js index 714154d..29cc7af 100644 --- a/lib/syscall.js +++ b/lib/syscall.js @@ -47,6 +47,7 @@ module.exports = { openat: syscall.bind(null, constants.SYS_openat), pread64: syscall.bind(null, constants.SYS_pread64), pwrite64: syscall.bind(null, constants.SYS_pwrite64), + pwritev: syscall.bind(null, constants.SYS_pwritev), read: syscall.bind(null, constants.SYS_read), readlinkat: syscall.bind(null, constants.SYS_readlinkat), removexattr: syscall.bind(null, constants.SYS_removexattr), @@ -56,7 +57,8 @@ module.exports = { sync: syscall.bind(null, constants.SYS_sync), truncate: syscall.bind(null, constants.SYS_truncate), unlinkat: syscall.bind(null, constants.SYS_unlinkat), - write: syscall.bind(null, constants.SYS_write) + write: syscall.bind(null, constants.SYS_write), + writev: syscall.bind(null, constants.SYS_writev) }; // Unimplemented syscalls diff --git a/src/bindings.cc b/src/bindings.cc index f06fd6b..dc7ad27 100644 --- a/src/bindings.cc +++ b/src/bindings.cc @@ -11,6 +11,7 @@ NAN_MODULE_INIT(InitAll) { NAN_EXPORT(target, sizeOfStructLklStat); NAN_EXPORT(target, parseLklStat); NAN_EXPORT(target, millisecondsToTimespec); + NAN_EXPORT(target, buffersToIoVecs); } NODE_MODULE(bindings, InitAll) diff --git a/src/node_lkl.cc b/src/node_lkl.cc index 2ff6539..768fd00 100644 --- a/src/node_lkl.cc +++ b/src/node_lkl.cc @@ -187,3 +187,19 @@ NAN_METHOD(millisecondsToTimespec) { ).ToLocalChecked(); info.GetReturnValue().Set(result); } + +NAN_METHOD(buffersToIoVecs) { + auto arr = info[0].As(); + auto len = arr->Length(); + auto *iovecs = new struct iovec[len]; + for (unsigned int i = 0; i < len; i++) { + auto buf = arr->Get(i); + iovecs[i].iov_base = reinterpret_cast(node::Buffer::Data(buf)); + iovecs[i].iov_len = node::Buffer::Length(buf); + } + auto result = Nan::NewBuffer( + reinterpret_cast(iovecs), + sizeof *iovecs + ).ToLocalChecked(); + info.GetReturnValue().Set(result); +} diff --git a/src/node_lkl.h b/src/node_lkl.h index 83c9c98..6e95499 100644 --- a/src/node_lkl.h +++ b/src/node_lkl.h @@ -7,3 +7,4 @@ NAN_METHOD(parseDirent64); NAN_METHOD(sizeOfStructLklStat); NAN_METHOD(parseLklStat); NAN_METHOD(millisecondsToTimespec); +NAN_METHOD(buffersToIoVecs); diff --git a/test/fixtures/disk.img b/test/fixtures/disk.img index 74a48058191e3061a69a510098c5f8b66d2e23d1..e0bcdf7c824dea5d3dbff9e09e55e3d7a2ee4869 100644 GIT binary patch delta 12257 zcmeIx<(C#^0EY4RU2ZydK~Th6x?|~v1(xpa?(U8Sh8tK)Kru)K6{Qgg6T8JO!tMZD zNiPn^5B>%E;d$o#CZ0KG&NFkaNl!nTKmD>O9wkJXB1M^_EK$}dTa-P@5#@|>MY*Fq zQR0ClB_y1=v@d=rzAtHee09?Lby=AD*G!$%p|KIM(Xk=1v9ZM1$pNu3oW^387+3a9 zTeMDVo7yHVnZb=%VYVyBOo#GjOFo@=`O*Kq3UQ^RRIc*RyZ-kJ`agV>u!hhwXE7!9jmTY&#G@Vuo_yaRwJvi)x=7(np(}Q=2i=wZK|vMb;wA)?#ak zwbaV6mRZZK71l~?m36bV+FE0+wQjL)wbog;S+`qvSa(|Mtqs;jYm>Fv+G5>h-ED2P zwpsUB_geQ^+pYVp2do{|PHUI7+uCF8wf0&2tp}|G)yUNWI$}L+Jz_m-J!U;_ zJz*WSp0u8_p0=K`p0%E{p0{4GUbJ4aUbbGbUbSAcj#;l;Z&+_yZ&`0!?^y3z?^*9# zA6Oq+$E_3AN$ZsLk@d0liS?=Vnf1B#h4rQNmG!mtjrFbdo%Ox-gY~0z+B#$XWc_UY zV*P6UX8mscVf|_SWu3LoS?8?_)+B~TKjP#R@W7UfVL6;KhCkb=sn zf~u&7>ZpO5sD;|7gSx1P`e=ZLNJS$wMiZo=DVm`FYd#3+>Zya13R$`yRip*u@C$4AP(Rm9K<0U#t}S>NAM^f z!{c}YNAV<{!qa#L&*C{ej~DPFUc$?G1+U^Y9K-8)18?Fjyp4D8F5biY_y8Z`I8NXs zPT?bbj8E_>KEvnu0$<`Qe2s7LExyC|_yIrSG|u2B{ET1lD}KZ8_yd39FPz0WoW})R z#HDzK68Qa*fK0f2of%n>71@v-Igk^%kQ;fBh$Q4iK3s+TD1fVR4GQ8~6vB159yj1d z+=OHlMiCT6F%(A$ltd|%Mj4bvIh02QR754DpfakUDypG6YM>@+p*HHEF6yB^8lWLk z(Fl#v1ZilBW@wHUXo*&6jW%eDc4&_d=!j0}j4tSkZs?94=!stFjXvm$e&~+@7>Gd_ zj3F3`VHl1P7>Q9BjWHODaTt#Yn21T3j47CkX_$@~n2A}KjX9W$c}T~6EWkoUSOjA+ VmS8C|unfzw0xJ`CYgNMezX2E-NTC1# delta 12223 zcmeIxRhy7i6o%nzhL^4(L|VGLySux)yE_N?c!2?iP`WVy1tb-lQcS=A3{VslB@`1B zP#@0x0Uqvy`(UlJwXbK##~;lc|4X`^&e`a^Mw zT~i@;&fWcSJ7f08^@v%WEKdJfJX{9h4MGEnrItxi^FtBcju z>SlGfdRRTJURH0bkJZ=eXZ5!RSOcv=)?jOhHPjkr4YxRRq&3PKZH=+UTH~zo)&y&! zHOZQ6O|hn0)2!*%3~Qz}%bIP)TXU?r);ue+=3BNFSPQL1R)V$IT4F7=60K#{a%+XP z(t6x_!dhjmw$@l{t##IVYlF4X+GK6Ewpd%OZPs?{N$V-=Y3mtlhqcq%Wj$*>XYIE3 zSbMGKt$o&h>wtC8I%FNTUa(%Yj#w{QFI%rzuUfBJuUl_eN3CPlaqEP2(t6W+%Q|Jf zZM|c?YrSW^Z+&2$w$4~*tq-k_tdFfvtaH|R>w@*E^_lg#^@VlOx@3K6ePvy?zP7%x zu2@&CZ>{gFYu5MH57u?-hIP}rW&LRVWZkxYwtlgGwSKdHxBjs1Sa+>It-q{$)_v=N z^|$p;f?^UCgIFZN!#OFEAvsbYB~l?Z(jYC;AwA-d0U41Anehm+;8A2nHe^Q*zl4c1~E)?))UViPuF3$|h#w&O`Wg{Schc3>xV z;aNO~-PnV@cpm$(9|v#{hj17#;6)t4OL!Tt;8nba*YO69;uwzO1Ww{jyoFPE8}Hy< zyodMk0Z!u#&f-ISgpctF&fz>R;8T2t&+!E=;u5~ZSGbI?@eQuvD!#>cxQ6fX1Fqu+ zZsHbx#80@5pYaQR#c%i>f8Y-8;!pgAd$^AW_#6MkBq)~ek60wZ!#OFEAvsbYB~l?Z z(jYC;AwA-d0U41Anehm+;8A2nHe^Q*