Merge branch 'master' into sam460ex
This commit is contained in:
commit
e06bde5a30
@ -9,6 +9,7 @@ UsePrivateHeaders kernel ;
|
|||||||
|
|
||||||
KernelAddon ntfs :
|
KernelAddon ntfs :
|
||||||
attributes.c
|
attributes.c
|
||||||
|
fake_attributes.c
|
||||||
mime_table.c
|
mime_table.c
|
||||||
utils.c
|
utils.c
|
||||||
ntfsdir.c
|
ntfsdir.c
|
||||||
|
@ -25,41 +25,6 @@
|
|||||||
|
|
||||||
//TODO: notify*()
|
//TODO: notify*()
|
||||||
|
|
||||||
|
|
||||||
int32 kBeOSTypeCookie = 0x1234;
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
set_mime(vnode *node, const char *filename)
|
|
||||||
{
|
|
||||||
struct ext_mime *p;
|
|
||||||
int32 namelen, ext_len;
|
|
||||||
|
|
||||||
TRACE("set_mime - for [%s]\n", filename);
|
|
||||||
|
|
||||||
node->mime = NULL;
|
|
||||||
|
|
||||||
namelen = strlen(filename);
|
|
||||||
|
|
||||||
for (p = mimes; p->extension; p++) {
|
|
||||||
ext_len = strlen(p->extension);
|
|
||||||
|
|
||||||
if (namelen <= ext_len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (filename[namelen-ext_len-1] != '.')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!strcasecmp(filename + namelen - ext_len, p->extension))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->mime = p->mime;
|
|
||||||
|
|
||||||
return B_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
||||||
{
|
{
|
||||||
|
@ -14,9 +14,6 @@
|
|||||||
|
|
||||||
#include "ntfs.h"
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
status_t set_mime(vnode *node, const char *filename);
|
|
||||||
|
|
||||||
status_t fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name,
|
status_t fs_create_attrib(fs_volume *_vol, fs_vnode *_node, const char* name,
|
||||||
uint32 type, int openMode, void** _cookie);
|
uint32 type, int openMode, void** _cookie);
|
||||||
status_t fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie);
|
status_t fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie);
|
||||||
|
337
src/add-ons/kernel/file_systems/ntfs/fake_attributes.c
Normal file
337
src/add-ons/kernel/file_systems/ntfs/fake_attributes.c
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
Copyright 1999-2001, Be Incorporated. All Rights Reserved.
|
||||||
|
This file may be used under the terms of the Be Sample Code License.
|
||||||
|
*/
|
||||||
|
/* fake_attributes.c
|
||||||
|
* handles mime type information for ntfs
|
||||||
|
* gets/sets mime information in vnode
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MIME_STRING_TYPE 'MIMS'
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fs_attr.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
#include "fake_attributes.h"
|
||||||
|
#include "mime_table.h"
|
||||||
|
|
||||||
|
int32 kBeOSTypeCookie = 0x1234;
|
||||||
|
|
||||||
|
status_t set_mime(vnode *node, const char *filename)
|
||||||
|
{
|
||||||
|
struct ext_mime *p;
|
||||||
|
int32 namelen, ext_len;
|
||||||
|
node->mime = NULL;
|
||||||
|
namelen = strlen(filename);
|
||||||
|
|
||||||
|
for (p=mimes; p->extension; p++) {
|
||||||
|
ext_len = strlen(p->extension);
|
||||||
|
|
||||||
|
if (namelen <= ext_len)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (filename[namelen-ext_len-1] != '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!strcasecmp(filename + namelen - ext_len, p->extension))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node->mime = p->mime;
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
TRACE("fake_open_attrdir - ENTER\n");
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
if ((*_cookie = malloc(sizeof(uint32))) == NULL) {
|
||||||
|
result = ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(int32 *)(*_cookie) = 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
TRACE("fs_open_attrdir - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_close_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
|
||||||
|
TRACE("fake_close_attrdir - ENTER\n");
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
*(int32 *)_cookie = 1;
|
||||||
|
|
||||||
|
TRACE("fake_close_attrdir - EXIT\n");
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_free_attrib_dir_cookie(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
TRACE("fake_free_attrib_dir_cookie - ENTER\n");
|
||||||
|
|
||||||
|
if (_cookie == NULL) {
|
||||||
|
TRACE("fake_free_attrib_dir_cookie - error:called with null cookie\n");
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(int32 *)_cookie = 0x87654321;
|
||||||
|
free(_cookie);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
TRACE("fake_free_attrib_dir_cookie - EXIT, result is %s\n",
|
||||||
|
strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
TRACE("fake_rewind_attrcookie - ENTER\n");
|
||||||
|
|
||||||
|
if (_cookie == NULL) {
|
||||||
|
TRACE("fake_rewind_attrcookie - error: fs_rewind_attrcookie"
|
||||||
|
"called with null cookie\n");
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(uint32 *)_cookie = 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
TRACE("fake_rewind_attrcookie - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_read_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
||||||
|
struct dirent *entry, size_t bufsize, uint32 *num)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
vnode *node = (vnode *)_node->private_node;
|
||||||
|
|
||||||
|
int32 *cookie = (int32 *)_cookie;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
TRACE("fake_read_attrdir - ENTER\n");
|
||||||
|
|
||||||
|
*num = 0;
|
||||||
|
|
||||||
|
if ((*cookie == 0) && (node->mime)) {
|
||||||
|
*num = 1;
|
||||||
|
|
||||||
|
entry->d_ino = node->vnid;
|
||||||
|
entry->d_dev = ns->id;
|
||||||
|
entry->d_reclen = 10;
|
||||||
|
strcpy(entry->d_name, "BEOS:TYPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
*cookie = 1;
|
||||||
|
|
||||||
|
TRACE("fake_read_attrdir - EXIT\n");
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
|
||||||
|
int openMode, void **_cookie)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
vnode *node = (vnode *)_node->private_node;
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
TRACE("fake_open_attrib - ENTER\n");
|
||||||
|
|
||||||
|
if (strcmp(name, "BEOS:TYPE")) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->mime == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_cookie = &kBeOSTypeCookie;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
TRACE("fake_open_attrib - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_close_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie)
|
||||||
|
{
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node, void *cookie)
|
||||||
|
{
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_read_attrib_stat(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
||||||
|
struct stat *stat)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
vnode *node = (vnode *)_node->private_node;
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
TRACE("fake_read_attr_stat - ENTER\n");
|
||||||
|
|
||||||
|
if (_cookie != &kBeOSTypeCookie) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->mime == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
stat->st_type = MIME_STRING_TYPE;
|
||||||
|
stat->st_size = strlen(node->mime) + 1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
TRACE("fake_read_attrib_stat - EXIT, result is %s\n",
|
||||||
|
strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
||||||
|
off_t pos,void *buffer, size_t *_length)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
vnode *node = (vnode *)_node->private_node;
|
||||||
|
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
TRACE("fake_read_attr - ENTER\n");
|
||||||
|
|
||||||
|
if (_cookie != &kBeOSTypeCookie) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->mime == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos < 0) || (pos > strlen(node->mime))) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(buffer, node->mime + pos, *_length - 1);
|
||||||
|
((char *)buffer)[*_length - 1] = 0;
|
||||||
|
*_length = strlen(buffer) + 1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
TRACE("fake_read_attr - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
fake_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
|
||||||
|
const void *buffer, size_t *_length)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace *)_vol->private_volume;
|
||||||
|
|
||||||
|
int result = B_NO_ERROR;
|
||||||
|
|
||||||
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
|
TRACE("fake_write_attr - ENTER\n");
|
||||||
|
|
||||||
|
*_length = 0;
|
||||||
|
|
||||||
|
if (_cookie != &kBeOSTypeCookie) {
|
||||||
|
result = ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("fake_write_attrib - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
|
UNLOCK_VOL(ns);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
39
src/add-ons/kernel/file_systems/ntfs/fake_attributes.h
Normal file
39
src/add-ons/kernel/file_systems/ntfs/fake_attributes.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Copyright 1999-2001, Be Incorporated. All Rights Reserved.
|
||||||
|
This file may be used under the terms of the Be Sample Code License.
|
||||||
|
*/
|
||||||
|
/* fake_attributes.h
|
||||||
|
* handles mime type information for ntfs
|
||||||
|
* gets/sets mime information in vnode
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NTFS_FAKE_ATTR_H_
|
||||||
|
#define NTFS_FAKE_ATTR_H_
|
||||||
|
|
||||||
|
#include <fs_attr.h>
|
||||||
|
|
||||||
|
status_t set_mime(vnode *node, const char *filename);
|
||||||
|
|
||||||
|
status_t fake_open_attrib_dir(fs_volume *_vol, fs_vnode *_node,
|
||||||
|
void **_cookie);
|
||||||
|
status_t fake_close_attrib_dir(fs_volume *_vol, fs_vnode *_node,
|
||||||
|
void *_cookie);
|
||||||
|
status_t fake_free_attrib_dir_cookie(fs_volume *_vol, fs_vnode *_node,
|
||||||
|
void *_cookie);
|
||||||
|
status_t fake_rewind_attrib_dir(fs_volume *_vol, fs_vnode *_node,
|
||||||
|
void *_cookie);
|
||||||
|
status_t fake_read_attrib_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
||||||
|
struct dirent *buf, size_t bufsize, uint32 *num);
|
||||||
|
status_t fake_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
|
||||||
|
int openMode, void **_cookie);
|
||||||
|
status_t fake_close_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie);
|
||||||
|
status_t fake_free_attrib_cookie(fs_volume *_vol, fs_vnode *_node,
|
||||||
|
void *cookie);
|
||||||
|
status_t fake_read_attrib_stat(fs_volume *_vol, fs_vnode *_node, void *cookie,
|
||||||
|
struct stat *stat);
|
||||||
|
status_t fake_read_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie,
|
||||||
|
off_t pos,void *buffer, size_t *_length);
|
||||||
|
status_t fake_write_attrib(fs_volume *_vol, fs_vnode *_node, void *cookie,
|
||||||
|
off_t pos, const void *buffer, size_t *_length);
|
||||||
|
|
||||||
|
#endif //NTFS_FAKE_ATTR_H_
|
@ -38,6 +38,7 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include "attributes.h"
|
#include "attributes.h"
|
||||||
|
#include "fake_attributes.h"
|
||||||
#include "lock.h"
|
#include "lock.h"
|
||||||
#include "ntfs.h"
|
#include "ntfs.h"
|
||||||
#include "volume_util.h"
|
#include "volume_util.h"
|
||||||
@ -113,6 +114,176 @@ get_node_type(ntfs_inode* ni, int* _type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u64
|
||||||
|
ntfs_inode_lookup(fs_volume *_vol, ino_t parent, const char *name)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
|
||||||
|
u64 ino = (u64)-1;
|
||||||
|
u64 inum;
|
||||||
|
ntfs_inode *dir_ni;
|
||||||
|
|
||||||
|
/* Open target directory. */
|
||||||
|
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
||||||
|
if (dir_ni) {
|
||||||
|
/* Lookup file */
|
||||||
|
inum = ntfs_inode_lookup_by_mbsname(dir_ni, name);
|
||||||
|
/* never return inodes 0 and 1 */
|
||||||
|
if (MREF(inum) <= 1) {
|
||||||
|
inum = (u64)-1;
|
||||||
|
errno = ENOENT;
|
||||||
|
}
|
||||||
|
if (ntfs_inode_close(dir_ni)
|
||||||
|
|| (inum == (u64)-1))
|
||||||
|
ino = (u64)-1;
|
||||||
|
else
|
||||||
|
ino = MREF(inum);
|
||||||
|
}
|
||||||
|
return (ino);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
ntfs_remove(fs_volume *_vol, ino_t parent, const char *name)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
|
||||||
|
ntfschar *uname = NULL;
|
||||||
|
ntfs_inode *dir_ni = NULL, *ni = NULL;
|
||||||
|
int res = B_OK, uname_len;
|
||||||
|
u64 iref;
|
||||||
|
|
||||||
|
/* Open parent directory. */
|
||||||
|
dir_ni = ntfs_inode_open(ns->ntvol, parent);
|
||||||
|
if (!dir_ni) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
/* Generate unicode filename. */
|
||||||
|
uname_len = ntfs_mbstoucs(name, &uname);
|
||||||
|
if (uname_len < 0) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
/* Open object for delete. */
|
||||||
|
iref = ntfs_inode_lookup_by_mbsname(dir_ni, name);
|
||||||
|
if (iref == (u64)-1) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
/* deny unlinking metadata files */
|
||||||
|
if (MREF(iref) < FILE_first_user) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, MREF(iref));
|
||||||
|
if (!ni) {
|
||||||
|
res = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntfs_delete(ns->ntvol, (char*)NULL, ni, dir_ni, uname, uname_len))
|
||||||
|
res = EINVAL;
|
||||||
|
/* ntfs_delete() always closes ni and dir_ni */
|
||||||
|
ni = dir_ni = NULL;
|
||||||
|
exit:
|
||||||
|
if (ni)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
if (dir_ni)
|
||||||
|
ntfs_inode_close(dir_ni);
|
||||||
|
|
||||||
|
free(uname);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
do_unlink(fs_volume *_vol, vnode *dir, const char *name, bool isdir)
|
||||||
|
{
|
||||||
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
|
ino_t vnid;
|
||||||
|
vnode *node = NULL;
|
||||||
|
ntfs_inode *ni = NULL;
|
||||||
|
ntfs_inode *bi = NULL;
|
||||||
|
ntfschar *uname = NULL;
|
||||||
|
int unameLength;
|
||||||
|
|
||||||
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
|
unameLength = ntfs_mbstoucs(name, &uname);
|
||||||
|
if (unameLength < 0) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bi = ntfs_inode_open(ns->ntvol, dir->vnid);
|
||||||
|
if (bi == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vnid = MREF(ntfs_inode_lookup_by_name(bi, uname, unameLength));
|
||||||
|
|
||||||
|
if ( vnid == (u64)-1 || vnid == FILE_root) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = get_vnode(_vol, vnid, (void**)&node);
|
||||||
|
|
||||||
|
if (result != B_NO_ERROR || node==NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
||||||
|
if (ni == NULL) {
|
||||||
|
result = ENOENT;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isdir) {
|
||||||
|
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
||||||
|
result = ENOTDIR;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
if (ntfs_check_empty_dir(ni)<0) {
|
||||||
|
result = ENOTEMPTY;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
} else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
|
||||||
|
result = EISDIR;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: the file must not be deleted here, only unlinked!
|
||||||
|
if (ntfs_delete(ns->ntvol, (char*)NULL, ni, bi, uname, unameLength))
|
||||||
|
result = errno;
|
||||||
|
|
||||||
|
ni = bi = NULL;
|
||||||
|
|
||||||
|
node->parent_vnid = dir->vnid;
|
||||||
|
|
||||||
|
notify_entry_removed(ns->id, dir->vnid, name, vnid);
|
||||||
|
|
||||||
|
remove_vnode(_vol, vnid);
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
exit2:
|
||||||
|
put_vnode(_vol, vnid);
|
||||||
|
exit1:
|
||||||
|
free(uname);
|
||||||
|
|
||||||
|
if (ni)
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
if (bi)
|
||||||
|
ntfs_inode_close(bi);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
fs_ntfs_update_times(fs_volume *vol, ntfs_inode *ni,
|
fs_ntfs_update_times(fs_volume *vol, ntfs_inode *ni,
|
||||||
ntfs_time_update_flags mask)
|
ntfs_time_update_flags mask)
|
||||||
@ -234,6 +405,7 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args,
|
|||||||
.state = NF_FreeClustersOutdate | NF_FreeMFTOutdate,
|
.state = NF_FreeClustersOutdate | NF_FreeMFTOutdate,
|
||||||
.show_sys_files = false,
|
.show_sys_files = false,
|
||||||
.ro = false,
|
.ro = false,
|
||||||
|
.fake_attrib = false,
|
||||||
.flags = 0
|
.flags = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -249,6 +421,8 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args,
|
|||||||
"false"), "false") != 0;
|
"false"), "false") != 0;
|
||||||
ns->noatime = strcasecmp(get_driver_parameter(handle, "no_atime", "true",
|
ns->noatime = strcasecmp(get_driver_parameter(handle, "no_atime", "true",
|
||||||
"true"), "true") == 0;
|
"true"), "true") == 0;
|
||||||
|
ns->fake_attrib = strcasecmp(get_driver_parameter(handle, "fake_attributes",
|
||||||
|
"false", "false"), "false") != 0;
|
||||||
unload_driver_settings(handle);
|
unload_driver_settings(handle);
|
||||||
|
|
||||||
if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0
|
if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0
|
||||||
@ -257,6 +431,21 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args,
|
|||||||
ns->flags |= B_FS_IS_READONLY;
|
ns->flags |= B_FS_IS_READONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ns->fake_attrib) {
|
||||||
|
gNTFSVnodeOps.open_attr_dir = fake_open_attrib_dir;
|
||||||
|
gNTFSVnodeOps.close_attr_dir = fake_close_attrib_dir;
|
||||||
|
gNTFSVnodeOps.free_attr_dir_cookie = fake_free_attrib_dir_cookie;
|
||||||
|
gNTFSVnodeOps.read_attr_dir = fake_read_attrib_dir;
|
||||||
|
gNTFSVnodeOps.rewind_attr_dir = fake_rewind_attrib_dir;
|
||||||
|
gNTFSVnodeOps.create_attr = NULL;
|
||||||
|
gNTFSVnodeOps.open_attr = fake_open_attrib;
|
||||||
|
gNTFSVnodeOps.close_attr = fake_close_attrib;
|
||||||
|
gNTFSVnodeOps.free_attr_cookie = fake_free_attrib_cookie;
|
||||||
|
gNTFSVnodeOps.read_attr = fake_read_attrib;
|
||||||
|
gNTFSVnodeOps.read_attr_stat = fake_read_attrib_stat;
|
||||||
|
gNTFSVnodeOps.write_attr = fake_write_attrib;
|
||||||
|
}
|
||||||
|
|
||||||
ns->ntvol = utils_mount_volume(device, mountFlags | MS_RECOVER);
|
ns->ntvol = utils_mount_volume(device, mountFlags | MS_RECOVER);
|
||||||
if (ns->ntvol != NULL)
|
if (ns->ntvol != NULL)
|
||||||
result = B_NO_ERROR;
|
result = B_NO_ERROR;
|
||||||
@ -531,18 +720,19 @@ fs_read_vnode(fs_volume *_vol, ino_t vnid, fs_vnode *_node, int *_type,
|
|||||||
|
|
||||||
newNode->vnid = vnid;
|
newNode->vnid = vnid;
|
||||||
newNode->parent_vnid = ntfs_mft_get_parent_ref(ni);
|
newNode->parent_vnid = ntfs_mft_get_parent_ref(ni);
|
||||||
|
|
||||||
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
if (ns->fake_attrib) {
|
||||||
set_mime(newNode, ".***");
|
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
||||||
else {
|
set_mime(newNode, ".***");
|
||||||
name = (char*)malloc(MAX_PATH);
|
else {
|
||||||
if (name != NULL) {
|
name = (char*)malloc(MAX_PATH);
|
||||||
if (utils_inode_get_name(ni, name, MAX_PATH) == 1)
|
if (name != NULL) {
|
||||||
set_mime(newNode, name);
|
if (utils_inode_get_name(ni, name, MAX_PATH) == 1)
|
||||||
free(name);
|
set_mime(newNode, name);
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_node->private_node = newNode;
|
_node->private_node = newNode;
|
||||||
} else
|
} else
|
||||||
result = ENOMEM;
|
result = ENOMEM;
|
||||||
@ -964,8 +1154,6 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
|
|||||||
le32 securid = const_cpu_to_le32(0);
|
le32 securid = const_cpu_to_le32(0);
|
||||||
ni = ntfs_create(bi, securid, uname, unameLength, S_IFREG);
|
ni = ntfs_create(bi, securid, uname, unameLength, S_IFREG);
|
||||||
if (ni) {
|
if (ni) {
|
||||||
NInoSetDirty(ni);
|
|
||||||
|
|
||||||
*_vnid = MREF(ni->mft_no);
|
*_vnid = MREF(ni->mft_no);
|
||||||
|
|
||||||
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
||||||
@ -981,15 +1169,20 @@ fs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
|
|||||||
|
|
||||||
newNode->vnid = *_vnid;
|
newNode->vnid = *_vnid;
|
||||||
newNode->parent_vnid = MREF(bi->mft_no);
|
newNode->parent_vnid = MREF(bi->mft_no);
|
||||||
set_mime(newNode, name);
|
|
||||||
|
if (ns->fake_attrib)
|
||||||
|
set_mime(newNode, name);
|
||||||
|
|
||||||
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
|
ntfs_inode_update_mbsname(bi, name, ni->mft_no);
|
||||||
|
NInoSetDirty(ni);
|
||||||
|
|
||||||
result = B_NO_ERROR;
|
result = B_NO_ERROR;
|
||||||
result = publish_vnode(_vol, *_vnid, (void*)newNode, &gNTFSVnodeOps,
|
result = publish_vnode(_vol, *_vnid, (void*)newNode, &gNTFSVnodeOps,
|
||||||
S_IFREG, 0);
|
S_IFREG, 0);
|
||||||
|
|
||||||
ntfs_mark_free_space_outdated(ns);
|
ntfs_mark_free_space_outdated(ns);
|
||||||
fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME);
|
fs_ntfs_update_times(_vol, bi, NTFS_UPDATE_MCTIME);
|
||||||
|
|
||||||
notify_entry_created(ns->id, MREF(bi->mft_no), name, *_vnid);
|
notify_entry_created(ns->id, MREF(bi->mft_no), name, *_vnid);
|
||||||
} else
|
} else
|
||||||
result = errno;
|
result = errno;
|
||||||
@ -1340,7 +1533,7 @@ fs_create_symlink(fs_volume *_vol, fs_vnode *_dir, const char *name,
|
|||||||
int unameLength;
|
int unameLength;
|
||||||
int utargetLength;
|
int utargetLength;
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
int fmode;
|
int fmode = FS_FILE_MODE;
|
||||||
le32 securid = 0;
|
le32 securid = 0;
|
||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
@ -1386,12 +1579,13 @@ fs_create_symlink(fs_volume *_vol, fs_vnode *_dir, const char *name,
|
|||||||
symnode->vnid = MREF(sym->mft_no);
|
symnode->vnid = MREF(sym->mft_no);
|
||||||
symnode->parent_vnid = MREF(bi->mft_no);
|
symnode->parent_vnid = MREF(bi->mft_no);
|
||||||
|
|
||||||
if (sym->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
|
if (ns->fake_attrib) {
|
||||||
set_mime(symnode, ".***");
|
if (sym->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
|
||||||
fmode = FS_DIR_MODE;
|
set_mime(symnode, ".***");
|
||||||
} else {
|
fmode = FS_DIR_MODE;
|
||||||
set_mime(symnode, name);
|
} else {
|
||||||
fmode = FS_FILE_MODE;
|
set_mime(symnode, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = publish_vnode(_vol, MREF(sym->mft_no), symnode, &gNTFSVnodeOps,
|
result = publish_vnode(_vol, MREF(sym->mft_no), symnode, &gNTFSVnodeOps,
|
||||||
@ -1470,8 +1664,6 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
ni = ntfs_create(bi, securid, uname, unameLength, S_IFDIR);
|
ni = ntfs_create(bi, securid, uname, unameLength, S_IFDIR);
|
||||||
if (ni) {
|
if (ni) {
|
||||||
ino_t vnid = MREF(ni->mft_no);
|
ino_t vnid = MREF(ni->mft_no);
|
||||||
|
|
||||||
NInoSetDirty(ni);
|
|
||||||
|
|
||||||
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
newNode = (vnode*)ntfs_calloc(sizeof(vnode));
|
||||||
if (newNode == NULL) {
|
if (newNode == NULL) {
|
||||||
@ -1486,7 +1678,13 @@ fs_mkdir(fs_volume *_vol, fs_vnode *_dir, const char *name, int perms)
|
|||||||
|
|
||||||
newNode->vnid = vnid;
|
newNode->vnid = vnid;
|
||||||
newNode->parent_vnid = MREF(bi->mft_no);
|
newNode->parent_vnid = MREF(bi->mft_no);
|
||||||
set_mime(newNode, ".***");
|
|
||||||
|
if (ns->fake_attrib)
|
||||||
|
set_mime(newNode, ".***");
|
||||||
|
|
||||||
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
|
ntfs_inode_update_mbsname(bi, name, ni->mft_no);
|
||||||
|
NInoSetDirty(ni);
|
||||||
|
|
||||||
result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps,
|
result = publish_vnode(_vol, vnid, (void*)newNode, &gNTFSVnodeOps,
|
||||||
S_IFDIR, 0);
|
S_IFDIR, 0);
|
||||||
@ -1513,30 +1711,24 @@ exit:
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *oldname,
|
fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *name,
|
||||||
fs_vnode *_ndir, const char *newname)
|
fs_vnode *_ndir, const char *newname)
|
||||||
{
|
{
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
nspace *ns = (nspace*)_vol->private_volume;
|
||||||
vnode *odir = (vnode*)_odir->private_node;
|
vnode *odir = (vnode*)_odir->private_node;
|
||||||
vnode *ndir = (vnode*)_ndir->private_node;
|
vnode *ndir = (vnode*)_ndir->private_node;
|
||||||
|
vnode *file = NULL;
|
||||||
|
|
||||||
|
ino_t parent = odir->vnid;
|
||||||
|
ino_t newparent = ndir->vnid;
|
||||||
|
|
||||||
vnode *onode = NULL;
|
ino_t ino, xino;
|
||||||
vnode *nnode = NULL;
|
|
||||||
|
|
||||||
ino_t ovnid, nvnid;
|
ntfs_inode *ni = NULL;
|
||||||
|
ntfs_inode *dir_ni = NULL;
|
||||||
ntfs_inode *oi = NULL;
|
|
||||||
ntfs_inode *ndi = NULL;
|
|
||||||
ntfs_inode *odi = NULL;
|
|
||||||
|
|
||||||
ntfschar *unewname = NULL;
|
|
||||||
ntfschar *uoldname = NULL;
|
|
||||||
int unewnameLength;
|
|
||||||
int uoldnameLength;
|
|
||||||
|
|
||||||
status_t result = B_NO_ERROR;
|
status_t result = B_NO_ERROR;
|
||||||
|
|
||||||
char path[MAX_PATH];
|
|
||||||
|
|
||||||
if (ns->flags & B_FS_IS_READONLY) {
|
if (ns->flags & B_FS_IS_READONLY) {
|
||||||
ERROR("ntfs is read-only\n");
|
ERROR("ntfs is read-only\n");
|
||||||
@ -1545,156 +1737,78 @@ fs_rename(fs_volume *_vol, fs_vnode *_odir, const char *oldname,
|
|||||||
|
|
||||||
LOCK_VOL(ns);
|
LOCK_VOL(ns);
|
||||||
|
|
||||||
TRACE("fs_rename - oldname:%s newname:%s\n", oldname, newname);
|
TRACE("NTFS:fs_rename - oldname:%s newname:%s\n", name, newname);
|
||||||
|
|
||||||
// convert names from utf8 to unicode string
|
ino = ntfs_inode_lookup(_vol, parent, name);
|
||||||
unewnameLength = ntfs_mbstoucs(newname, &unewname);
|
if (ino == (u64)-1) {
|
||||||
if (unewnameLength < 0) {
|
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether target is present */
|
||||||
|
xino = ntfs_inode_lookup(_vol, newparent, newname);
|
||||||
|
|
||||||
|
if (xino == (u64)-1) {
|
||||||
|
ntfschar *uname = NULL;
|
||||||
|
int uname_len;
|
||||||
|
|
||||||
uoldnameLength = ntfs_mbstoucs(oldname, &uoldname);
|
result = get_vnode(_vol, ino, (void**)&file);
|
||||||
if (uoldnameLength < 0) {
|
if (result != B_NO_ERROR)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
|
||||||
|
ni = ntfs_inode_open(ns->ntvol, ino);
|
||||||
|
if (!ni) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
uname_len = ntfs_mbstoucs(newname, &uname);
|
||||||
|
if (uname_len < 0) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir_ni = ntfs_inode_open(ns->ntvol, newparent);
|
||||||
|
if (!dir_ni) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntfs_link(ni, dir_ni, uname, uname_len)) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no);
|
||||||
|
|
||||||
|
ni->flags |= FILE_ATTR_ARCHIVE;
|
||||||
|
|
||||||
|
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_CTIME);
|
||||||
|
fs_ntfs_update_times(_vol, dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
|
|
||||||
|
if (ns->fake_attrib) {
|
||||||
|
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
||||||
|
set_mime(file, ".***");
|
||||||
|
else
|
||||||
|
set_mime(file, newname);
|
||||||
|
}
|
||||||
|
|
||||||
|
ntfs_inode_close(dir_ni);
|
||||||
|
ntfs_inode_close(ni);
|
||||||
|
|
||||||
|
free(uname);
|
||||||
|
|
||||||
|
ntfs_remove(_vol, parent, name);
|
||||||
|
|
||||||
|
file->parent_vnid = newparent;
|
||||||
|
|
||||||
|
put_vnode(_vol, file->vnid);
|
||||||
|
|
||||||
|
notify_entry_moved(ns->id, parent, name, newparent, newname, ino);
|
||||||
|
} else
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// open source directory inode
|
|
||||||
odi = ntfs_inode_open(ns->ntvol, odir->vnid);
|
|
||||||
if (odi == NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ovnid = MREF(ntfs_inode_lookup_by_name(odi, uoldname, uoldnameLength));
|
|
||||||
if (ovnid == (u64) -1) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = get_vnode(_vol, ovnid, (void**)&onode);
|
|
||||||
if (result != B_NO_ERROR)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
|
|
||||||
if (odir != ndir) {
|
|
||||||
// moving
|
|
||||||
ndi = ntfs_inode_open(ns->ntvol, ndir->vnid);
|
|
||||||
if (ndi != NULL) {
|
|
||||||
nvnid = MREF(ntfs_inode_lookup_by_name(ndi, unewname,
|
|
||||||
unewnameLength));
|
|
||||||
if (nvnid != (u64) -1)
|
|
||||||
get_vnode(_vol, nvnid, (void**)&nnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nnode != NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
put_vnode(_vol, nnode->vnid);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntfs_link(oi, ndi, unewname, unewnameLength)) {
|
|
||||||
ntfs_inode_close(oi);
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oi->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
|
||||||
set_mime(onode, ".***");
|
|
||||||
else
|
|
||||||
set_mime(onode, newname);
|
|
||||||
|
|
||||||
ntfs_inode_close(oi);
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
onode->parent_vnid = MREF(ndi->mft_no);
|
|
||||||
|
|
||||||
notify_entry_moved(ns->id, MREF(odi->mft_no), oldname, MREF(ndi->mft_no),
|
|
||||||
newname, onode->vnid);
|
|
||||||
|
|
||||||
if (utils_inode_get_name(oi, path, MAX_PATH) == 0) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ntfs_delete(ns->ntvol, path, oi, odi, uoldname, uoldnameLength);
|
|
||||||
oi = odi = NULL;
|
|
||||||
/* ntfs_delete() always closes ni and dir_ni */
|
|
||||||
|
|
||||||
put_vnode(_vol, onode->vnid);
|
|
||||||
} else {
|
|
||||||
// renaming
|
|
||||||
|
|
||||||
nvnid = MREF(ntfs_inode_lookup_by_name(odi, unewname, unewnameLength));
|
|
||||||
if (nvnid != (u64)-1)
|
|
||||||
get_vnode(_vol, nvnid, (void**)&nnode);
|
|
||||||
|
|
||||||
if (nnode != NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
put_vnode(_vol, nnode->vnid);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntfs_link(oi, odi, unewname, unewnameLength)) {
|
|
||||||
ntfs_inode_close(oi);
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oi->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
|
||||||
set_mime(onode, ".***");
|
|
||||||
else
|
|
||||||
set_mime(onode, newname);
|
|
||||||
|
|
||||||
ntfs_inode_close(oi);
|
|
||||||
|
|
||||||
oi = ntfs_inode_open(ns->ntvol, onode->vnid);
|
|
||||||
if (oi == NULL) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
notify_entry_moved(ns->id, MREF(odi->mft_no), oldname,
|
|
||||||
MREF(odi->mft_no), newname, onode->vnid);
|
|
||||||
put_vnode(_vol, onode->vnid);
|
|
||||||
|
|
||||||
if (utils_inode_get_name(oi, path, MAX_PATH) == 0) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ntfs_delete(ns->ntvol, path, oi, odi, uoldname, uoldnameLength);
|
|
||||||
oi = odi = NULL;
|
|
||||||
/* ntfs_delete() always closes ni and dir_ni */
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
free(unewname);
|
|
||||||
free(uoldname);
|
|
||||||
|
|
||||||
if (odi)
|
|
||||||
ntfs_inode_close(odi);
|
|
||||||
if (ndi)
|
|
||||||
ntfs_inode_close(ndi);
|
|
||||||
|
|
||||||
TRACE("fs_rename - EXIT, result is %s\n", strerror(result));
|
TRACE("fs_rename - EXIT, result is %s\n", strerror(result));
|
||||||
|
|
||||||
UNLOCK_VOL(ns);
|
UNLOCK_VOL(ns);
|
||||||
@ -1703,97 +1817,6 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
do_unlink(fs_volume *_vol, vnode *dir, const char *name, bool isdir)
|
|
||||||
{
|
|
||||||
nspace *ns = (nspace*)_vol->private_volume;
|
|
||||||
ino_t vnid;
|
|
||||||
vnode *node = NULL;
|
|
||||||
ntfs_inode *ni = NULL;
|
|
||||||
ntfs_inode *bi = NULL;
|
|
||||||
ntfschar *uname = NULL;
|
|
||||||
int unameLength;
|
|
||||||
char path[MAX_PATH];
|
|
||||||
|
|
||||||
status_t result = B_NO_ERROR;
|
|
||||||
|
|
||||||
unameLength = ntfs_mbstoucs(name, &uname);
|
|
||||||
if (unameLength < 0) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bi = ntfs_inode_open(ns->ntvol, dir->vnid);
|
|
||||||
if (bi == NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnid = MREF(ntfs_inode_lookup_by_name(bi, uname, unameLength));
|
|
||||||
|
|
||||||
if ( vnid == (u64)-1 || vnid == FILE_root) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = get_vnode(_vol, vnid, (void**)&node);
|
|
||||||
|
|
||||||
if (result != B_NO_ERROR || node==NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ni = ntfs_inode_open(ns->ntvol, node->vnid);
|
|
||||||
if (ni == NULL) {
|
|
||||||
result = ENOENT;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdir) {
|
|
||||||
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
|
|
||||||
result = ENOTDIR;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
if (ntfs_check_empty_dir(ni)<0) {
|
|
||||||
result = ENOTEMPTY;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
} else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
|
|
||||||
result = EISDIR;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utils_inode_get_name(ni, path, MAX_PATH) == 0) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto exit2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: the file must not be deleted here, only unlinked!
|
|
||||||
if (ntfs_delete(ns->ntvol, path, ni, bi, uname, unameLength))
|
|
||||||
result = errno;
|
|
||||||
|
|
||||||
ni = bi = NULL;
|
|
||||||
|
|
||||||
node->parent_vnid = dir->vnid;
|
|
||||||
|
|
||||||
notify_entry_removed(ns->id, dir->vnid, name, vnid);
|
|
||||||
|
|
||||||
result = remove_vnode(_vol, vnid);
|
|
||||||
|
|
||||||
exit2:
|
|
||||||
put_vnode(_vol, vnid);
|
|
||||||
exit1:
|
|
||||||
free(uname);
|
|
||||||
|
|
||||||
if (ni)
|
|
||||||
ntfs_inode_close(ni);
|
|
||||||
if (bi)
|
|
||||||
ntfs_inode_close(bi);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
fs_rmdir(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
fs_rmdir(fs_volume *_vol, fs_vnode *_dir, const char *name)
|
||||||
{
|
{
|
||||||
@ -1872,4 +1895,3 @@ exit:
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ typedef struct nspace {
|
|||||||
long free_mft;
|
long free_mft;
|
||||||
BOOL ro;
|
BOOL ro;
|
||||||
BOOL show_sys_files;
|
BOOL show_sys_files;
|
||||||
|
BOOL fake_attrib;
|
||||||
BOOL silent;
|
BOOL silent;
|
||||||
BOOL force;
|
BOOL force;
|
||||||
BOOL debug;
|
BOOL debug;
|
||||||
|
@ -6,3 +6,4 @@
|
|||||||
hide_sys_files true
|
hide_sys_files true
|
||||||
read_only false
|
read_only false
|
||||||
no_atime true
|
no_atime true
|
||||||
|
fake_attributes true
|
||||||
|
@ -183,7 +183,7 @@ void
|
|||||||
Icb::GetAccessTime(struct timespec ×pec) const
|
Icb::GetAccessTime(struct timespec ×pec) const
|
||||||
{
|
{
|
||||||
timestamp ts;
|
timestamp ts;
|
||||||
if ((_Tag().id() == TAGID_EXTENDED_FILE_ENTRY))
|
if (_Tag().id() == TAGID_EXTENDED_FILE_ENTRY)
|
||||||
ts = _ExtendedEntry()->access_date_and_time();
|
ts = _ExtendedEntry()->access_date_and_time();
|
||||||
else
|
else
|
||||||
ts = _FileEntry()->access_date_and_time();
|
ts = _FileEntry()->access_date_and_time();
|
||||||
@ -200,7 +200,7 @@ void
|
|||||||
Icb::GetModificationTime(struct timespec ×pec) const
|
Icb::GetModificationTime(struct timespec ×pec) const
|
||||||
{
|
{
|
||||||
timestamp ts;
|
timestamp ts;
|
||||||
if ((_Tag().id() == TAGID_EXTENDED_FILE_ENTRY))
|
if (_Tag().id() == TAGID_EXTENDED_FILE_ENTRY)
|
||||||
ts = _ExtendedEntry()->modification_date_and_time();
|
ts = _ExtendedEntry()->modification_date_and_time();
|
||||||
else
|
else
|
||||||
ts = _FileEntry()->modification_date_and_time();
|
ts = _FileEntry()->modification_date_and_time();
|
||||||
@ -214,7 +214,7 @@ Icb::GetModificationTime(struct timespec ×pec) const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Icb::FindBlock(uint32 logicalBlock, off_t &block)
|
Icb::FindBlock(uint32 logicalBlock, off_t &block, bool &recorded)
|
||||||
{
|
{
|
||||||
off_t pos = logicalBlock << fVolume->BlockShift();
|
off_t pos = logicalBlock << fVolume->BlockShift();
|
||||||
if (uint64(pos) >= Length()) {
|
if (uint64(pos) >= Length()) {
|
||||||
@ -227,9 +227,11 @@ Icb::FindBlock(uint32 logicalBlock, off_t &block)
|
|||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
long_address extent;
|
long_address extent;
|
||||||
bool isEmpty = false;
|
bool isEmpty = false;
|
||||||
|
recorded = false;
|
||||||
|
|
||||||
switch (_IcbTag().descriptor_flags()) {
|
switch (_IcbTag().descriptor_flags()) {
|
||||||
case ICB_DESCRIPTOR_TYPE_SHORT: {
|
case ICB_DESCRIPTOR_TYPE_SHORT:
|
||||||
|
{
|
||||||
TRACE(("Icb::FindBlock: descriptor type -> short\n"));
|
TRACE(("Icb::FindBlock: descriptor type -> short\n"));
|
||||||
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
||||||
ShortDescriptorAccessor(fPartition));
|
ShortDescriptorAccessor(fPartition));
|
||||||
@ -241,7 +243,8 @@ Icb::FindBlock(uint32 logicalBlock, off_t &block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ICB_DESCRIPTOR_TYPE_LONG: {
|
case ICB_DESCRIPTOR_TYPE_LONG:
|
||||||
|
{
|
||||||
TRACE(("Icb::FindBlock: descriptor type -> long\n"));
|
TRACE(("Icb::FindBlock: descriptor type -> long\n"));
|
||||||
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
||||||
status = list.FindExtent(pos, &extent, &isEmpty);
|
status = list.FindExtent(pos, &extent, &isEmpty);
|
||||||
@ -252,7 +255,8 @@ Icb::FindBlock(uint32 logicalBlock, off_t &block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ICB_DESCRIPTOR_TYPE_EXTENDED: {
|
case ICB_DESCRIPTOR_TYPE_EXTENDED:
|
||||||
|
{
|
||||||
TRACE(("Icb::FindBlock: descriptor type -> extended\n"));
|
TRACE(("Icb::FindBlock: descriptor type -> extended\n"));
|
||||||
// AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0));
|
// AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0));
|
||||||
// RETURN(_Read(list, pos, buffer, length, block));
|
// RETURN(_Read(list, pos, buffer, length, block));
|
||||||
@ -260,7 +264,8 @@ Icb::FindBlock(uint32 logicalBlock, off_t &block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ICB_DESCRIPTOR_TYPE_EMBEDDED: {
|
case ICB_DESCRIPTOR_TYPE_EMBEDDED:
|
||||||
|
{
|
||||||
TRACE(("Icb::FindBlock: descriptor type: embedded\n"));
|
TRACE(("Icb::FindBlock: descriptor type: embedded\n"));
|
||||||
RETURN(B_ERROR);
|
RETURN(B_ERROR);
|
||||||
break;
|
break;
|
||||||
@ -275,6 +280,7 @@ Icb::FindBlock(uint32 logicalBlock, off_t &block)
|
|||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
block = extent.block();
|
block = extent.block();
|
||||||
|
recorded = extent.type() == EXTENT_TYPE_RECORDED;
|
||||||
TRACE(("Icb::FindBlock: block %lld\n", block));
|
TRACE(("Icb::FindBlock: block %lld\n", block));
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
@ -301,7 +307,8 @@ Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
|
|||||||
return file_cache_read(fFileCache, NULL, pos, buffer, length);
|
return file_cache_read(fFileCache, NULL, pos, buffer, length);
|
||||||
|
|
||||||
switch (_IcbTag().descriptor_flags()) {
|
switch (_IcbTag().descriptor_flags()) {
|
||||||
case ICB_DESCRIPTOR_TYPE_SHORT: {
|
case ICB_DESCRIPTOR_TYPE_SHORT:
|
||||||
|
{
|
||||||
TRACE(("Icb::Read: descriptor type -> short\n"));
|
TRACE(("Icb::Read: descriptor type -> short\n"));
|
||||||
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
||||||
ShortDescriptorAccessor(fPartition));
|
ShortDescriptorAccessor(fPartition));
|
||||||
@ -309,14 +316,16 @@ Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ICB_DESCRIPTOR_TYPE_LONG: {
|
case ICB_DESCRIPTOR_TYPE_LONG:
|
||||||
|
{
|
||||||
TRACE(("Icb::Read: descriptor type -> long\n"));
|
TRACE(("Icb::Read: descriptor type -> long\n"));
|
||||||
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
||||||
RETURN(_Read(list, pos, buffer, length, block));
|
RETURN(_Read(list, pos, buffer, length, block));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ICB_DESCRIPTOR_TYPE_EXTENDED: {
|
case ICB_DESCRIPTOR_TYPE_EXTENDED:
|
||||||
|
{
|
||||||
TRACE(("Icb::Read: descriptor type -> extended\n"));
|
TRACE(("Icb::Read: descriptor type -> extended\n"));
|
||||||
// AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0));
|
// AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0));
|
||||||
// RETURN(_Read(list, pos, buffer, length, block));
|
// RETURN(_Read(list, pos, buffer, length, block));
|
||||||
@ -324,7 +333,8 @@ Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ICB_DESCRIPTOR_TYPE_EMBEDDED: {
|
case ICB_DESCRIPTOR_TYPE_EMBEDDED:
|
||||||
|
{
|
||||||
TRACE(("Icb::Read: descriptor type: embedded\n"));
|
TRACE(("Icb::Read: descriptor type: embedded\n"));
|
||||||
RETURN(B_ERROR);
|
RETURN(B_ERROR);
|
||||||
break;
|
break;
|
||||||
|
@ -105,7 +105,8 @@ public:
|
|||||||
uint32 AllocationDescriptorsSize()
|
uint32 AllocationDescriptorsSize()
|
||||||
{ return _AbstractEntry()->AllocationDescriptorsLength(); }
|
{ return _AbstractEntry()->AllocationDescriptorsLength(); }
|
||||||
|
|
||||||
status_t FindBlock(uint32 logicalBlock, off_t &block);
|
status_t FindBlock(uint32 logicalBlock, off_t &block,
|
||||||
|
bool &recorded);
|
||||||
status_t Read(off_t pos, void *buffer, size_t *length,
|
status_t Read(off_t pos, void *buffer, size_t *length,
|
||||||
uint32 *block = NULL);
|
uint32 *block = NULL);
|
||||||
|
|
||||||
|
@ -31,8 +31,16 @@ MetadataPartition::MetadataPartition(Volume *volume,
|
|||||||
fMetadataIcb = new(nothrow) Icb(volume, address);
|
fMetadataIcb = new(nothrow) Icb(volume, address);
|
||||||
if (fMetadataIcb == NULL || fMetadataIcb->InitCheck() != B_OK)
|
if (fMetadataIcb == NULL || fMetadataIcb->InitCheck() != B_OK)
|
||||||
fInitStatus = B_NO_MEMORY;
|
fInitStatus = B_NO_MEMORY;
|
||||||
|
else
|
||||||
|
fInitStatus = B_OK;
|
||||||
|
|
||||||
fInitStatus = B_OK;
|
address.set_to(metadataMirrorFileLocation, fPartition);
|
||||||
|
|
||||||
|
fMetadataMirrorIcb = new(nothrow) Icb(volume, address);
|
||||||
|
if (fMetadataMirrorIcb == NULL
|
||||||
|
|| fMetadataMirrorIcb->InitCheck() != B_OK) {
|
||||||
|
fInitStatus = B_NO_MEMORY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Destroys the MetadataPartition object.
|
/*! \brief Destroys the MetadataPartition object.
|
||||||
@ -48,9 +56,17 @@ status_t
|
|||||||
MetadataPartition::MapBlock(uint32 logicalBlock, off_t &physicalBlock)
|
MetadataPartition::MapBlock(uint32 logicalBlock, off_t &physicalBlock)
|
||||||
{
|
{
|
||||||
off_t block = 0;
|
off_t block = 0;
|
||||||
status_t status = fMetadataIcb->FindBlock(logicalBlock, block);
|
bool isRecorded;
|
||||||
|
status_t status = fMetadataIcb->FindBlock(logicalBlock, block, isRecorded);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
if (!isRecorded) {
|
||||||
|
status = fMetadataMirrorIcb->FindBlock(logicalBlock, block, isRecorded);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
if (!isRecorded)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
return fParentPartition.MapBlock(block, physicalBlock);
|
return fParentPartition.MapBlock(block, physicalBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ private:
|
|||||||
bool fMetadataIsDuplicated;
|
bool fMetadataIsDuplicated;
|
||||||
status_t fInitStatus;
|
status_t fInitStatus;
|
||||||
Icb *fMetadataIcb;
|
Icb *fMetadataIcb;
|
||||||
|
Icb *fMetadataMirrorIcb;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _UDF_METADATA_PARTITION_H
|
#endif // _UDF_METADATA_PARTITION_H
|
||||||
|
@ -613,8 +613,10 @@ void
|
|||||||
Area::_UpdateMaxSizeConstraint(BSize max)
|
Area::_UpdateMaxSizeConstraint(BSize max)
|
||||||
{
|
{
|
||||||
if (!fLayoutItem->IsVisible()) {
|
if (!fLayoutItem->IsVisible()) {
|
||||||
fMaxContentHeight->SetRightSide(B_SIZE_UNLIMITED);
|
if (fMaxContentHeight != NULL)
|
||||||
fMaxContentWidth->SetRightSide(B_SIZE_UNLIMITED);
|
fMaxContentHeight->SetRightSide(B_SIZE_UNLIMITED);
|
||||||
|
if (fMaxContentWidth != NULL)
|
||||||
|
fMaxContentWidth->SetRightSide(B_SIZE_UNLIMITED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +622,8 @@ KeyboardLayoutView::_DrawKey(BView* view, BRect updateRect, const Key* key,
|
|||||||
+ (key->frame.Width() - key->second_row) * fFactor - fGap - 2);
|
+ (key->frame.Width() - key->second_row) * fFactor - fGap - 2);
|
||||||
|
|
||||||
topLeft.bottom = bottomLeft.top;
|
topLeft.bottom = bottomLeft.top;
|
||||||
topLeft.right = bottomLeft.right;
|
topLeft.right = bottomLeft.right + 1;
|
||||||
|
// add one to make the borders meet
|
||||||
|
|
||||||
topRight.bottom = topLeft.bottom;
|
topRight.bottom = topLeft.bottom;
|
||||||
topRight.left = topLeft.right;
|
topRight.left = topLeft.right;
|
||||||
@ -630,28 +631,52 @@ KeyboardLayoutView::_DrawKey(BView* view, BRect updateRect, const Key* key,
|
|||||||
bottomRight.top = bottomLeft.top;
|
bottomRight.top = bottomLeft.top;
|
||||||
bottomRight.left = bottomLeft.right;
|
bottomRight.left = bottomLeft.right;
|
||||||
|
|
||||||
|
// draw top left corner
|
||||||
be_control_look->DrawButtonFrame(view, topLeft, updateRect,
|
be_control_look->DrawButtonFrame(view, topLeft, updateRect,
|
||||||
4.0f, 0.0f, 0.0f, 0.0f, base, background,
|
4.0f, 0.0f, 4.0f, 0.0f, base, background,
|
||||||
pressed ? BControlLook::B_ACTIVATED : 0,
|
pressed ? BControlLook::B_ACTIVATED : 0,
|
||||||
BControlLook::B_LEFT_BORDER | BControlLook::B_TOP_BORDER
|
BControlLook::B_LEFT_BORDER | BControlLook::B_TOP_BORDER
|
||||||
| BControlLook::B_BOTTOM_BORDER);
|
| BControlLook::B_BOTTOM_BORDER);
|
||||||
|
be_control_look->DrawButtonBackground(view, topLeft, updateRect,
|
||||||
|
4.0f, 0.0f, 4.0f, 0.0f, base,
|
||||||
|
pressed ? BControlLook::B_ACTIVATED : 0,
|
||||||
|
BControlLook::B_LEFT_BORDER | BControlLook::B_TOP_BORDER
|
||||||
|
| BControlLook::B_BOTTOM_BORDER);
|
||||||
|
|
||||||
|
// draw top right corner
|
||||||
be_control_look->DrawButtonFrame(view, topRight, updateRect,
|
be_control_look->DrawButtonFrame(view, topRight, updateRect,
|
||||||
0.0f, 4.0f, 0.0f, 0.0f, base, background,
|
0.0f, 4.0f, 0.0f, 0.0f, base, background,
|
||||||
pressed ? BControlLook::B_ACTIVATED : 0,
|
pressed ? BControlLook::B_ACTIVATED : 0,
|
||||||
BControlLook::B_TOP_BORDER | BControlLook::B_RIGHT_BORDER);
|
BControlLook::B_TOP_BORDER | BControlLook::B_RIGHT_BORDER);
|
||||||
|
be_control_look->DrawButtonBackground(view, topRight, updateRect,
|
||||||
|
0.0f, 4.0f, 0.0f, 0.0f, base,
|
||||||
|
pressed ? BControlLook::B_ACTIVATED : 0,
|
||||||
|
BControlLook::B_TOP_BORDER | BControlLook::B_RIGHT_BORDER);
|
||||||
|
|
||||||
|
// draw bottom right corner
|
||||||
be_control_look->DrawButtonFrame(view, bottomRight, updateRect,
|
be_control_look->DrawButtonFrame(view, bottomRight, updateRect,
|
||||||
0.0f, 0.0f, 0.0f, 4.0f, base, background,
|
0.0f, 0.0f, 4.0f, 4.0f, base, background,
|
||||||
|
pressed ? BControlLook::B_ACTIVATED : 0,
|
||||||
|
BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER
|
||||||
|
| BControlLook::B_BOTTOM_BORDER);
|
||||||
|
be_control_look->DrawButtonBackground(view, bottomRight, updateRect,
|
||||||
|
0.0f, 0.0f, 4.0f, 4.0f, base,
|
||||||
pressed ? BControlLook::B_ACTIVATED : 0,
|
pressed ? BControlLook::B_ACTIVATED : 0,
|
||||||
BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER
|
BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER
|
||||||
| BControlLook::B_BOTTOM_BORDER);
|
| BControlLook::B_BOTTOM_BORDER);
|
||||||
|
|
||||||
// Clip out the bottom left corner
|
// clip out the bottom left corner
|
||||||
bottomLeft.right += 1;
|
bottomLeft.right += 1;
|
||||||
bottomLeft.top -= 2;
|
bottomLeft.top -= 2;
|
||||||
BRegion region(rect);
|
BRegion region(rect);
|
||||||
region.Exclude(bottomLeft);
|
region.Exclude(bottomLeft);
|
||||||
view->ConstrainClippingRegion(®ion);
|
view->ConstrainClippingRegion(®ion);
|
||||||
|
|
||||||
|
// Fill in the rect with the background color
|
||||||
|
SetHighColor(background);
|
||||||
|
FillRect(rect);
|
||||||
|
|
||||||
|
// draw the button background
|
||||||
BRect bgRect = rect.InsetByCopy(2, 2);
|
BRect bgRect = rect.InsetByCopy(2, 2);
|
||||||
be_control_look->DrawButtonBackground(view, bgRect, updateRect,
|
be_control_look->DrawButtonBackground(view, bgRect, updateRect,
|
||||||
4.0f, 4.0f, 0.0f, 4.0f, base,
|
4.0f, 4.0f, 0.0f, 4.0f, base,
|
||||||
@ -660,9 +685,11 @@ KeyboardLayoutView::_DrawKey(BView* view, BRect updateRect, const Key* key,
|
|||||||
rect.left = bottomLeft.right;
|
rect.left = bottomLeft.right;
|
||||||
_GetAbbreviatedKeyLabelIfNeeded(view, rect, key, text, sizeof(text));
|
_GetAbbreviatedKeyLabelIfNeeded(view, rect, key, text, sizeof(text));
|
||||||
|
|
||||||
|
// draw the button label
|
||||||
be_control_look->DrawLabel(view, text, rect, updateRect,
|
be_control_look->DrawLabel(view, text, rect, updateRect,
|
||||||
base, 0, BAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE));
|
base, 0, BAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE));
|
||||||
|
|
||||||
|
// reset the clipping region
|
||||||
view->ConstrainClippingRegion(NULL);
|
view->ConstrainClippingRegion(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user