diff --git a/ChangeLog b/ChangeLog index 6a358524..d689c476 100644 --- a/ChangeLog +++ b/ChangeLog @@ -71,6 +71,9 @@ xx/xx/2005 - 1.12.2-WIP starting to clone or restore. (Szaka) - Change @type parameter for ntfs_create() to be dev_t rather than internal NTFS_DT_* constants. (Yura) + - Teech ntfs_create() to create special Interix files (charcter and + block devices, FIFOs and sockets). Add @dev parameter to ntfs_create() + for this. (Yura) 10/10/2005 - 1.12.1 - Minor fix to location of mount.ntfs-fuse and mkfs.ntfs. diff --git a/include/ntfs/dir.h b/include/ntfs/dir.h index d15c0424..c6170e4f 100644 --- a/include/ntfs/dir.h +++ b/include/ntfs/dir.h @@ -49,7 +49,7 @@ extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, const char *pathname); extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type); + dev_t type, dev_t dev); extern int ntfs_delete(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len); extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, diff --git a/libntfs/dir.c b/libntfs/dir.c index f5dd2428..2e0009f4 100644 --- a/libntfs/dir.c +++ b/libntfs/dir.c @@ -1077,19 +1077,25 @@ err_out: * @name: unicode name of new object * @name_len: length of the name in unicode characters * @type: type of the object to create + * @dev: major and minor device numbers (obtained from makedev()) * * @type can be: * S_IFREG to create regular file * S_IFDIR to create directory + * S_IFBLK to create block device + * S_IFCHR to create character device * S_IFIFO to create FIFO * S_IFSOCK to create socket * other valuer are invalid. * + * @dev is only used if @type is S_IFBLK or S_IFCHR, in other cases it's value + * is ignored. + * * Return opened ntfs inode that describes created object on success or NULL * on error with errno set to the error code. */ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type) + dev_t type, dev_t dev) { ntfs_inode *ni; FILE_NAME_ATTR *fn = NULL; @@ -1100,7 +1106,8 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, /* Sanity checks. */ if (!dir_ni || !name || !name_len || (type != S_IFREG && type != S_IFDIR && type != S_IFIFO && - type != S_IFSOCK)) { + type != S_IFSOCK && type != S_IFCHR && + type != S_IFBLK)) { ntfs_log_error("Invalid arguments."); return NULL; } @@ -1125,7 +1132,7 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, si->last_data_change_time = utc2ntfs(ni->last_data_change_time); si->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); si->last_access_time = utc2ntfs(ni->last_access_time); - if (type == S_IFSOCK || type == S_IFIFO) { + if (type != S_IFREG && type != S_IFDIR) { si->file_attributes = FILE_ATTR_SYSTEM; ni->flags = FILE_ATTR_SYSTEM; } @@ -1175,13 +1182,46 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, goto err_out; } } else { + INTX_FILE *data; + int data_len; + + switch (type) { + case S_IFBLK: + case S_IFCHR: + data_len = offsetof(INTX_FILE, device_end); + data = malloc(data_len); + if (!data) { + err = errno; + ntfs_log_error("Not enough memory for " + "content of DATA " + "attribute.\n"); + goto err_out; + } + data->major = cpu_to_le64(major(dev)); + data->minor = cpu_to_le64(minor(dev)); + if (type == S_IFBLK) + data->magic = INTX_BLOCK_DEVICE; + if (type == S_IFCHR) + data->magic = INTX_CHARACTER_DEVICE; + break; + case S_IFSOCK: + data = NULL; + data_len = 1; + break; + default: + data = NULL; + data_len = 0; + break; + } /* Add DATA attribute to inode. */ - if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, NULL, - (type == S_IFSOCK) ? 1 : 0)) { + if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data, + data_len)) { err = errno; ntfs_log_error("Failed to add DATA attribute."); goto err_out; } + if (data) + free(data); } /* Create FILE_NAME attribute. */ fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); @@ -1197,7 +1237,7 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, fn->file_name_type = FILE_NAME_POSIX; if (type == S_IFDIR) fn->file_attributes = FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT; - if (type == S_IFIFO || type == S_IFSOCK) + if (type != S_IFREG && type != S_IFDIR) fn->file_attributes = FILE_ATTR_SYSTEM; fn->creation_time = utc2ntfs(ni->creation_time); fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); diff --git a/ntfsprogs/ntfsmount.c b/ntfsprogs/ntfsmount.c index 7ae3318a..dd523fb2 100644 --- a/ntfsprogs/ntfsmount.c +++ b/ntfsprogs/ntfsmount.c @@ -703,7 +703,7 @@ static int ntfs_fuse_chmod(const char *path, return -EOPNOTSUPP; } -static int ntfs_fuse_create(const char *org_path, dev_t type) +static int ntfs_fuse_create(const char *org_path, dev_t type, dev_t dev) { char *name; ntfschar *uname = NULL; @@ -732,7 +732,7 @@ static int ntfs_fuse_create(const char *org_path, dev_t type) goto exit; } /* Create object specified in @type. */ - ni = ntfs_create(dir_ni, uname, uname_len, type); + ni = ntfs_create(dir_ni, uname, uname_len, type, dev); if (ni) ntfs_inode_close(ni); else @@ -759,7 +759,7 @@ static int ntfs_fuse_create_stream(const char *path, * If such file does not exist, create it and try once * again to add stream to it. */ - res = ntfs_fuse_create(path, S_IFREG); + res = ntfs_fuse_create(path, S_IFREG, 0); if (!res) return ntfs_fuse_create_stream(path, stream_name, stream_name_len); @@ -775,15 +775,15 @@ static int ntfs_fuse_create_stream(const char *path, return res; } -static int ntfs_fuse_mknod(const char *org_path, mode_t mode, - dev_t dev __attribute__((unused))) +static int ntfs_fuse_mknod(const char *org_path, mode_t mode, dev_t dev) { char *path = NULL; ntfschar *stream_name; int stream_name_len; int res = 0; - if (mode && !(mode & (S_IFREG | S_IFIFO | S_IFSOCK))) + if (mode && !(mode & + (S_IFREG | S_IFIFO | S_IFSOCK | S_IFCHR | S_IFBLK))) return -EOPNOTSUPP; stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) @@ -793,7 +793,7 @@ static int ntfs_fuse_mknod(const char *org_path, mode_t mode, goto exit; } if (!stream_name_len) - res = ntfs_fuse_create(path, mode & S_IFMT); + res = ntfs_fuse_create(path, mode & S_IFMT, dev); else res = ntfs_fuse_create_stream(path, stream_name, stream_name_len); @@ -968,7 +968,7 @@ static int ntfs_fuse_mkdir(const char *path, { if (strchr(path, ':') && ctx->streams == NF_STREAMS_INTERFACE_WINDOWS) return -EINVAL; /* n/a for named data streams. */ - return ntfs_fuse_create(path, S_IFDIR); + return ntfs_fuse_create(path, S_IFDIR, 0); } static int ntfs_fuse_rmdir(const char *path)