- path = unix_build_extraction_path(dentry, ctx);
-retry_create:
- fd = open(path, O_TRUNC | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
- if (fd < 0) {
- if (errno == EEXIST && !unlink(path))
- goto retry_create;
- ERROR_WITH_ERRNO("Can't create regular file \"%s\"", path);
- return WIMLIB_ERR_OPEN;
- }
- /* On empty files, we can set timestamps immediately because we don't
- * need to write any data to them. */
- ret = unix_set_metadata(fd, inode, path, ctx);
- if (close(fd) && !ret) {
- ERROR_WITH_ERRNO("Error closing \"%s\"", path);
- ret = WIMLIB_ERR_WRITE;
+ /* Recognize special files in UNIX_DATA mode */
+ if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) &&
+ inode_get_unix_data(inode, &unix_data) &&
+ !S_ISREG(unix_data.mode))
+ {
+ path = unix_build_extraction_path(dentry, ctx);
+ retry_mknod:
+ if (mknod(path, unix_data.mode, unix_data.rdev)) {
+ if (errno == EPERM) {
+ WARNING_WITH_ERRNO("Can't create special "
+ "file \"%s\"", path);
+ ctx->num_special_files_ignored++;
+ return 0;
+ }
+ if (errno == EEXIST && !unlink(path))
+ goto retry_mknod;
+ ERROR_WITH_ERRNO("Can't create special file \"%s\"",
+ path);
+ return WIMLIB_ERR_MKNOD;
+ }
+ /* On special files, we can set timestamps immediately because
+ * we don't need to write any data to them. */
+ ret = unix_set_metadata(-1, inode, path, ctx);
+ } else {
+ int fd;
+
+ path = unix_build_extraction_path(dentry, ctx);
+ retry_create:
+ fd = open(path, O_TRUNC | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
+ if (fd < 0) {
+ if (errno == EEXIST && !unlink(path))
+ goto retry_create;
+ ERROR_WITH_ERRNO("Can't create regular file \"%s\"", path);
+ return WIMLIB_ERR_OPEN;
+ }
+ /* On empty files, we can set timestamps immediately because we
+ * don't need to write any data to them. */
+ ret = unix_set_metadata(fd, inode, path, ctx);
+ if (close(fd) && !ret) {
+ ERROR_WITH_ERRNO("Error closing \"%s\"", path);
+ ret = WIMLIB_ERR_WRITE;
+ }