Merge branch 'master' of github.com:FreeRDP/xrdp
This commit is contained in:
commit
8715433732
@ -242,8 +242,19 @@ l_file_read_section(int fd, int max_file_size, const char *section,
|
||||
|
||||
for (index = 0; index < len; index++)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
in_uint8(s, c);
|
||||
|
||||
if ((c == '#') || (c == ';'))
|
||||
{
|
||||
file_read_line(s, text);
|
||||
in_it = 0;
|
||||
in_it_index = 0;
|
||||
g_memset(text, 0, 512);
|
||||
continue;
|
||||
}
|
||||
if (c == '[')
|
||||
{
|
||||
in_it = 1;
|
||||
@ -253,7 +264,6 @@ l_file_read_section(int fd, int max_file_size, const char *section,
|
||||
if (g_strcasecmp(section, text) == 0)
|
||||
{
|
||||
file_read_line(s, text);
|
||||
|
||||
while (file_read_line(s, text) == 0)
|
||||
{
|
||||
if (g_strlen(text) > 0)
|
||||
@ -296,7 +306,6 @@ l_file_read_section(int fd, int max_file_size, const char *section,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
@ -18,24 +18,20 @@
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* o need to support sym links
|
||||
* o when creating dir/file, ensure it does not already exist
|
||||
* o enable changing metadata for files/folders (time, owner, mode etc)
|
||||
* o do not allow dirs to be created in ino==1 except for .clipbard and share mounts
|
||||
* o xrdp_fs needs to grow dynamically - currently it is fixed at 1k or 4k
|
||||
* o fix the HACK where I have to use my own buf instead of g_buffer
|
||||
* this is in func xfuse_check_wait_objs()
|
||||
* o if fuse mount point is already mounted, I get segfault
|
||||
* o in open, check for modes such as O_TRUNC, O_APPEND
|
||||
* o copying over an existing file does not work
|
||||
* o need to keep track of open files, reqd during rename
|
||||
* o need to use dir notification for changed files and update xrdp fs
|
||||
* o copying over an existing file does not work
|
||||
* o after a dir is created, the device cannot be unmounted on the client side
|
||||
* so something is holding it up
|
||||
* o in thunar, when I move a file by dragging to another folder, the file
|
||||
* is getting copied instead of being moved
|
||||
* o unable to edit files in vi
|
||||
* o fuse ops to support
|
||||
* o touch does not work
|
||||
* o keep track of lookup_count
|
||||
* o chmod must work
|
||||
* o cat >> file is not working
|
||||
*
|
||||
@ -45,6 +41,7 @@
|
||||
|
||||
/* FUSE mount point */
|
||||
char g_fuse_root_path[256] = "";
|
||||
char g_fuse_clipboard_path[256] = ""; /* for clipboard use */
|
||||
|
||||
#ifndef XRDP_FUSE
|
||||
|
||||
@ -104,6 +101,7 @@ void xfuse_devredir_cb_file_close(void *vp) {}
|
||||
#include "arch.h"
|
||||
#include "os_calls.h"
|
||||
#include "chansrv_fuse.h"
|
||||
#include "list.h"
|
||||
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
@ -201,8 +199,17 @@ struct xfuse_handle
|
||||
};
|
||||
typedef struct xfuse_handle XFUSE_HANDLE;
|
||||
|
||||
/* globals */
|
||||
/* used for file data request sent to client */
|
||||
struct req_list_item
|
||||
{
|
||||
fuse_req_t req;
|
||||
int stream_id;
|
||||
int lindex;
|
||||
int off;
|
||||
int size;
|
||||
};
|
||||
|
||||
static struct list *g_req_list = 0;
|
||||
static struct xrdp_fs g_xrdp_fs; /* an inst of xrdp file system */
|
||||
static char *g_mount_point = 0; /* our FUSE mount point */
|
||||
static struct fuse_lowlevel_ops g_xfuse_ops; /* setup FUSE callbacks */
|
||||
@ -257,6 +264,8 @@ int dev_redir_file_read(void *fusep, tui32 device_id, tui32 FileId,
|
||||
int dev_redir_file_write(void *fusep, tui32 device_id, tui32 FileId,
|
||||
const char *buf, tui32 Length, tui64 Offset);
|
||||
|
||||
int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId);
|
||||
|
||||
/* forward declarations for FUSE callbacks */
|
||||
static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent,
|
||||
const char *name);
|
||||
@ -311,36 +320,9 @@ static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent,
|
||||
const char *name, mode_t mode,
|
||||
struct fuse_file_info *fi);
|
||||
|
||||
// LK_TODO may not need to be implemented
|
||||
#if 0
|
||||
static void xfuse_cb_statfs(fuse_req_t req, fuse_ino_t ino);
|
||||
|
||||
static void xfuse_cb_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
const char *value, size_t size, int flags);
|
||||
|
||||
static void xfuse_cb_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
size_t size);
|
||||
|
||||
static void xfuse_cb_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size);
|
||||
|
||||
static void xfuse_cb_access(fuse_req_t req, fuse_ino_t ino, int mask);
|
||||
|
||||
static void xfuse_cb_getlk(fuse_req_t req, fuse_ino_t ino,
|
||||
struct fuse_file_info *fi, struct flock *lock);
|
||||
|
||||
static void xfuse_cb_setlk(fuse_req_t req, fuse_ino_t ino,
|
||||
struct fuse_file_info *fi, struct flock *lock,
|
||||
int sleep);
|
||||
|
||||
static void xfuse_cb_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags,
|
||||
const void *in_buf, size_t in_bufsz,
|
||||
size_t out_bufsz);
|
||||
|
||||
static void xfuse_cb_poll(fuse_req_t req, fuse_ino_t ino,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_pollhandle *ph);
|
||||
#endif
|
||||
/* clipboard calls */
|
||||
int clipboard_request_file_data(int stream_id, int lindex, int offset,
|
||||
int request_bytes);
|
||||
|
||||
static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
int to_set, struct fuse_file_info *fi);
|
||||
@ -360,7 +342,6 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
int xfuse_init()
|
||||
{
|
||||
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
|
||||
char opt[1024];
|
||||
|
||||
/* if already inited, just return */
|
||||
if (g_xfuse_inited)
|
||||
@ -377,6 +358,7 @@ int xfuse_init()
|
||||
|
||||
/* define FUSE mount point to ~/xrdp_client */
|
||||
g_snprintf(g_fuse_root_path, 255, "%s/xrdp_client", g_getenv("HOME"));
|
||||
g_snprintf(g_fuse_clipboard_path, 255, "%s/.clipboard", g_fuse_root_path);
|
||||
|
||||
/* if FUSE mount point does not exist, create it */
|
||||
if (!g_directory_exist(g_fuse_root_path))
|
||||
@ -409,28 +391,8 @@ int xfuse_init()
|
||||
g_xfuse_ops.getattr = xfuse_cb_getattr;
|
||||
g_xfuse_ops.setattr = xfuse_cb_setattr;
|
||||
|
||||
#if 0
|
||||
g_xfuse_ops.statfs = xfuse_cb_statfs;
|
||||
g_xfuse_ops.listxattr = xfuse_cb_listxattr;
|
||||
g_xfuse_ops.getlk = xfuse_cb_getlk;
|
||||
g_xfuse_ops.setlk = xfuse_cb_setlk;
|
||||
g_xfuse_ops.ioctl = xfuse_cb_ioctl;
|
||||
g_xfuse_ops.poll = xfuse_cb_poll;
|
||||
g_xfuse_ops.access = xfuse_cb_access;
|
||||
g_xfuse_ops.setxattr = xfuse_cb_setxattr;
|
||||
g_xfuse_ops.getxattr = xfuse_cb_getxattr;
|
||||
#endif
|
||||
|
||||
fuse_opt_add_arg(&args, "xrdp-chansrv");
|
||||
fuse_opt_add_arg(&args, g_fuse_root_path);
|
||||
#if 0
|
||||
sprintf(opt, "-o uid=%d,gid=%d", g_getuid(), g_getgid());
|
||||
fuse_opt_add_arg(&args, opt);
|
||||
#else
|
||||
/* disable multi threading */
|
||||
sprintf(opt, "-s");
|
||||
fuse_opt_add_arg(&args, opt);
|
||||
#endif
|
||||
|
||||
if (xfuse_init_lib(&args))
|
||||
{
|
||||
@ -471,6 +433,12 @@ int xfuse_deinit()
|
||||
g_buffer = 0;
|
||||
}
|
||||
|
||||
if (g_req_list != 0)
|
||||
{
|
||||
list_delete(g_req_list);
|
||||
g_req_list = 0;
|
||||
}
|
||||
|
||||
g_xfuse_inited = 0;
|
||||
return 0;
|
||||
}
|
||||
@ -553,11 +521,11 @@ int xfuse_get_wait_objs(tbus *objs, int *count, int *timeout)
|
||||
|
||||
int xfuse_create_share(tui32 device_id, char *dirname)
|
||||
{
|
||||
/* LK_TODO need to specify parent dir, mode */
|
||||
|
||||
#if 0
|
||||
XFUSE_INFO *fip;
|
||||
#endif
|
||||
XRDP_INODE *xinode;
|
||||
tui32 saved_inode;
|
||||
/* tui32 saved_inode; */
|
||||
|
||||
if (dirname == NULL || strlen(dirname) == 0)
|
||||
return -1;
|
||||
@ -583,7 +551,7 @@ int xfuse_create_share(tui32 device_id, char *dirname)
|
||||
xinode->device_id = device_id;
|
||||
|
||||
g_xrdp_fs.num_entries++;
|
||||
saved_inode = xinode->inode;
|
||||
/* saved_inode = xinode->inode; */
|
||||
|
||||
/* insert it in xrdp fs */
|
||||
g_xrdp_fs.inode_table[xinode->inode] = xinode;
|
||||
@ -605,7 +573,7 @@ int xfuse_create_share(tui32 device_id, char *dirname)
|
||||
|
||||
/* enumerate root dir, do not call FUSE when done */
|
||||
fip->req = NULL;
|
||||
fip->inode = 1; // LK_TODO saved_inode;
|
||||
fip->inode = 1; /* TODO saved_inode; */
|
||||
strncpy(fip->name, dirname, 1024);
|
||||
fip->name[1023] = 0;
|
||||
fip->device_id = device_id;
|
||||
@ -617,36 +585,107 @@ int xfuse_create_share(tui32 device_id, char *dirname)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all clipboard entries in xrdp_fs
|
||||
*
|
||||
* This function is called by clipboard code
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
*****************************************************************************/
|
||||
|
||||
int xfuse_clear_clip_dir(void)
|
||||
{
|
||||
return 0; // CLIPBOARD_TODO
|
||||
int i;
|
||||
XRDP_INODE *xinode;
|
||||
XRDP_INODE *xip;
|
||||
|
||||
log_debug("entered");
|
||||
|
||||
/* xinode for .clipboard */
|
||||
xip = g_xrdp_fs.inode_table[2];
|
||||
|
||||
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
|
||||
{
|
||||
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
|
||||
continue;
|
||||
|
||||
if (xinode->parent_inode == 2)
|
||||
{
|
||||
g_xrdp_fs.inode_table[i] = NULL;
|
||||
free(xinode);
|
||||
xip->nentries--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Return clipboard data to fuse
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
*****************************************************************************/
|
||||
|
||||
int xfuse_file_contents_range(int stream_id, char *data, int data_bytes)
|
||||
{
|
||||
return 0; // CLIPBOARD_TODO
|
||||
log_debug("entered: stream_id=%d data_bytes=%d", stream_id, data_bytes);
|
||||
|
||||
struct req_list_item *rli;
|
||||
|
||||
if ((rli = (struct req_list_item *) list_get_item(g_req_list, 0)) == NULL)
|
||||
{
|
||||
log_error("range error!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_debug("lindex=%d off=%d size=%d", rli->lindex, rli->off, rli->size);
|
||||
|
||||
fuse_reply_buf(rli->req, data, data_bytes);
|
||||
|
||||
list_remove_item(g_req_list, 0);
|
||||
if (g_req_list->count <= 0)
|
||||
{
|
||||
log_debug("completed all requests");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send next request */
|
||||
rli = (struct req_list_item *) list_get_item(g_req_list, 0);
|
||||
if (rli == NULL)
|
||||
{
|
||||
log_error("range error!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_debug("requesting clipboard file data");
|
||||
|
||||
clipboard_request_file_data(rli->stream_id, rli->lindex,
|
||||
rli->off, rli->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file in .clipboard dir
|
||||
*
|
||||
* This function is called by clipboard code
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
*****************************************************************************/
|
||||
|
||||
int xfuse_add_clip_dir_item(char *filename, int flags, int size, int lindex)
|
||||
{
|
||||
return 0; // CLIPBOARD_TODO
|
||||
log_debug("entered: filename=%s flags=%d size=%d lindex=%d",
|
||||
filename, flags, size, lindex);
|
||||
|
||||
/* add entry to xrdp_fs */
|
||||
XRDP_INODE *xinode = xfuse_create_file_in_xrdp_fs(0, /* device id */
|
||||
2, /* parent inode */
|
||||
filename,
|
||||
S_IFREG);
|
||||
xinode->size = size;
|
||||
xinode->lindex = lindex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -657,7 +696,8 @@ int xfuse_add_clip_dir_item(char *filename, int flags, int size, int lindex)
|
||||
|
||||
int xfuse_file_contents_size(int stream_id, int file_size)
|
||||
{
|
||||
return 0; // CLIPBOARD_TODO
|
||||
log_debug("entered: stream_id=%d file_size=%d", stream_id, file_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -705,6 +745,9 @@ static int xfuse_init_lib(struct fuse_args *args)
|
||||
g_buffer = calloc(g_bufsize, 1);
|
||||
g_fd = fuse_chan_fd(g_ch);
|
||||
|
||||
g_req_list = list_create();
|
||||
g_req_list->auto_free = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -789,7 +832,7 @@ static int xfuse_init_xrdp_fs()
|
||||
g_xrdp_fs.inode_table[2] = xino;
|
||||
xino->parent_inode = 1;
|
||||
xino->inode = 2;
|
||||
xino->nentries = 1;
|
||||
xino->nentries = 0;
|
||||
xino->mode = S_IFDIR | 0755;
|
||||
xino->uid = getuid();
|
||||
xino->gid = getgid();
|
||||
@ -1076,8 +1119,6 @@ static struct xrdp_inode * xfuse_create_file_in_xrdp_fs(tui32 device_id,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_debug("S_IFDIR=0x%x S_IFREG=0x%x type=0x%x", S_IFDIR, S_IFREG, type);
|
||||
|
||||
xinode->parent_inode = pinode;
|
||||
xinode->inode = g_xrdp_fs.next_node++;
|
||||
xinode->nlink = 1;
|
||||
@ -1458,7 +1499,7 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
|
||||
|
||||
/* insert it in xrdp fs and update lookup count */
|
||||
g_xrdp_fs.inode_table[xinode->inode] = xinode;
|
||||
g_xrdp_fs.inode_table[fip->inode]->nentries;
|
||||
g_xrdp_fs.inode_table[fip->inode]->nentries++; /* this was missing */
|
||||
xfuse_update_xrdpfs_size();
|
||||
}
|
||||
|
||||
@ -1759,7 +1800,6 @@ done:
|
||||
|
||||
void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length)
|
||||
{
|
||||
XFUSE_HANDLE *fh;
|
||||
XFUSE_INFO *fip;
|
||||
|
||||
fip = (XFUSE_INFO *) vp;
|
||||
@ -1773,7 +1813,6 @@ void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length)
|
||||
void xfuse_devredir_cb_write_file(void *vp, char *buf, size_t length)
|
||||
{
|
||||
XRDP_INODE *xinode;
|
||||
XFUSE_HANDLE *fh;
|
||||
XFUSE_INFO *fip;
|
||||
|
||||
fip = (XFUSE_INFO *) vp;
|
||||
@ -1962,131 +2001,6 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
|
||||
return;
|
||||
}
|
||||
|
||||
static void xfuse_cb_lookup_TODO(fuse_req_t req, fuse_ino_t parent, const char *name)
|
||||
{
|
||||
XFUSE_INFO *fip;
|
||||
XRDP_INODE *xinode;
|
||||
struct fuse_entry_param e;
|
||||
tui32 device_id;
|
||||
char full_path[4096];
|
||||
char *cptr;
|
||||
|
||||
/* SPEEDUP_TODO */
|
||||
printf("###### cb_lookup: looking for parent=%d name=%s\n", (int) parent, name);
|
||||
|
||||
log_debug("ENTERED: looking for parent=%d name=%s", (int) parent, name);
|
||||
|
||||
xfuse_dump_fs();
|
||||
|
||||
if (!xfuse_is_inode_valid(parent))
|
||||
{
|
||||
log_error("inode %d is not valid", parent);
|
||||
fuse_reply_err(req, EBADF);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) != NULL)
|
||||
{
|
||||
log_debug("got match: device_id=%d", xinode->device_id);
|
||||
|
||||
/* got a full match; if this dir is located on a remote device */
|
||||
/* and is not synced, do a remote look up */
|
||||
#ifdef USE_SYNC_FLAG
|
||||
if ((xinode->device_id != 0) && (!xinode->is_synced))
|
||||
goto do_remote_lookup;
|
||||
#else
|
||||
if (xinode->device_id != 0)
|
||||
goto do_remote_lookup;
|
||||
#endif
|
||||
memset(&e, 0, sizeof(e));
|
||||
e.ino = xinode->inode;
|
||||
e.attr_timeout = XFUSE_ATTR_TIMEOUT;
|
||||
e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
|
||||
e.attr.st_ino = xinode->inode;
|
||||
e.attr.st_mode = xinode->mode;
|
||||
e.attr.st_nlink = xinode->nlink;
|
||||
e.attr.st_uid = xinode->uid;
|
||||
e.attr.st_gid = xinode->gid;
|
||||
e.attr.st_size = xinode->size;
|
||||
e.attr.st_atime = xinode->atime;
|
||||
e.attr.st_mtime = xinode->mtime;
|
||||
e.attr.st_ctime = xinode->ctime;
|
||||
e.generation = 1;
|
||||
|
||||
fuse_reply_entry(req, &e);
|
||||
log_debug("found entry in xrdp fs; returning");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_debug("xinode is NULL for parent=%d name=%s", (int) parent, name);
|
||||
}
|
||||
|
||||
do_remote_lookup:
|
||||
|
||||
/* if ino belongs to a redirected share, pass the call to devredir; */
|
||||
/* when done, devredir will invoke xfuse_devredir_cb_enum_dir_done(...) */
|
||||
strcpy(full_path, name);
|
||||
log_debug("full_path=%s name=%s", full_path, name);
|
||||
device_id = xfuse_get_device_id_for_inode((tui32) parent, full_path);
|
||||
log_debug("device_id=%d", device_id);
|
||||
if (device_id != 0)
|
||||
{
|
||||
log_debug("did not find entry; redirecting call to dev_redir");
|
||||
|
||||
printf("????????? xfuse_cb_lookup() doing remote lookup for %s\n", name);
|
||||
|
||||
if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
|
||||
{
|
||||
log_error("system out of memory");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
return;
|
||||
}
|
||||
fip->req = req;
|
||||
fip->inode = parent;
|
||||
strncpy(fip->name, name, 1024);
|
||||
fip->name[1023] = 0;
|
||||
fip->invoke_fuse = 1;
|
||||
fip->device_id = device_id;
|
||||
|
||||
if (parent != 1)
|
||||
{
|
||||
strcat(full_path, "/");
|
||||
strcat(full_path, name);
|
||||
}
|
||||
|
||||
/* we want path minus 'root node of the share' */
|
||||
if ((cptr = strchr(full_path, '/')) == NULL)
|
||||
{
|
||||
/* enumerate root dir */
|
||||
if (dev_redir_get_dir_listing((void *) fip, device_id, "\\"))
|
||||
{
|
||||
log_error("failed to send dev_redir_get_dir_listing() cmd");
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_debug("dev_redir_get_dir_listing() called");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dev_redir_get_dir_listing((void *) fip, device_id, cptr))
|
||||
{
|
||||
log_error("failed to send dev_redir_get_dir_listing() cmd");
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("cmd sent; reting");
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("parent=%d name=%s not found", (int) parent, name);
|
||||
fuse_reply_err(req, ENOENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file attributes
|
||||
*****************************************************************************/
|
||||
@ -2202,85 +2116,6 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
|
||||
/* enumerate resources on a remote device */
|
||||
|
||||
// lK_TODO
|
||||
#if 0
|
||||
{
|
||||
struct dirbuf b;
|
||||
|
||||
memset(&b, 0, sizeof(struct dirbuf));
|
||||
xfuse_dirbuf_add(req, &b, ".", 1);
|
||||
xfuse_dirbuf_add(req, &b, "..", 1);
|
||||
xfuse_dirbuf_add(req, &b, "f2", 2);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f3", 3);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f4", 4);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f5", 5);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f6", 6);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f7", 7);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f8", 8);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f9", 9);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f10", 10);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f11", 11);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
xfuse_dirbuf_add(req, &b, "f12", 12);
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SYNC_FLAG
|
||||
if (xinode->is_synced)
|
||||
{
|
||||
@ -2337,66 +2172,6 @@ do_remote_lookup:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void xfuse_cb_readdir_TODO(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
struct xrdp_inode *xinode;
|
||||
struct dirbuf b;
|
||||
int i;
|
||||
|
||||
(void) fi;
|
||||
|
||||
/* SPEEDUP_TODO */
|
||||
printf("++++++ cb_readdir: looking for inode=%d\n", (int) ino);
|
||||
|
||||
log_debug("looking for dir with inode=%d", ino);
|
||||
|
||||
if (!xfuse_is_inode_valid(ino))
|
||||
{
|
||||
log_error("inode %d is not valid", ino);
|
||||
fuse_reply_err(req, EBADF);
|
||||
return;
|
||||
}
|
||||
|
||||
/* does this dir have any entries? */
|
||||
xinode = g_xrdp_fs.inode_table[ino];
|
||||
memset(&b, 0, sizeof(b));
|
||||
if (ino == 1)
|
||||
{
|
||||
xfuse_dirbuf_add(req, &b, ".", 1);
|
||||
xfuse_dirbuf_add(req, &b, "..", 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
xfuse_dirbuf_add(req, &b, ".", xinode->inode);
|
||||
xfuse_dirbuf_add(req, &b, "..", xinode->parent_inode);
|
||||
}
|
||||
|
||||
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
|
||||
{
|
||||
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
|
||||
continue;
|
||||
|
||||
if (xinode->parent_inode == ino)
|
||||
xfuse_dirbuf_add(req, &b, xinode->name, xinode->inode);
|
||||
}
|
||||
|
||||
if (off < b.size)
|
||||
fuse_reply_buf(req, b.p + off, min(b.size - off, size));
|
||||
else
|
||||
fuse_reply_buf(req, NULL, 0);
|
||||
|
||||
free(b.p);
|
||||
|
||||
printf("++++++ cb_readdir: leaving\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a directory
|
||||
*****************************************************************************/
|
||||
@ -2816,10 +2591,16 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
||||
}
|
||||
|
||||
device_id = xfuse_get_device_id_for_inode((tui32) ino, full_path);
|
||||
if (device_id)
|
||||
if (device_id == 0)
|
||||
{
|
||||
/* specified file resides on redirected share */
|
||||
/* specified file is a local resource */
|
||||
XFUSE_HANDLE *fh = calloc(1, sizeof(XFUSE_HANDLE));
|
||||
fi->fh = (uint64_t) ((long) fh);
|
||||
fuse_reply_open(req, fi);
|
||||
return;
|
||||
}
|
||||
|
||||
/* specified file resides on redirected share */
|
||||
if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
|
||||
{
|
||||
log_error("system out of memory");
|
||||
@ -2858,15 +2639,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
||||
fuse_reply_err(req, EREMOTEIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* specified file is a local resource */
|
||||
//XFUSE_HANDLE *fh;
|
||||
|
||||
log_debug("LK_TODO: this is still a TODO");
|
||||
fuse_reply_err(req, EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void xfuse_cb_flush(fuse_req_t req, fuse_ino_t ino, struct
|
||||
@ -2885,8 +2657,7 @@ static void xfuse_cb_flush(fuse_req_t req, fuse_ino_t ino, struct
|
||||
if (handle->DeviceId == 0)
|
||||
{
|
||||
/* specified file is a local resource */
|
||||
log_debug("LK_TODO: this is still a TODO");
|
||||
fuse_reply_err(req, EBADF);
|
||||
fuse_reply_err(req, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2920,9 +2691,11 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
{
|
||||
XFUSE_HANDLE *fh;
|
||||
XFUSE_INFO *fusep;
|
||||
XRDP_INODE *xinode;
|
||||
struct req_list_item *rli;
|
||||
long handle;
|
||||
|
||||
log_debug("want_bytes %d bytes at off %d", size, off);
|
||||
log_debug("want_bytes %ld bytes at off %ld", size, off);
|
||||
|
||||
if (fi->fh == 0)
|
||||
{
|
||||
@ -2936,7 +2709,35 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
if (fh->DeviceId == 0)
|
||||
{
|
||||
/* target file is in .clipboard dir */
|
||||
log_debug(">>>>>>>>>>>>>>>>> THIS IS STILL A TODO!");
|
||||
|
||||
log_debug("target file is in .clipboard dir");
|
||||
|
||||
if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
|
||||
{
|
||||
log_error("ino does not exist in xrdp_fs");
|
||||
fuse_reply_buf(req, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
rli = (struct req_list_item *)
|
||||
g_malloc(sizeof(struct req_list_item), 1);
|
||||
|
||||
rli->stream_id = 0;
|
||||
rli->req = req;
|
||||
rli->lindex = xinode->lindex;
|
||||
rli->off = off;
|
||||
rli->size = size;
|
||||
list_add_item(g_req_list, (tbus) rli);
|
||||
|
||||
if (g_req_list->count == 1)
|
||||
{
|
||||
log_debug("requesting clipboard file data lindex = %d off = %d size = %d",
|
||||
rli->lindex, (int) off, (int) size);
|
||||
|
||||
clipboard_request_file_data(rli->stream_id, rli->lindex,
|
||||
(int) off, (int) size);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3007,88 +2808,12 @@ static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent,
|
||||
xfuse_create_dir_or_file(req, parent, name, mode, fi, S_IFREG);
|
||||
}
|
||||
|
||||
// LK_TODO may not need to implement the following funcs
|
||||
|
||||
#if 0
|
||||
static void xfuse_cb_statfs(fuse_req_t req, fuse_ino_t ino)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
}
|
||||
|
||||
static void xfuse_cb_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
const char *value, size_t size, int flags)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
static void xfuse_cb_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
size_t size)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
static void xfuse_cb_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
static void xfuse_cb_access(fuse_req_t req, fuse_ino_t ino, int mask)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
static void xfuse_cb_getlk(fuse_req_t req, fuse_ino_t ino,
|
||||
struct fuse_file_info *fi, struct flock *lock)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
static void xfuse_cb_setlk(fuse_req_t req, fuse_ino_t ino,
|
||||
struct fuse_file_info *fi, struct flock *lock,
|
||||
int sleep)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
static void xfuse_cb_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags,
|
||||
const void *in_buf, size_t in_bufsz,
|
||||
size_t out_bufsz)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
static void xfuse_cb_poll(fuse_req_t req, fuse_ino_t ino,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_pollhandle *ph)
|
||||
{
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
int to_set, struct fuse_file_info *fi)
|
||||
{
|
||||
XRDP_INODE *xinode;
|
||||
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered to_set=0x%x", to_set);
|
||||
log_debug("entered to_set=0x%x", to_set);
|
||||
|
||||
if (!xfuse_is_inode_valid(ino))
|
||||
{
|
||||
@ -3102,20 +2827,20 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
if (to_set & FUSE_SET_ATTR_MODE)
|
||||
{
|
||||
xinode->mode = attr->st_mode;
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_MODE");
|
||||
log_debug("FUSE_SET_ATTR_MODE");
|
||||
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_UID)
|
||||
{
|
||||
xinode->uid = attr->st_uid;
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_UID");
|
||||
log_debug("FUSE_SET_ATTR_UID");
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_GID)
|
||||
{
|
||||
xinode->gid = attr->st_gid;
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_GID");
|
||||
log_debug("FUSE_SET_ATTR_GID");
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_SIZE)
|
||||
@ -3128,25 +2853,25 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
if (to_set & FUSE_SET_ATTR_ATIME)
|
||||
{
|
||||
xinode->atime = attr->st_atime;
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_ATIME");
|
||||
log_debug("FUSE_SET_ATTR_ATIME");
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_MTIME)
|
||||
{
|
||||
xinode->mtime = attr->st_mtime;
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_MTIME");
|
||||
log_debug("FUSE_SET_ATTR_MTIME");
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_ATIME_NOW)
|
||||
{
|
||||
xinode->atime = attr->st_atime;
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_ATIME_NOW");
|
||||
log_debug("FUSE_SET_ATTR_ATIME_NOW");
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_MTIME_NOW)
|
||||
{
|
||||
xinode->mtime = attr->st_mtime;
|
||||
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_MTIME_NOW");
|
||||
log_debug("FUSE_SET_ATTR_MTIME_NOW");
|
||||
}
|
||||
|
||||
fuse_reply_attr(req, attr, 1.0); /* LK_TODO just faking for now */
|
||||
|
@ -38,6 +38,7 @@ struct xrdp_inode
|
||||
tui32 device_id; /* for file system redirection */
|
||||
char is_synced; /* dir struct has been read from */
|
||||
/* remote device, done just once */
|
||||
int lindex; /* used in clipboard operations */
|
||||
};
|
||||
typedef struct xrdp_inode XRDP_INODE; // LK_TODO use this instead of using struct xrdp_inode
|
||||
|
||||
|
@ -53,7 +53,7 @@ extern int g_cliprdr_chan_id; /* in chansrv.c */
|
||||
extern struct clip_s2c g_clip_s2c; /* in clipboard.c */
|
||||
extern struct clip_c2s g_clip_c2s; /* in clipboard.c */
|
||||
|
||||
extern char g_fuse_root_path[]; /* in chansrv_fuse.c */
|
||||
extern char g_fuse_clipboard_path[];
|
||||
|
||||
struct cb_file_info
|
||||
{
|
||||
@ -454,7 +454,9 @@ clipboard_request_file_data(int stream_id, int lindex, int offset,
|
||||
int size;
|
||||
int rv;
|
||||
|
||||
LLOGLN(10, ("clipboard_request_file_data:"));
|
||||
LLOGLN(10, ("clipboard_request_file_data: stream_id=%d lindex=%d off=%d request_bytes=%d",
|
||||
stream_id, lindex, offset, request_bytes));
|
||||
|
||||
if (g_file_request_sent_type != 0)
|
||||
{
|
||||
LLOGLN(0, ("clipboard_request_file_data: warning, still waiting "
|
||||
@ -625,8 +627,8 @@ clipboard_c2s_in_files(struct stream *s, char *file_list)
|
||||
g_strcpy(ptr, "file://");
|
||||
ptr += 7;
|
||||
|
||||
str_len = g_strlen(g_fuse_root_path);
|
||||
g_strcpy(ptr, g_fuse_root_path);
|
||||
str_len = g_strlen(g_fuse_clipboard_path);
|
||||
g_strcpy(ptr, g_fuse_clipboard_path);
|
||||
ptr += str_len;
|
||||
|
||||
*ptr = '/';
|
||||
|
@ -1024,7 +1024,6 @@ int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId)
|
||||
if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL)
|
||||
{
|
||||
log_error("no IRP found with FileId = %d", FileId);
|
||||
xfuse_devredir_cb_read_file(fusep, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
130
tests/gtcp_proxy/hexdump.c
Normal file
130
tests/gtcp_proxy/hexdump.c
Normal file
@ -0,0 +1,130 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* An optimized hexdump function
|
||||
*
|
||||
* @param address address to display in address column
|
||||
* @param buf data to hexdump
|
||||
* @param len number of bytes to dump
|
||||
*****************************************************************************/
|
||||
|
||||
void hexdump(int address, char *buf, int len)
|
||||
{
|
||||
uint32_t addr;
|
||||
char outbuf[80];
|
||||
int blocks;
|
||||
int residual;
|
||||
int i;
|
||||
int j;
|
||||
int buf_index;
|
||||
int index2; /* data column */
|
||||
int index3; /* ascii column */
|
||||
|
||||
unsigned char c;
|
||||
|
||||
char cvt[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
if ((buf == NULL) || (len <= 0))
|
||||
return;
|
||||
|
||||
addr = (address < 0) ? 0 : address;
|
||||
blocks = len / 16;
|
||||
residual = len - blocks * 16;
|
||||
buf_index = 0;
|
||||
|
||||
for (i = 0; i < blocks; i++)
|
||||
{
|
||||
index2 = 10;
|
||||
index3 = 60;
|
||||
|
||||
outbuf[9] = ' ';
|
||||
outbuf[8] = ' ';
|
||||
outbuf[7] = cvt[(addr >> 0) & 0x0000000f];
|
||||
outbuf[6] = cvt[(addr >> 4) & 0x0000000f];
|
||||
outbuf[5] = cvt[(addr >> 8) & 0x0000000f];
|
||||
outbuf[4] = cvt[(addr >> 12) & 0x0000000f];
|
||||
outbuf[3] = cvt[(addr >> 16) & 0x0000000f];
|
||||
outbuf[2] = cvt[(addr >> 20) & 0x0000000f];
|
||||
outbuf[1] = cvt[(addr >> 24) & 0x0000000f];
|
||||
outbuf[0] = cvt[(addr >> 28) & 0x0000000f];
|
||||
addr += 16;
|
||||
|
||||
/* insert spaces */
|
||||
outbuf[8] = ' ';
|
||||
outbuf[9] = ' ';
|
||||
outbuf[58] = ' ';
|
||||
outbuf[59] = ' ';
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
c = buf[buf_index++];
|
||||
|
||||
outbuf[index2++] = cvt[(c >> 4) & 0x0f];
|
||||
outbuf[index2++] = cvt[(c >> 0) & 0x0f];
|
||||
outbuf[index2++] = ' ';
|
||||
|
||||
if ((c >= 0x20) && (c <= 0x7e))
|
||||
outbuf[index3++] = c;
|
||||
else
|
||||
outbuf[index3++] = '.';
|
||||
}
|
||||
|
||||
outbuf[index3] = 0;
|
||||
puts(outbuf);
|
||||
}
|
||||
|
||||
if (!residual)
|
||||
return;
|
||||
|
||||
outbuf[7] = cvt[(addr >> 0) & 0x0000000f];
|
||||
outbuf[6] = cvt[(addr >> 4) & 0x0000000f];
|
||||
outbuf[5] = cvt[(addr >> 8) & 0x0000000f];
|
||||
outbuf[4] = cvt[(addr >> 12) & 0x0000000f];
|
||||
outbuf[3] = cvt[(addr >> 16) & 0x0000000f];
|
||||
outbuf[2] = cvt[(addr >> 20) & 0x0000000f];
|
||||
outbuf[1] = cvt[(addr >> 24) & 0x0000000f];
|
||||
outbuf[0] = cvt[(addr >> 28) & 0x0000000f];
|
||||
addr += 16;
|
||||
|
||||
index2 = 10;
|
||||
index3 = 60;
|
||||
memset(&outbuf[8], ' ', 68);
|
||||
|
||||
for (j = 0; j < residual; j++)
|
||||
{
|
||||
c = buf[buf_index++];
|
||||
|
||||
outbuf[index2++] = cvt[(c >> 4) & 0x0f];
|
||||
outbuf[index2++] = cvt[(c >> 0) & 0x0f];
|
||||
outbuf[index2++] = ' ';
|
||||
|
||||
if ((c >= 0x20) && (c <= 0x7e))
|
||||
outbuf[index3++] = c;
|
||||
else
|
||||
outbuf[index3++] = '.';
|
||||
}
|
||||
|
||||
outbuf[index3] = 0;
|
||||
puts(outbuf);
|
||||
}
|
Loading…
Reference in New Issue
Block a user