* implement symblic link creation in ntfs_create
* rename ntfs_create -> __ntfs_create. add wrapers ntfs_create{_symlink,_device} * ntfsmount: implement .symlink * ntfsmount: fix readdir to emulate . and .. when needededge.strict_endians
parent
f45436a9df
commit
4652ad72c6
|
@ -71,9 +71,11 @@ 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)
|
||||
- Teach ntfs_create() to create special Interix files (charcter and
|
||||
block devices, FIFOs and sockets). Add @dev parameter to ntfs_create()
|
||||
for this. (Yura)
|
||||
- New APIs (dir.[ch]):
|
||||
ntfs_create_device() for Interix block and character devices
|
||||
creation.
|
||||
ntfs_crate_symlink() for Interix symbolic links creation. (Yura)
|
||||
- Teach ntfs_create() to create Interix FIFOs and sockets. (Yura)
|
||||
- Fix the -u option in ntfsundelete. Instead of a confusing optional
|
||||
parameter, there's a new option -i with a required parameter (Rich)
|
||||
|
||||
|
|
|
@ -49,9 +49,15 @@ 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 dev);
|
||||
dev_t type);
|
||||
extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni,
|
||||
ntfschar *name, u8 name_len, dev_t type, dev_t dev);
|
||||
extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni,
|
||||
ntfschar *name, u8 name_len, ntfschar *target, u8 target_len);
|
||||
|
||||
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,
|
||||
u8 name_len);
|
||||
|
||||
|
|
|
@ -1072,18 +1072,23 @@ err_out:
|
|||
}
|
||||
|
||||
/**
|
||||
* ntfs_create - create object on ntfs volume
|
||||
* __ntfs_create - create object on ntfs volume
|
||||
* @dir_ni: ntfs inode for directory in which create new object
|
||||
* @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())
|
||||
* @target: target in unicode (only for symlinks)
|
||||
* @target_len: length of target in unicode charcters
|
||||
*
|
||||
* Internal, use ntfs_create{_device,_symlink} wrappers instead.
|
||||
*
|
||||
* @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_IFLNK to create symbolic link
|
||||
* S_IFIFO to create FIFO
|
||||
* S_IFSOCK to create socket
|
||||
* other values are invalid.
|
||||
|
@ -1094,8 +1099,9 @@ err_out:
|
|||
* 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 dev)
|
||||
static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni,
|
||||
ntfschar *name, u8 name_len, dev_t type, dev_t dev,
|
||||
ntfschar *target, u8 target_len)
|
||||
{
|
||||
ntfs_inode *ni;
|
||||
FILE_NAME_ATTR *fn = NULL;
|
||||
|
@ -1104,10 +1110,7 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,
|
|||
|
||||
ntfs_log_trace("Entering.\n");
|
||||
/* Sanity checks. */
|
||||
if (!dir_ni || !name || !name_len || (type != S_IFREG &&
|
||||
type != S_IFDIR && type != S_IFIFO &&
|
||||
type != S_IFSOCK && type != S_IFCHR &&
|
||||
type != S_IFBLK)) {
|
||||
if (!dir_ni || !name || !name_len) {
|
||||
ntfs_log_error("Invalid arguments.");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1204,6 +1207,21 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,
|
|||
if (type == S_IFCHR)
|
||||
data->magic = INTX_CHARACTER_DEVICE;
|
||||
break;
|
||||
case S_IFLNK:
|
||||
data_len = sizeof(INTX_FILE_TYPES) +
|
||||
target_len * sizeof(ntfschar);
|
||||
data = malloc(data_len);
|
||||
if (!data) {
|
||||
err = errno;
|
||||
ntfs_log_error("Not enough memory for "
|
||||
"content of DATA "
|
||||
"attribute.\n");
|
||||
goto err_out;
|
||||
}
|
||||
data->magic = INTX_SYMBOLIC_LINK;
|
||||
memcpy(data->target, target,
|
||||
target_len * sizeof(ntfschar));
|
||||
break;
|
||||
case S_IFSOCK:
|
||||
data = NULL;
|
||||
data_len = 1;
|
||||
|
@ -1278,6 +1296,42 @@ err_out:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some wrappers around __ntfs_create() ...
|
||||
*/
|
||||
|
||||
ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,
|
||||
dev_t type)
|
||||
{
|
||||
if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&
|
||||
type != S_IFSOCK) {
|
||||
ntfs_log_error("Invalid arguments.");
|
||||
return NULL;
|
||||
}
|
||||
return __ntfs_create(dir_ni, name, name_len, type, 0, NULL, 0);
|
||||
}
|
||||
|
||||
ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,
|
||||
dev_t type, dev_t dev)
|
||||
{
|
||||
if (type != S_IFCHR && type != S_IFBLK) {
|
||||
ntfs_log_error("Invalid arguments.");
|
||||
return NULL;
|
||||
}
|
||||
return __ntfs_create(dir_ni, name, name_len, type, dev, NULL, 0);
|
||||
}
|
||||
|
||||
ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,
|
||||
ntfschar *target, u8 target_len)
|
||||
{
|
||||
if (!target || !target_len) {
|
||||
ntfs_log_error("Invalid arguments.");
|
||||
return NULL;
|
||||
}
|
||||
return __ntfs_create(dir_ni, name, name_len, S_IFLNK, 0,
|
||||
target, target_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_delete - delete file or directory from ntfs volume
|
||||
* @ni: ntfs inode for object to delte
|
||||
|
|
|
@ -516,6 +516,9 @@ static int ntfs_fuse_readdir(const char *path, void *buf,
|
|||
ni = ntfs_pathname_to_inode(vol, NULL, path);
|
||||
if (!ni)
|
||||
return -errno;
|
||||
if (!strcmp(path, "/"))
|
||||
filler(buf, ".", NULL, 0);
|
||||
filler(buf, "..", NULL, 0);
|
||||
if (ntfs_readdir(ni, &pos, &fill_ctx,
|
||||
(ntfs_filldir_t)ntfs_fuse_filler))
|
||||
err = -errno;
|
||||
|
@ -703,13 +706,14 @@ static int ntfs_fuse_chmod(const char *path,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int ntfs_fuse_create(const char *org_path, dev_t type, dev_t dev)
|
||||
static int ntfs_fuse_create(const char *org_path, dev_t type, dev_t dev,
|
||||
const char *target)
|
||||
{
|
||||
char *name;
|
||||
ntfschar *uname = NULL;
|
||||
ntfschar *uname = NULL, *utarget = NULL;
|
||||
ntfs_inode *dir_ni = NULL, *ni;
|
||||
char *path;
|
||||
int res = 0, uname_len;
|
||||
int res = 0, uname_len, utarget_len;
|
||||
|
||||
path = strdup(org_path);
|
||||
if (!path)
|
||||
|
@ -732,7 +736,25 @@ static int ntfs_fuse_create(const char *org_path, dev_t type, dev_t dev)
|
|||
goto exit;
|
||||
}
|
||||
/* Create object specified in @type. */
|
||||
ni = ntfs_create(dir_ni, uname, uname_len, type, dev);
|
||||
switch (type) {
|
||||
case S_IFCHR:
|
||||
case S_IFBLK:
|
||||
ni = ntfs_create_device(dir_ni, uname, uname_len, type,
|
||||
dev);
|
||||
break;
|
||||
case S_IFLNK:
|
||||
utarget_len = ntfs_mbstoucs(target, &utarget, 0);
|
||||
if (utarget_len < 0) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
ni = ntfs_create_symlink(dir_ni, uname, uname_len,
|
||||
utarget, utarget_len);
|
||||
break;
|
||||
default:
|
||||
ni = ntfs_create(dir_ni, uname, uname_len, type);
|
||||
break;
|
||||
}
|
||||
if (ni)
|
||||
ntfs_inode_close(ni);
|
||||
else
|
||||
|
@ -741,6 +763,8 @@ exit:
|
|||
free(uname);
|
||||
if (dir_ni)
|
||||
ntfs_inode_close(dir_ni);
|
||||
if (utarget)
|
||||
free(utarget);
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
@ -759,7 +783,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, 0);
|
||||
res = ntfs_fuse_create(path, S_IFREG, 0, NULL);
|
||||
if (!res)
|
||||
return ntfs_fuse_create_stream(path,
|
||||
stream_name, stream_name_len);
|
||||
|
@ -790,7 +814,7 @@ static int ntfs_fuse_mknod(const char *org_path, mode_t mode, dev_t dev)
|
|||
goto exit;
|
||||
}
|
||||
if (!stream_name_len)
|
||||
res = ntfs_fuse_create(path, mode & S_IFMT, dev);
|
||||
res = ntfs_fuse_create(path, mode & S_IFMT, dev, NULL);
|
||||
else
|
||||
res = ntfs_fuse_create_stream(path, stream_name,
|
||||
stream_name_len);
|
||||
|
@ -801,6 +825,14 @@ exit:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int ntfs_fuse_symlink(const char *to, const char *from)
|
||||
{
|
||||
if (strchr(from, ':') && /* n/a for named data streams. */
|
||||
ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)
|
||||
return -EINVAL;
|
||||
return ntfs_fuse_create(from, S_IFLNK, 0, to);
|
||||
}
|
||||
|
||||
static int ntfs_fuse_link(const char *old_path, const char *new_path)
|
||||
{
|
||||
char *name;
|
||||
|
@ -965,7 +997,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, 0);
|
||||
return ntfs_fuse_create(path, S_IFDIR, 0, NULL);
|
||||
}
|
||||
|
||||
static int ntfs_fuse_rmdir(const char *path)
|
||||
|
@ -1302,6 +1334,7 @@ static struct fuse_operations ntfs_fuse_oper = {
|
|||
.statfs = ntfs_fuse_statfs,
|
||||
.chmod = ntfs_fuse_chmod,
|
||||
.mknod = ntfs_fuse_mknod,
|
||||
.symlink = ntfs_fuse_symlink,
|
||||
.link = ntfs_fuse_link,
|
||||
.unlink = ntfs_fuse_unlink,
|
||||
.rename = ntfs_fuse_rename,
|
||||
|
|
Loading…
Reference in New Issue