ObjFW  Check-in [ed4d7ecf9c]

Overview
Comment:Merge trunk into 1.0 branch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | 1.0
Files: files | file ages | folders
SHA3-256: ed4d7ecf9c0f857fdabef3f06304ac39d572cc51566c068e9a1058aa8df10714
User & Date: js on 2023-08-29 12:37:57
Other Links: branch diff | manifest | tags
Context
2023-08-29
12:55
Merge trunk into 1.0 branch check-in: 239d7340e1 user: js tags: 1.0
12:37
Merge trunk into 1.0 branch check-in: ed4d7ecf9c user: js tags: 1.0
12:16
Fix compilation with Apple GCC 4.0.1 & 4.2.1 check-in: b5e3f01a59 user: js tags: trunk
2023-08-28
15:49
Merge trunk into 1.0 branch check-in: c13025a1af user: js tags: 1.0
Changes

Modified README.md from [2681c29664] to [af3f3c85c5].

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404

<h1 id="thanks">Thanks</h1>

  * Thank you to [Jonathan Neuschäfer](https://github.com/neuschaefer) for
    reviewing the *entirety* (all 84k LoC at the time) of ObjFW's codebase in
    2017!
  * Thank you to [Hill Ma](https://github.com/mahiuchun) for donating an M1 Mac
    Mini to the project!


<h1 id="commercial-use">Commercial use</h1>

  If for whatever reason neither the terms of the QPL nor those of the GPL work
  for you, a proprietary license for ObjFW including support is available upon
  request. Just write a mail to js@nil.im and we can find a reasonable solution
  for both parties.







|








389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404

<h1 id="thanks">Thanks</h1>

  * Thank you to [Jonathan Neuschäfer](https://github.com/neuschaefer) for
    reviewing the *entirety* (all 84k LoC at the time) of ObjFW's codebase in
    2017!
  * Thank you to [Hill Ma](https://github.com/mahiuchun) for donating an M1 Mac
    Mini to the project in 2022!


<h1 id="commercial-use">Commercial use</h1>

  If for whatever reason neither the terms of the QPL nor those of the GPL work
  for you, a proprietary license for ObjFW including support is available upon
  request. Just write a mail to js@nil.im and we can find a reasonable solution
  for both parties.

Modified configure.ac from [400e9026b6] to [275f1e86b5].

1397
1398
1399
1400
1401
1402
1403
1404





1405
1406
1407
1408
1409
1410
1411
			[Whether we have netinet/in.h])
	])
	AC_CHECK_HEADER(netinet/tcp.h, [
		AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1,
			[Whether we have netinet/tcp.h])
	])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h sys/sockio.h])
	AC_CHECK_HEADERS([net/if.h net/if_arp.h net/if_dl.h net/if_types.h])





	AC_CHECK_FUNCS([if_indextoname if_nametoindex if_nameindex])
	AC_CHECK_TYPES([struct sockaddr_dl], [], [], [
		#ifdef HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef HAVE_NET_IF_DL_H
		# include <net/if_dl.h>







|
>
>
>
>
>







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
			[Whether we have netinet/in.h])
	])
	AC_CHECK_HEADER(netinet/tcp.h, [
		AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1,
			[Whether we have netinet/tcp.h])
	])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h sys/sockio.h])
	AC_CHECK_HEADERS([net/if.h], [], [], [
		#ifdef OF_HAVE_SYS_SOCKET_H
		# include <sys/socket.h>
		#endif
	])
	AC_CHECK_HEADERS([net/if_arp.h net/if_dl.h net/if_types.h])
	AC_CHECK_FUNCS([if_indextoname if_nametoindex if_nameindex])
	AC_CHECK_TYPES([struct sockaddr_dl], [], [], [
		#ifdef HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef HAVE_NET_IF_DL_H
		# include <net/if_dl.h>
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

	AC_CHECK_HEADER(netipx/ipx.h, [
		AC_DEFINE(OF_HAVE_NETIPX_IPX_H, 1,
			[Whether we have netipx/ipx.h])
	])
	AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_network, [], [
		AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [
			AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_addr.x_port, [
			], [], [
				#ifdef HAVE_SYS_TYPES_H
				# include <sys/types.h>
				#endif

				#ifdef OF_HAVE_NETIPX_IPX_H
				# include <netipx/ipx.h>
				#endif







|
|







1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

	AC_CHECK_HEADER(netipx/ipx.h, [
		AC_DEFINE(OF_HAVE_NETIPX_IPX_H, 1,
			[Whether we have netipx/ipx.h])
	])
	AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_network, [], [
		AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [
			AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_addr.x_port,
			[], [], [
				#ifdef HAVE_SYS_TYPES_H
				# include <sys/types.h>
				#endif

				#ifdef OF_HAVE_NETIPX_IPX_H
				# include <netipx/ipx.h>
				#endif

Modified src/OFArray.m from [c1836ceb46] to [2fdd882a05].

206
207
208
209
210
211
212
213
214
215
216


217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239


240
241
242
243
244
245
246
		objects[0] = firstObject;

		for (size_t i = 1; i < count; i++) {
			objects[i] = va_arg(arguments, id);
			OFEnsure(objects[i] != nil);
		}

		return [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}


}

- (instancetype)initWithArray: (OFArray *)array
{
	id *objects;
	size_t count;

	@try {
		count = array.count;
		objects = OFAllocMemory(count, sizeof(id));

		[array getObjects: objects
			  inRange: OFMakeRange(0, count)];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		return [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}


}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"







|



>
>



















|



>
>







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
		objects[0] = firstObject;

		for (size_t i = 1; i < count; i++) {
			objects[i] = va_arg(arguments, id);
			OFEnsure(objects[i] != nil);
		}

		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

- (instancetype)initWithArray: (OFArray *)array
{
	id *objects;
	size_t count;

	@try {
		count = array.count;
		objects = OFAllocMemory(count, sizeof(id));

		[array getObjects: objects
			  inRange: OFMakeRange(0, count)];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"

Modified src/OFDictionary.m from [e134f53095] to [624c31369c].

214
215
216
217
218
219
220
221
222
223
224
225
226


227
228
229
230
231
232
233
		keys = keys_.objects;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		return [self initWithObjects: objects
				     forKeys: keys
				       count: count];
	} @finally {
		objc_autoreleasePoolPop(pool);
	}


}

- (instancetype)initWithObject: (id)object forKey: (id)key
{
	@try {
		if (key == nil || object == nil)
			@throw [OFInvalidArgumentException exception];







|





>
>







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
		keys = keys_.objects;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects
				     forKeys: keys
				       count: count];
	} @finally {
		objc_autoreleasePoolPop(pool);
	}

	return self;
}

- (instancetype)initWithObject: (id)object forKey: (id)key
{
	@try {
		if (key == nil || object == nil)
			@throw [OFInvalidArgumentException exception];
332
333
334
335
336
337
338
339
340
341
342
343
344
345


346
347
348
349
350
351
352
		OFFreeMemory(keys);

		[self release];
		@throw e;
	}

	@try {
		return [self initWithObjects: objects
				     forKeys: keys
				       count: count];
	} @finally {
		OFFreeMemory(objects);
		OFFreeMemory(keys);
	}


}

- (id)objectForKey: (id)key
{
	OF_UNRECOGNIZED_SELECTOR
}








|






>
>







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
		OFFreeMemory(keys);

		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects
				     forKeys: keys
				       count: count];
	} @finally {
		OFFreeMemory(objects);
		OFFreeMemory(keys);
	}

	return self;
}

- (id)objectForKey: (id)key
{
	OF_UNRECOGNIZED_SELECTOR
}

Modified src/OFFileIRIHandler.m from [b18e6efaea] to [bf82260f3f].

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
#else
	OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970;
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct timeval times[2] = {
		{
			.tv_sec = (time_t)lastAccessTime,
			.tv_usec =
			    (int)((lastAccessTime - times[0].tv_sec) * 1000000)
		},
		{
			.tv_sec = (time_t)modificationTime,
			.tv_usec = (int)((modificationTime - times[1].tv_sec) *
			    1000000)
		},
	};

	if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes







|
|



|
|







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
#else
	OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970;
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct timeval times[2] = {
		{
			.tv_sec = (time_t)lastAccessTime,
			.tv_usec = (int)((lastAccessTime -
			    (time_t)lastAccessTime) * 1000000)
		},
		{
			.tv_sec = (time_t)modificationTime,
			.tv_usec = (int)((modificationTime -
			    (time_t)modificationTime) * 1000000)
		},
	};

	if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes

Modified src/OFFileManager.m from [34c9baec0c] to [c1beae22c2].

328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343


344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359


360
361
362
363
364
365
366
367
368
369

370

371

372
373
374


375
376
377
378
379
380
381

	return ret;
}
#endif

- (void)createDirectoryAtIRI: (OFIRI *)IRI
{

	OFIRIHandler *IRIHandler;

	if (IRI == nil)
		@throw [OFInvalidArgumentException exception];

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler createDirectoryAtIRI: IRI];


}

- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableIRI *mutableIRI;
	OFArray OF_GENERIC(OFString *) *components;
	OFMutableArray OF_GENERIC(OFIRI *) *componentIRIs;
	size_t componentIRIsCount;
	ssize_t i;

	if (IRI == nil)
		@throw [OFInvalidArgumentException exception];

	if (!createParents) {
		[self createDirectoryAtIRI: IRI];


		return;
	}

	/*
	 * Try blindly creating the directory first.
	 *
	 * The reason for this is that we might be sandboxed, so attempting to
	 * create any of the parent directories will fail, while creating the
	 * directory itself will work.
	 */

	if ([self directoryExistsAtIRI: IRI])

		return;


	@try {
		[self createDirectoryAtIRI: IRI];


		return;
	} @catch (OFCreateDirectoryFailedException *e) {
		/*
		 * If we didn't fail because any of the parents is missing,
		 * there is no point in trying to create the parents.
		 */
		if (e.errNo != ENOENT)







>









>
>
















>
>










>
|
>

>



>
>







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

	return ret;
}
#endif

- (void)createDirectoryAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFIRIHandler *IRIHandler;

	if (IRI == nil)
		@throw [OFInvalidArgumentException exception];

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler createDirectoryAtIRI: IRI];

	objc_autoreleasePoolPop(pool);
}

- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableIRI *mutableIRI;
	OFArray OF_GENERIC(OFString *) *components;
	OFMutableArray OF_GENERIC(OFIRI *) *componentIRIs;
	size_t componentIRIsCount;
	ssize_t i;

	if (IRI == nil)
		@throw [OFInvalidArgumentException exception];

	if (!createParents) {
		[self createDirectoryAtIRI: IRI];

		objc_autoreleasePoolPop(pool);
		return;
	}

	/*
	 * Try blindly creating the directory first.
	 *
	 * The reason for this is that we might be sandboxed, so attempting to
	 * create any of the parent directories will fail, while creating the
	 * directory itself will work.
	 */

	if ([self directoryExistsAtIRI: IRI]) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	@try {
		[self createDirectoryAtIRI: IRI];

		objc_autoreleasePoolPop(pool);
		return;
	} @catch (OFCreateDirectoryFailedException *e) {
		/*
		 * If we didn't fail because any of the parents is missing,
		 * there is no point in trying to create the parents.
		 */
		if (e.errNo != ENOENT)

Modified src/OFSet.m from [8d2f3f00f2] to [a482207723].

173
174
175
176
177
178
179
180
181
182
183


184
185
186
187
188
189
190
		OFFreeMemory(objects);

		[self release];
		@throw e;
	}

	@try {
		return [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}


}

- (instancetype)initWithArray: (OFArray *)array
{
	void *pool = objc_autoreleasePoolPush();
	size_t count;
	const id *objects;







|



>
>







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
		OFFreeMemory(objects);

		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

- (instancetype)initWithArray: (OFArray *)array
{
	void *pool = objc_autoreleasePoolPush();
	size_t count;
	const id *objects;
254
255
256
257
258
259
260
261
262
263
264


265
266
267
268
269
270
271
		objects[0] = firstObject;

		for (size_t i = 1; i < count; i++) {
			objects[i] = va_arg(arguments, id);
			OFEnsure(objects[i] != nil);
		}

		return [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}


}

- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}








|



>
>







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
		objects[0] = firstObject;

		for (size_t i = 1; i < count; i++) {
			objects[i] = va_arg(arguments, id);
			OFEnsure(objects[i] != nil);
		}

		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

Modified src/OFSystemInfo.m from [50bc975723] to [0621210a4b].

55
56
57
58
59
60
61
62

63
64
65
66
67
68
69

#import "OFSystemInfo.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
 #import "OFFile.h"

#endif
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFString.h"








|
>







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

#import "OFSystemInfo.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFString.h"

446
447
448
449
450
451
452


453
454
455
456
457
458
459
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];


# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;
	OFIRI *IRI;
	void *pool;

	if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil &&







>
>







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];
# elif defined(OF_WII) || defined(OF_NINTENDO_3DS)
	return [[OFFileManager defaultManager] currentDirectoryIRI];
# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;
	OFIRI *IRI;
	void *pool;

	if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil &&
536
537
538
539
540
541
542


543
544
545
546
547
548
549
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];


# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;

	if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil &&
	    var.length > 0)
		return [OFIRI fileIRIWithPath: var isDirectory: true];







>
>







539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];
# elif defined(OF_WII) || defined(OF_NINTENDO_3DS)
	return [[OFFileManager defaultManager] currentDirectoryIRI];
# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;

	if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil &&
	    var.length > 0)
		return [OFIRI fileIRIWithPath: var isDirectory: true];
613
614
615
616
617
618
619


620
621
622
623
624
625
626

	if (path == nil)
		return nil;

	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_MINT)
	return [OFIRI fileIRIWithPath: @"u:\\tmp" isDirectory: true];


# elif defined(OF_NINTENDO_SWITCH)
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, mountTmpFS);

	return tmpFSIRI;
# else
	OFString *path;







>
>







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

	if (path == nil)
		return nil;

	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_MINT)
	return [OFIRI fileIRIWithPath: @"u:\\tmp" isDirectory: true];
# elif defined(OF_WII) || defined(OF_NINTENDO_3DS)
	return [[OFFileManager defaultManager] currentDirectoryIRI];
# elif defined(OF_NINTENDO_SWITCH)
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, mountTmpFS);

	return tmpFSIRI;
# else
	OFString *path;

Modified src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m from [f03657380d] to [4ddf302e5d].

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
		return false;

	@try {
		for (size_t i = 0; nameindex[i].if_index != 0; i++) {
			OFString *name = [OFString
			    stringWithCString: nameindex[i].if_name
				     encoding: encoding];
			OFNumber *index = [OFNumber
			    numberWithUnsignedInt: nameindex[i].if_index];
			OFMutableDictionary *interface =
			    [ret objectForKey: name];

			if (interface == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			[interface setObject: index
				      forKey: OFNetworkInterfaceIndex];
		}
	} @finally {
		if_freenameindex(nameindex);
	}

	return true;







|









|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
		return false;

	@try {
		for (size_t i = 0; nameindex[i].if_index != 0; i++) {
			OFString *name = [OFString
			    stringWithCString: nameindex[i].if_name
				     encoding: encoding];
			OFNumber *idx = [OFNumber
			    numberWithUnsignedInt: nameindex[i].if_index];
			OFMutableDictionary *interface =
			    [ret objectForKey: name];

			if (interface == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			[interface setObject: idx
				      forKey: OFNetworkInterfaceIndex];
		}
	} @finally {
		if_freenameindex(nameindex);
	}

	return true;