I'm writing an Applet for Linux Mint/Cinnamon to manage OpenVPN v3 connections.
In order to avoid synchronous calls that can cause the DE to stutter or freeze, I'm writing a simple DBus client using the Gio and GLib libraries provided by GJS. This allows an asynchronous, partly event-driven approach and should avoid any nasty side effects. It's my first time using any of these technologies but the OpenVPN DBus API is pretty well documented and the API docs for Gio and GLib are also good.
The problem I have is with signal subscriptions, specifically the StatusChange signal published by the net.openvpn.v3.sessions service. A bunch of these signals are published whenever a connection is established, paused, resumed or closed. Most of the signals are picked up by my subscribed listener, but not all of them. In particular, I don't receive the session closed signal.
Using the dbus-monitor commandline tool, you can see all the StatusChange signals published when a connection is established (7 signals) and then closed (2 signals):
$ sudo dbus-monitor --system "type='signal',interface='net.openvpn.v3.sessions',member='StatusChange'"
...
// Connect:
signal time=1625847543.107244 sender=:1.891 -> destination=:1.892 serial=2745 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 3
uint32 27
string "session_path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49, backend_pid=42584"
signal time=1625847543.116395 sender=:1.891 -> destination=:1.892 serial=2762 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 3
uint32 17
string "session_path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49 backend_busname=net.openvpn.v3.backends.be42585 backend_path=/net/openvpn/v3/backends/session"
signal time=1625847543.117286 sender=:1.891 -> destination=(null destination) serial=2764 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 2
uint32 2
string "config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232"
signal time=1625847543.638519 sender=:1.891 -> destination=(null destination) serial=2775 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 2
uint32 2
string "config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232"
signal time=1625847543.638533 sender=:1.891 -> destination=(null destination) serial=2776 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 2
uint32 6
string ""
signal time=1625847543.735357 sender=:1.891 -> destination=(null destination) serial=2777 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 2
uint32 6
string ""
signal time=1625847543.974784 sender=:1.891 -> destination=(null destination) serial=2778 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 2
uint32 7
string ""
// Disconnect:
signal time=1625847646.846790 sender=:1.891 -> destination=:1.892 serial=2834 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 3
uint32 28
string "Session closed"
signal time=1625847646.848262 sender=:1.891 -> destination=:1.892 serial=2839 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
uint32 3
uint32 19
string ""
The following code creates a subscription that, as far as I can tell, should receive the same signals as above. Note I'm using the lower-level approach to obtain a subscription here; the subscription is made on the global connection, rather than via a DBusProxy for a specific object path. I've tried both approaches (same result) but the following should be a closer analogue to the dbus-monitor command above.
subscribeToStatusChangeSignals() {
this.statusChangeHandlerId = Gio.DBus.system.signal_subscribe(
'net.openvpn.v3.sessions',
'net.openvpn.v3.sessions',
'StatusChange',
null,
null,
Gio.DBusSignalFlags.NONE,
this._handleGlobalStatusChangeSignal
);
}
_handleGlobalStatusChangeSignal(connection, sender, path, iface, signal, params) {
let container = params.deep_unpack();
let statusMajorCode = container[0];
let statusMinorCode = container[1];
let statusMajor = lookupStatusMajor(statusMajorCode); // lookup the corresponding text
let statusMinor = lookupStatusMinor(statusMinorCode); // from something resembling an enum
let message = container[2];
global.log(`Received StatusChange signal
path: [${path}]
Status Major: [${statusMajorCode} - ${statusMajor}]
Status Minor: [${statusMinorCode} - ${statusMinor}]
Message: [${message}]`
);
}
The resulting logs when opening and closing the same connection as before:
// Connect:
Cjs-Message: 18:19:03.117: JS LOG: [LookingGlass/info] Received StatusChange signal
path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
Status Major: [2 - CONNECTION]
Status Minor: [2 - CFG_OK]
Message: [config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232]
Cjs-Message: 18:19:03.638: JS LOG: [LookingGlass/info] Received StatusChange signal
path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
Status Major: [2 - CONNECTION]
Status Minor: [2 - CFG_OK]
Message: [config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232]
Cjs-Message: 18:19:03.639: JS LOG: [LookingGlass/info] Received StatusChange signal
path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
Status Major: [2 - CONNECTION]
Status Minor: [6 - CONN_CONNECTING]
Message: []
Cjs-Message: 18:19:03.735: JS LOG: [LookingGlass/info] Received StatusChange signal
path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
Status Major: [2 - CONNECTION]
Status Minor: [6 - CONN_CONNECTING]
Message: []
Cjs-Message: 18:19:03.974: JS LOG: [LookingGlass/info] Received StatusChange signal
path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
Status Major: [2 - CONNECTION]
Status Minor: [7 - CONN_CONNECTED]
Message: []
// Disconnect:
<nada>
One pattern i've noticed is that the signals i do receive all have a null destination in the dbus-monitor output:
... sender=:1.891 -> destination=(null destination) ...
while the signals I don't receive have a specific destination:
... sender=:1.891 -> destination=:1.892 ...
Presumably these are direct signals intended for a particular recipient, rather than signals broadcast to all interested subscribers, but I haven't found this explained anywhere in the docs.
So the question is, why do I receive some signals but not all? Is this by design, or an issue with Gio, or (more likely) an issue with how I'm using it?
After a bit more digging it appears this behaviour is by design - Signals that carry a destination value are treated as unicast messages. Subscribers other than the intended recipient will only receive such messages if they are configured to eavesdrop. Presumably this is the case for dbus-monitor.
Source: DBus Specification (Message Routing)
I am having an issue playing MOV camera captured files from an iPhone. My FFMPEG implementation has no problem playing most file formats, this issue is exclusive only for camera captured MOV.
When trying to open the file, I can see in the logs that many requests are made, each requests decoding only one frame, before making a new request which results the video being buffered extremely slowly.
It takes roughly a minute to buffer about a few seconds of the video.
Another thing to mention is that the very same problematic file is played without an issue locally. The problem is when trying to decode while streaming.
I compiled my code on Xcode 11, iOS SDK 13, with cocoapods mobile-ffmpeg-https 4.2.
Here is a rough representation of my code, its pretty standard:
Here is how I open AVFormatContext:
AVFormatContext *context = avformat_alloc_context();
context->interrupt_callback.callback = FFMPEGFormatContextIOHandler_IO_CALLBACK;
context->interrupt_callback.opaque = (__bridge void *)(handler);
av_log_set_level(AV_LOG_TRACE);
int result = avformat_open_input(&context, [request.urlAsString UTF8String], NULL, NULL);
if (result != 0) {
if (context != NULL) {
avformat_free_context(context);
}
return nil;
}
result = avformat_find_stream_info(context, NULL);
if (result < 0) {
avformat_close_input(&context);
return nil;
}
Video decoder is opened like so, audio decoder is nearly identical
AVCodecParameters *params = context->streams[streamIndex]->codecpar;
AVCodec *codec = avcodec_find_decoder(params->codec_id);
if (codec == NULL) {
return NULL;
}
AVCodecContext *codecContext = avcodec_alloc_context3(codec);
if (codecContext == NULL) {
return NULL;
}
codecContext->thread_count = 6;
int result = avcodec_parameters_to_context(codecContext, params);
if (result < 0) {
avcodec_free_context(&codecContext);
return NULL;
}
result = avcodec_open2(codecContext, codec, NULL);
if (result < 0) {
avcodec_free_context(&codecContext);
return NULL;
}
I read the data from the server like so:
AVPacket packet;
int result = av_read_frame(formatContext, &avPacket);
if (result == 0) {
avcodec_send_packet(codecContext, &avPacket);
// .... decode ....
}
Logs after opening the decoders:
// [tls] Request is made here
// [tls] Request response headers are here
Probing mov,mp4,m4a,3gp,3g2,mj2 score:100 size:2048
Probing mp3 score:1 size:2048
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] Format mov,mp4,m4a,3gp,3g2,mj2 probed with size=2048 and score=100
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] type:'ftyp' parent:'root' sz: 20 8 23077123
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] ISO: File Type Major Brand: qt
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] type:'wide' parent:'root' sz: 8 28 23077123
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] type:'mdat' parent:'root' sz: 23066642 36 23077123
// [tls] Request is made here
// [tls] Request response headers are here
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] stream 0, sample 4, dts 133333
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] stream 1, sample 48, dts 1114558
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] stream 2, sample 1, dts 2666667
[h264 # 0x116080200] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 1
// [tls] Request is made here
// [tls] Request response headers are here
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] stream 0, sample 4, dts 133333
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] stream 1, sample 48, dts 1114558
[mov,mp4,m4a,3gp,3g2,mj2 # 0x115918e00] stream 2, sample 1, dts 2666667
[h264 # 0x116080200] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 1
// [tls] Request is made here
// [tls] Request response headers are here
// ...
These are some warnings I found in the log
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] interrupted
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] stream 0: start_time: 0.000 duration: 11.833
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] stream 1: start_time: 0.000 duration: 11.832
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] stream 2: start_time: 0.000 duration: 11.833
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] stream 3: start_time: 0.000 duration: 11.833
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] format: start_time: 0.000 duration: 11.833 bitrate=15601 kb/s
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] Could not find codec parameters for stream 0 (Video: h264, 1 reference frame (avc1 / 0x31637661), none(bt709, left), 1920x1080, 1/1200, 15495 kb/s): unspecified pixel format
Consider increasing the value for the 'analyzeduration' and 'probesize' options
[mov,mp4,m4a,3gp,3g2,mj2 # 0x11c030800] After avformat_find_stream_info() pos: 23077123 bytes read:16293 seeks:1 frames:0
Also when calling avformat_open_input(...), 2 GET requests are made, before the returning.
Notice the "Probing mp3 score:1", that is not shown for other MOV files or any other files.
I have tried different versions of ffmpeg, I have tried messing around with the delays of the stream, I tried removing my custom interrupt callback, nothing have worked.
Code works fine with any other videos I have tested (mp4, mkv, avi).
Metadata of the test file:
Metadata:
major_brand : qt
minor_version : 0
compatible_brands: qt
creation_time : 2019-04-14T08:17:03.000000Z
com.apple.quicktime.make: Apple
com.apple.quicktime.model: iPhone 7
com.apple.quicktime.software: 12.2
com.apple.quicktime.creationdate: 2019-04-14T11:17:03+0300
Duration: 00:00:16.83, bitrate: N/A
Stream #0:0(und), 0, 1/600: Video: h264, 1 reference frame (avc1 / 0x31637661), none(bt709), 1920x1080 (0x0), 0/1, 15301 kb/s, 30 fps, 30 tbr, 600 tbn (default)
Metadata:
creation_time : 2019-04-14T08:17:03.000000Z
handler_name : Core Media Video
encoder : H.264
Stream #0:1(und), 0, 1/44100: Audio: aac (mp4a / 0x6134706D), 44100 Hz, mono, 100 kb/s (default)
Metadata:
creation_time : 2019-04-14T08:17:03.000000Z
handler_name : Core Media Audio
Stream #0:2(und), 0, 1/600: Data: none (mebx / 0x7862656D), 0/1, 0 kb/s (default)
Metadata:
creation_time : 2019-04-14T08:17:03.000000Z
handler_name : Core Media Metadata
Stream #0:3(und), 0, 1/600: Data: none (mebx / 0x7862656D), 0/1, 0 kb/s (default)
Metadata:
creation_time : 2019-04-14T08:17:03.000000Z
handler_name : Core Media Metadata
I found a fix for this (sorta of):
Set the io_open callback of the AVFormatContext to your own function, and then when that is called, after you call the default io_open you change the buffer size.
static int (*IO_OPEN_DEFAULT)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options);
int IO_OPEN_OVERRIDE(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options) {
int result = IO_OPEN_DEFAULT(s, pb, url, flags, options);
pb[0]->buffer_size = 41239179;
return result;
}
This fixes the issue. The value you set it to is usually very large (20 to 40MB). You can get that value from the second network request bytes range when you are opening the format context (first network request is made with bytes range 0-* and then the second network request is made with bytes range XXXX-* where XXXX should be the buffer size).
The reason why this fixes the issue, is because by buffering all of that data, aviocontext no longer needs to make a new network request to get the audio data. The audio data is already buffered (or at least the first position is).
There might be a better way to fix this issue, it seems like apple MOV files separate their video and audio data with these massive chunks for some reason and that causes ffmpeg to make a million network requests, for each frame.
I have a Grabba smart card reader. I am trying to get card information with APDU commands. I have read a lot about EMV standards and related ISO 7816-4 standard but I am not able to execute simple select command with success. Here is some details:
I have successfully powered my VISA card and get its attributes:
NSError *error = nil;
GRGrabbaSmartcardSession *session = [GRGrabba.sharedGrabba.smartcard startSession:&error];
NSLog(#"EMV : smartCardInsertedEvent : Attribute : %#", [session getATR]);
Result: 3b690000 8072a445 6400ff00 10
When I parse this attribute on here I get this information for my card:
My contactless card is a credit card from Akbank from Turkey but it is listed as a Denizbank card from Turkey in this list.
Now I am tring to run a select command on card like this:
NSError *error = nil;
GRGrabbaSmartcardSession *session = [GRGrabba.sharedGrabba.smartcard startSession:&error];
NSLog(#"EMV : smartCardInsertedEvent : Attribute : %#", [session getATR]);
session.protocol = 1;
uint8_t aid[] = {'2', 'P', 'A', 'Y', '.', 'S', 'Y', 'S', '.', 'D', 'D', 'F', '0', '1'};
NSData *data = [NSData dataWithBytes:aid length:sizeof(aid)];
NSError *err = nil;
GRGrabbaCommandAPDU *apduCMD =
[[GRGrabbaCommandAPDU alloc]
initWithCLA:0x00
INS:0xA4
P1:0x04
P2:0x00
Data:data
Le:0x00
Error:&err];
GRGrabbaResponseAPDU *response = [[GRGrabbaResponseAPDU alloc] initWithData:nil SW1:0 SW2:0];
BOOL success = [session exchangeAPDUCommand:apduCMD withResponse:response error:&error];
if (!success) {
NSLog(#"EMV : smartCardInsertedEvent : ERROR: Could not read ADF");
return;
}
But it is failing with could not read ADF error. Can anyone show me what am I doing wrong?
UPDATE:
I have tried following combinations but still not able to run select command with success:
PROTOCOL DATA CLA LE STATUS
0 1PAY.SYS.DDF01 0x00 - unrecognised SW in response: SW1 = 61, SW2 = 52
0 1PAY.SYS.DDF01 0x00 0x00 Smartcard protocol error.
0 2PAY.SYS.DDF01 0x00 - unrecognised SW in response: SW1 = 61, SW2 = 66
0 2PAY.SYS.DDF01 0x00 0x00 Smartcard protocol error.
0 1PAY.SYS.DDF01 0x80 - card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0 1PAY.SYS.DDF01 0x80 0x00 card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0 2PAY.SYS.DDF01 0x80 - card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0 2PAY.SYS.DDF01 0x80 0x00 card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
1 1PAY.SYS.DDF01 0x00 - unrecognised SW in response: SW1 = 00, SW2 = 00
1 1PAY.SYS.DDF01 0x00 0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1 2PAY.SYS.DDF01 0x00 - unrecognised SW in response: SW1 = 00, SW2 = 00
1 2PAY.SYS.DDF01 0x00 0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1 1PAY.SYS.DDF01 0x80 - unrecognised SW in response: SW1 = 00, SW2 = 00
1 1PAY.SYS.DDF01 0x80 0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1 2PAY.SYS.DDF01 0x80 - unrecognised SW in response: SW1 = 00, SW2 = 00
1 2PAY.SYS.DDF01 0x80 0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
The following two results look perfectly fine:
PROTOCOL DATA CLA LE STATUS
0 1PAY.SYS.DDF01 0x00 - unrecognised SW in response: SW1 = 61, SW2 = 52
0 2PAY.SYS.DDF01 0x00 - unrecognised SW in response: SW1 = 61, SW2 = 66
The status word 61xx indicates that there are xx bytes of response data waiting and that you need issue a GET RESPONSE command to obtain the actual response data.
Consequently, you would need to set protocol to 0,
session.protocol = 0;
issue the SELECT command (for 2PAY.SYS.DDF01)
uint8_t aid[] = {'2', 'P', 'A', 'Y', '.', 'S', 'Y', 'S', '.', 'D', 'D', 'F', '0', '1'};
NSData *data = [NSData dataWithBytes:aid length:sizeof(aid)];
NSError *err = nil;
GRGrabbaCommandAPDU *apduCMD =
[[GRGrabbaCommandAPDU alloc]
initWithCLA:0x00
INS:0xA4
P1:0x04
P2:0x00
Data:data
Error:&err];
GRGrabbaResponseAPDU *response = [[GRGrabbaResponseAPDU alloc] initWithData:nil SW1:0 SW2:0];
BOOL success = [session exchangeAPDUCommand:apduCMD withResponse:response error:&error];
and evaluate the SW1. If SW1 equals 0x90 you are set and already have the response data. If it equals 0x61, then you will need to issue a GET RESPONSE command with Le set to the length indicated by SW2:
if (response.sw1 == 0x61) {
GRGrabbaCommandAPDU *apduGETRESPCMD =
[[GRGrabbaCommandAPDU alloc]
initWithCLA:0x00
INS:0xC0
P1:0x00
P2:0x00
Le:response.sw2
Error:&err];
BOOL success = [session exchangeAPDUCommand:apduGETRESPCMD withResponse:response error:&error];
}
Note: I'm not too confident about syntax and field names in the above code...feel free to fix that once you got it to work.
I haven't used Grabba and I'm not sure if you are using it in contact or contactless, but since you're dealing with T=0 card, you might try issuing the command without Le.
I'm developing a jailbroken app on iOS and getting errno 22 when calling
mprotect(p, 1024, PROT_READ | PROT_EXEC)
errno 22 means invalid arguments but I can't figure out whats wrong. I've aligned p to be a multiple of page size, and I've malloced the memory previously before calling mprotect.
Here's my code and sample output
#define PAGESIZE 4096
FILE * pFile;
pFile = fopen ("log.txt","w");
uint32_t code[] = {
0xe2800001, // add r0, r0, #1
0xe12fff1e, // bx lr
};
fprintf(pFile, "Before Execution\n");
p = (uint32_t *)malloc(1024+PAGESIZE-1);
if (!p) {
fprintf(pFile, "Couldn't malloc(1024)");
perror("Couldn't malloc(1024)");
exit(errno);
}
fprintf(pFile, "Malloced to %p\n", p);
p = (uint32_t *)(((uintptr_t)p + PAGESIZE-1) & ~(PAGESIZE-1));
fprintf(pFile, "Moved pointer to %p\n", p);
fprintf(pFile, "Before Compiling\n");
// copy instructions to function
p[0] = code[0];
p[1] = code[1];
fprintf(pFile, "After Compiling\n");
if (mprotect(p, 1024, PROT_READ | PROT_EXEC)) {
int err = errno;
fprintf(pFile, "Couldn't mprotect2: %i\n", errno);
perror("Couldn't mprotect");
exit(errno);
}
And output:
Before Execution
Malloced to 0x13611ec00
Moved pointer 0x13611f000
Before Compiling
After Compiling
Couldn't mprotect2: 22
Fixed this by using posix_memalign(). Turns out I wasn't aligning my pointer to the page size correctly
I am having a strange problem trying to read and write 9k bytes with open(), read() and write(). When I attempt to write 9k to a file and read it back, the data only goes up to 2250 bytes. After that everything is zeros.
Here is my code (except for the filename which isn't relevant, I'm just putting it to NSDocumentDirectory):
int fp = open([appFile cStringUsingEncoding:NSASCIIStringEncoding], O_RDWR | O_CREAT, 0644);
[_detailViewController log:#"first open() returns %i (err: %i)", fp, errno];
int data2[10000];
int data3[10000];
for (int i=0;i<10000;i++) data2[i] = 1;
[_detailViewController log:#"resetting seek to 0"];
int seekPos = lseek(fp, 0, SEEK_SET);
result = write(fp, data2, 9000);
[_detailViewController log:#"wrote 9k, result is %i", result];
[_detailViewController log:#"resetting seek to 0"];
seekPos = lseek(fp, 0, SEEK_SET);
result = read(fp, data3, 9000);
[_detailViewController log:#"read 9k, result is %i", result];
[_detailViewController log:#"values of data2[2248-2252] = 0x%x 0x%x 0x%x 0x%x 0x%x", data2[2248], data2[2249], data2[2250], data2[2251], data2[2252]];
[_detailViewController log:#"values of data3[2248-2252] = 0x%x 0x%x 0x%x 0x%x 0x%x", data3[2248], data3[2249], data3[2250], data3[2251], data3[2252]];
close(fp);
And here is the strange output:
2013-02-13 14:08:38.290 FileTester[2800:907] first open() returns 6 (err: 3)
2013-02-13 14:08:38.295 FileTester[2800:907] resetting seek to 0
2013-02-13 14:08:38.301 FileTester[2800:907] wrote 9k, result is 9000
2013-02-13 14:08:38.306 FileTester[2800:907] resetting seek to 0
2013-02-13 14:08:38.311 FileTester[2800:907] read 9k, result is 9000
2013-02-13 14:08:38.319 FileTester[2800:907] values of data2[2248-2252] = 0x1 0x1 0x1 0x1 0x1
2013-02-13 14:08:38.327 FileTester[2800:907] values of data3[2248-2252] = 0x1 0x1 0x0 0x0 0x0
As you can see on the last line, the data suddenly goes to zero.
Any ideas what I might be doing wrong? The thing that really gets me is that both the read() and write() return 9000.
As mentioned by ughoavgfhw (Thanks!) the problem was I was mixing up bytes and ints. 9000 bytes is the same thing as 2250 ints, since each int is 4 bytes.