{"id":16189150,"url":"https://github.com/jhermsmeier/node-udif","last_synced_at":"2025-07-17T16:04:48.771Z","repository":{"id":57384951,"uuid":"82322165","full_name":"jhermsmeier/node-udif","owner":"jhermsmeier","description":"Apple Universal Disk Image Format (UDIF/DMG)","archived":false,"fork":false,"pushed_at":"2020-07-25T14:08:13.000Z","size":274,"stargazers_count":12,"open_issues_count":5,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-08T06:16:01.709Z","etag":null,"topics":["apple","apple-disk-image","disk","disk-image","dmg","udif"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jhermsmeier.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-17T17:36:57.000Z","updated_at":"2024-04-09T18:25:43.000Z","dependencies_parsed_at":"2022-08-28T14:51:52.213Z","dependency_job_id":null,"html_url":"https://github.com/jhermsmeier/node-udif","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhermsmeier%2Fnode-udif","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhermsmeier%2Fnode-udif/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhermsmeier%2Fnode-udif/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhermsmeier%2Fnode-udif/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jhermsmeier","download_url":"https://codeload.github.com/jhermsmeier/node-udif/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234037379,"owners_count":18769745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple","apple-disk-image","disk","disk-image","dmg","udif"],"created_at":"2024-10-10T07:34:19.954Z","updated_at":"2025-01-15T12:17:52.577Z","avatar_url":"https://github.com/jhermsmeier.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Apple Universal Disk Image Format (UDIF/DMG)\n[![npm](https://img.shields.io/npm/v/udif.svg?style=flat-square)](https://npmjs.com/package/udif)\n[![npm license](https://img.shields.io/npm/l/udif.svg?style=flat-square)](https://npmjs.com/package/udif)\n[![npm downloads](https://img.shields.io/npm/dm/udif.svg?style=flat-square)](https://npmjs.com/package/udif)\n[![build status](https://img.shields.io/travis/jhermsmeier/node-udif/master.svg?style=flat-square)](https://travis-ci.org/jhermsmeier/node-udif)\n\n## Install via [npm](https://npmjs.com)\n\n```sh\n$ npm install --save udif\n```\n\n## Used by\n\n- **[Etcher](https://github.com/resin-io/etcher)** to support Apple's disk image format (.dmg)\n\n## Related Modules\n\n- [apple-partition-map](https://github.com/jhermsmeier/node-gpt) – Parse / construct Apple Partition Maps\n- [blockdevice](https://github.com/jhermsmeier/node-blockdevice) – Read from / write to block devices\n- [disk](https://github.com/jhermsmeier/node-disk) – Disk / image toolbox\n\n## Usage\n\n```js\nvar UDIF = require( 'udif' )\n```\n\n### Opening a .dmg image\n\n```js\nvar dmg = new UDIF.Image( 'path/to/image.dmg' )\n\ndmg.open( function( error ) {\n  // ...\n})\n```\n\n### Closing the image\n\n```js\ndmg.close( function( error ) {\n  // ...\n})\n```\n\n### Determining the uncompressed size\n\nNote that the image has to be opened to determine the uncompressed size,\nas this is read from the resource fork.\n\n```js\nUDIF.getUncompressedSize( 'path/to/image.dmg', function( error, size ) {\n  console.log( size, 'bytes' )\n  // \u003e 629145600 bytes\n})\n```\n\n```js\nvar dmg = new UDIF.Image( 'path/to/image.dmg' )\n\ndmg.open( function( error ) {\n  console.log( dmg.getUncompressedSize(), 'bytes' )\n  // \u003e 629145600 bytes\n})\n```\n\n### Creating a readable stream\n\n```js\nvar readableStream = UDIF.createReadStream( 'path/to/image.dmg' )\n```\n\nOr, if you already have an instance of `UDIF.Image`:\n\n```js\nvar readableStream = dmg.createReadStream()\n```\n\n### Extracting the raw disk image\n\nExtracting the uncompressed, raw disk image from a `.dmg` file becomes as easy as the following:\n\n```js\nUDIF.createReadStream( 'path/to/image.dmg' )\n  .pipe( fs.createWriteStream( '/path/to/destination.img' ) )\n```\n\n### Sparse streams\n\n```js\nvar sparseStream = UDIF.createSparseReadStream( 'path/to/image.dmg' )\n```\n\nSparse readstreams are in `objectMode` and will emit objects of the shape `{ buffer, position }`.\nThis means you'll need a writable stream that is also in `objectMode` and knows how to handle these.\nFor the sake of brevity, the following example only demonstrates passing a chunk's properties to `fs.write()`;\n\n```js\nsparseStream.on( 'data', function( chunk ) {\n  fs.writeSync( fd, chunk.buffer, 0, chunk.buffer.length, chunk.position )\n})\n```\n\n### Using a custom file system\n\n```js\nvar dmg = new UDIF.Image( 'https://github.com/resin-io/etcher/releases/download/v1.2.0/Etcher-1.2.0.dmg', {\n  fs: new HttpFs()\n})\n\ndmg.open( function( error ) {\n  // ...\n})\n```\n\n### Inspecting the UDIF footer\n\nThe footer (aka the \"Koly Block\") contains pointers to the XML metadata,\ndata fork \u0026 resource fork as well as checksums.\n\n```js\n// Once the dmg has been opened:\ndmg.open( function( error ) {\n  console.log( dmg.footer )\n})\n```\n\n```js\nKolyBlock {\n  signature: 1802464377,\n  version: 4,\n  headerSize: 512,\n  flags: 1,\n  runningDataForkOffset: 0,\n  dataForkOffset: 0,\n  dataForkLength: 6585140266,\n  resourceForkOffset: 0,\n  resourceForkLength: 0,\n  segmentNumber: 1,\n  segmentCount: 1,\n  segmentId: \u003cBuffer 18 66 9e 31 fa 6 d 4 f 7 d aa d0 f2 50 12 8 f 49 54\u003e,\n  dataChecksum: Checksum { type: 2, bits: 32, value: 'c2208200' },\n  xmlOffset: 6585140266,\n  xmlLength: 1752206,\n  reserved1: \u003cBuffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...\u003e,\n  checksum: Checksum { type: 2, bits: 32, value: '3f40bb47' },\n  imageVariant: 1,\n  sectorCount: 15178432,\n  reserved2: 0,\n  reserved3: 0,\n  reserved4: 0,\n}\n```\n\n### Inspecting the XML Metadata\n\nThe XML data is a [Property List](https://en.wikipedia.org/wiki/Property_list), (or plist) which contains a block map under `resource-fork.blkx`.\n\n```js\ndmg.open( function( error ) {\n  console.log( dmg.resourceFork )\n})\n```\n\n```js\n{\n  blkx: [{\n    id: -1,\n    attributes: 80,\n    name: 'Driver Descriptor Map (DDM : 0)',\n    coreFoundationName: 'Driver Descriptor Map (DDM : 0)',\n    map: BlockMap {\n      signature: 1835627368,\n      version: 1,\n      sectorNumber: 0,\n      sectorCount: 1,\n      dataOffset: 0,\n      buffersNeeded: 520,\n      blockDescriptorCount: 0,\n      reserved1: 0,\n      reserved2: 0,\n      reserved3: 0,\n      reserved4: 0,\n      reserved5: 0,\n      reserved6: 0,\n      checksum: Checksum { type: 2, bits: 32, value: '698a85ed' },\n      blockCount: 2,\n      blocks: [\n        Block {\n          type: 2147483653,\n          description: 'UDZO (zlib-compressed)',\n          comment: '',\n          sectorNumber: 0,\n          sectorCount: 1,\n          compressedOffset: 0,\n          compressedLength: 22\n        },\n        Block {\n          type: 4294967295,\n          description: 'TERMINATOR',\n          comment: '',\n          sectorNumber: 1,\n          sectorCount: 0,\n          compressedOffset: 22,\n          compressedLength: 0\n        }\n      ]\n    }\n  }, {\n    id: 0,\n    attributes: 80,\n    name: 'WINDOWSSUPPORT (Apple_ISO : 1)',\n    coreFoundationName: 'WINDOWSSUPPORT (Apple_ISO : 1)',\n    map: BlockMap {\n      signature: 1835627368,\n      version: 1,\n      sectorNumber: 1,\n      sectorCount: 3,\n      dataOffset: 0,\n      buffersNeeded: 520,\n      blockDescriptorCount: 1,\n      reserved1: 0,\n      reserved2: 0,\n      reserved3: 0,\n      reserved4: 0,\n      reserved5: 0,\n      reserved6: 0,\n      checksum: Checksum { type: 2, bits: 32, value: '6c1ce17e' },\n      blockCount: 2,\n      blocks: [\n        Block {\n          type: 2147483653,\n          description: 'UDZO (zlib-compressed)',\n          comment: '',\n          sectorNumber: 0,\n          sectorCount: 3,\n          compressedOffset: 22,\n          compressedLength: 24\n        },\n        Block {\n          type: 4294967295,\n          description: 'TERMINATOR',\n          comment: '',\n          sectorNumber: 3,\n          sectorCount: 0,\n          compressedOffset: 46,\n          compressedLength: 0\n        }\n      ]\n    }\n  }, {\n    id: 1,\n    attributes: 80,\n    name: 'Apple (Apple_partition_map : 2)',\n    coreFoundationName: 'Apple (Apple_partition_map : 2)',\n    map: BlockMap {\n      signature: 1835627368,\n      version: 1,\n      sectorNumber: 4,\n      sectorCount: 60,\n      dataOffset: 0,\n      buffersNeeded: 520,\n      blockDescriptorCount: 2,\n      reserved1: 0,\n      reserved2: 0,\n      reserved3: 0,\n      reserved4: 0,\n      reserved5: 0,\n      reserved6: 0,\n      checksum: Checksum { type: 2, bits: 32, value: '115fc68e' },\n      blockCount: 2,\n      blocks: [\n        Block {\n          type: 2147483653,\n          description: 'UDZO (zlib-compressed)',\n          comment: '',\n          sectorNumber: 0,\n          sectorCount: 60,\n          compressedOffset: 46,\n          compressedLength: 358\n        },\n        Block {\n          type: 4294967295,\n          description: 'TERMINATOR',\n          comment: '',\n          sectorNumber: 60,\n          sectorCount: 0,\n          compressedOffset: 404,\n          compressedLength: 0\n        }\n      ]\n    }\n  }, {\n    id: 2,\n    attributes: 80,\n    name: 'Macintosh (Apple_Driver_ATAPI : 3)',\n    coreFoundationName: 'Macintosh (Apple_Driver_ATAPI : 3)',\n    map: BlockMap {\n      signature: 1835627368,\n      version: 1,\n      sectorNumber: 64,\n      sectorCount: 2020420,\n      dataOffset: 0,\n      buffersNeeded: 520,\n      blockDescriptorCount: 3,\n      reserved1: 0,\n      reserved2: 0,\n      reserved3: 0,\n      reserved4: 0,\n      reserved5: 0,\n      reserved6: 0,\n      checksum: Checksum { type: 2, bits: 32, value: 'b2bb86f8' },\n      blockCount: 3948,\n      blocks: [\n        Block {\n          type: 2147483653,\n          description: 'UDZO (zlib-compressed)',\n          comment: '',\n          sectorNumber: 0,\n          sectorCount: 512,\n          compressedOffset: 404,\n          compressedLength: 25147\n        },\n        Block {\n          type: 2147483653,\n          description: 'UDZO (zlib-compressed)',\n          comment: '',\n          sectorNumber: 512,\n          sectorCount: 512,\n          compressedOffset: 25551,\n          compressedLength: 29149\n        },\n        ... more items\n      ]\n    }\n  }, {\n    id: 3,\n    attributes: 80,\n    name: ' (Apple_Free : 4)',\n    coreFoundationName: ' (Apple_Free : 4)',\n    map: BlockMap {\n      signature: 1835627368,\n      version: 1,\n      sectorNumber: 2020484,\n      sectorCount: 4,\n      dataOffset: 0,\n      buffersNeeded: 0,\n      blockDescriptorCount: 4,\n      reserved1: 0,\n      reserved2: 0,\n      reserved3: 0,\n      reserved4: 0,\n      reserved5: 0,\n      reserved6: 0,\n      checksum: Checksum { type: 2, bits: 32, value: '00000000' },\n      blockCount: 2,\n      blocks: [\n        Block {\n          type: 2,\n          description: 'FREE (unallocated)',\n          comment: '',\n          sectorNumber: 0,\n          sectorCount: 4,\n          compressedOffset: 984141554,\n          compressedLength: 0\n        },\n        Block {\n          type: 4294967295,\n          description: 'TERMINATOR',\n          comment: '',\n          sectorNumber: 4,\n          sectorCount: 0,\n          compressedOffset: 984141554,\n          compressedLength: 0\n        }\n      ]\n    }\n  }, {\n    id: 4,\n    attributes: 80,\n    name: 'Mac_OS_X (Apple_HFS : 5)',\n    coreFoundationName: 'Mac_OS_X (Apple_HFS : 5)',\n    map: BlockMap {\n      signature: 1835627368,\n      version: 1,\n      sectorNumber: 2020488,\n      sectorCount: 13157944,\n      dataOffset: 0,\n      buffersNeeded: 520,\n      blockDescriptorCount: 5,\n      reserved1: 0,\n      reserved2: 0,\n      reserved3: 0,\n      reserved4: 0,\n      reserved5: 0,\n      reserved6: 0,\n      checksum: Checksum { type: 2, bits: 32, value: '39ce04b6' },\n      blockCount: 25387,\n      blocks: [\n        Block {\n          type: 2147483646,\n          description: 'COMMENT',\n          comment: '+beg',\n          sectorNumber: 0,\n          sectorCount: 0,\n          compressedOffset: 984141554,\n          compressedLength: 0\n        },\n        Block {\n          type: 2147483653,\n          description: 'UDZO (zlib-compressed)',\n          comment: '',\n          sectorNumber: 0,\n          sectorCount: 512,\n          compressedOffset: 984141554,\n          compressedLength: 1812\n        },\n        ... more items\n      ]\n    }\n  }],\n  cSum: [{\n    Attributes: '0x0000',\n    Data: \u003cBuffer 01 00 02 00 00 00 00 00 00 00\u003e,\n    ID: '0',\n    Name: null\n  }, {\n    Attributes: '0x0000',\n    Data: \u003cBuffer 01 00 02 00 00 00 10 fc a8 3f\u003e,\n    ID: '1',\n    Name: null\n  }, {\n    Attributes: '0x0000',\n    Data: \u003cBuffer 01 00 02 00 00 00 10 37 71 ef\u003e,\n    ID: '2',\n    Name: null\n  }],\n  nsiz: [{\n    Attributes: '0x0000',\n    Data: \u003cBuffer 3 c 3 f 78 6 d 6 c 20 76 65 72 73 69 6 f 6e 3 d 22 31 2e 30 22 20 65 6e 63 6 f 64 69 6e 67 3 d 22 55 54 46 2 d 38 22 3 f 3e 0 a 3 c 21 44 4 f 43 54 59 50 45 20 70 ...\u003e,\n    ID: '0',\n    Name: null\n  }, {\n    Attributes: '0x0000',\n    Data: \u003cBuffer 3 c 3 f 78 6 d 6 c 20 76 65 72 73 69 6 f 6e 3 d 22 31 2e 30 22 20 65 6e 63 6 f 64 69 6e 67 3 d 22 55 54 46 2 d 38 22 3 f 3e 0 a 3 c 21 44 4 f 43 54 59 50 45 20 70 ...\u003e,\n    ID: '1',\n    Name: null\n  }, {\n    Attributes: '0x0000',\n    Data: \u003cBuffer 3 c 3 f 78 6 d 6 c 20 76 65 72 73 69 6 f 6e 3 d 22 31 2e 30 22 20 65 6e 63 6 f 64 69 6e 67 3 d 22 55 54 46 2 d 38 22 3 f 3e 0 a 3 c 21 44 4 f 43 54 59 50 45 20 70 ...\u003e,\n    ID: '2',\n    Name: null\n  }],\n  plst: [{\n    Attributes: '0x0050',\n    Data: \u003cBuffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...\u003e,\n    ID: '0',\n    Name: null\n  }],\n  size: [{\n    Attributes: '0x0000',\n    Data: \u003cBuffer 05 00 01 00 00 00 00 60 8 c 91 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...\u003e,\n    ID: '2',\n    Name: null\n  }]\n}\n\n```\n\n## References\n\n- [Demystifying the DMG File Format](http://newosxbook.com/DMG.html)\n- [VBox/Storage/DMG.cpp](https://www.virtualbox.org/svn/vbox/trunk/src/VBox/Storage/DMG.cpp)\n- [man1/hdiutil.1](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/hdiutil.1.html)\n- [Wikipedia/Apple_Disk_Image](https://en.wikipedia.org/wiki/Apple_Disk_Image)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhermsmeier%2Fnode-udif","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjhermsmeier%2Fnode-udif","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhermsmeier%2Fnode-udif/lists"}