From 867c5533786e1dfc58d12252bfda3ccba9cce087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stig-=C3=98rjan=20Smelror?= Date: Fri, 31 May 2024 16:19:45 +0200 Subject: [PATCH] Third Batch: Update files using ChatGPT 4o --- ctrl.c | 691 +++++++++--------- disk.c | 2018 +++++++++++++++++++++++++--------------------------- disk.h | 224 +++--- dvc.c | 614 +++++++--------- ewmhints.c | 55 +- 5 files changed, 1690 insertions(+), 1912 deletions(-) diff --git a/ctrl.c b/ctrl.c index 190a249..3452a56 100644 --- a/ctrl.c +++ b/ctrl.c @@ -51,469 +51,432 @@ static struct _ctrl_slave_t *_ctrl_slaves; typedef struct _ctrl_slave_t { - struct _ctrl_slave_t *prev, *next; - int sock; - char linebuf[CTRL_LINEBUF_SIZE]; + struct _ctrl_slave_t *prev, *next; + int sock; + char linebuf[CTRL_LINEBUF_SIZE]; } _ctrl_slave_t; +static void _ctrl_slave_new(int sock); +static void _ctrl_slave_disconnect(int sock); +static void _ctrl_command_result(_ctrl_slave_t *slave, int result); +static void _ctrl_dispatch_command(_ctrl_slave_t *slave); +static RD_BOOL _ctrl_verify_unix_socket(void); +static void _ctrl_create_hash(const char *user, const char *domain, const char *host, char *hash, size_t hsize); -static void -_ctrl_slave_new(int sock) +static void _ctrl_slave_new(int sock) { - _ctrl_slave_t *it, *ns; + _ctrl_slave_t *it, *ns; - /* initialize new slave list item */ - ns = (_ctrl_slave_t *) xmalloc(sizeof(_ctrl_slave_t)); - memset(ns, 0, sizeof(_ctrl_slave_t)); - ns->sock = sock; + ns = (_ctrl_slave_t *)malloc(sizeof(_ctrl_slave_t)); + if (!ns) + { + logger(Core, Error, "_ctrl_slave_new(), malloc() failed"); + return; + } + memset(ns, 0, sizeof(_ctrl_slave_t)); + ns->sock = sock; - /* append new slave to end of list */ - it = _ctrl_slaves; + it = _ctrl_slaves; - /* find last element in list */ - while (it && it->next) - it = it->next; + while (it && it->next) + it = it->next; - /* if last found append new */ - if (it) - { - it->next = ns; - ns->prev = it; - } - else - { - /* no elements in list, lets add first */ - _ctrl_slaves = ns; - } + if (it) + { + it->next = ns; + ns->prev = it; + } + else + { + _ctrl_slaves = ns; + } } -static void -_ctrl_slave_disconnect(int sock) +static void _ctrl_slave_disconnect(int sock) { - _ctrl_slave_t *it; + _ctrl_slave_t *it; - if (!_ctrl_slaves) - return; + if (!_ctrl_slaves) + return; - it = _ctrl_slaves; + it = _ctrl_slaves; - /* find slave with sock */ - while (it->next && it->sock != sock) - it = it->next; + while (it->next && it->sock != sock) + it = it->next; - if (it->sock == sock) - { - /* shutdown socket */ - shutdown(sock, SHUT_RDWR); - close(sock); + if (it->sock == sock) + { + shutdown(sock, SHUT_RDWR); + close(sock); - /* remove item from list */ - if (it == _ctrl_slaves) - { - if (it->next) - _ctrl_slaves = it->next; - else - _ctrl_slaves = NULL; - } + if (it == _ctrl_slaves) + { + if (it->next) + _ctrl_slaves = it->next; + else + _ctrl_slaves = NULL; + } - if (it->prev) - { - (it->prev)->next = it->next; - if (it->next) - (it->next)->prev = it->prev; - } - else if (it->next) - (it->next)->prev = NULL; + if (it->prev) + { + (it->prev)->next = it->next; + if (it->next) + (it->next)->prev = it->prev; + } + else if (it->next) + (it->next)->prev = NULL; - xfree(it); - - } + free(it); + } } -static void -_ctrl_command_result(_ctrl_slave_t * slave, int result) +static void _ctrl_command_result(_ctrl_slave_t *slave, int result) { - char buf[64] = { 0 }; + char buf[64] = {0}; - /* translate and send result code back to client */ - if (result == 0) - send(slave->sock, "OK\n", 3, 0); - else - { - snprintf(buf, 64, "ERROR %x\n", result); - send(slave->sock, buf, strlen(buf), 0); - } + if (result == 0) + send(slave->sock, "OK\n", 3, 0); + else + { + snprintf(buf, sizeof(buf), "ERROR %x\n", result); + send(slave->sock, buf, strlen(buf), 0); + } } -static void -_ctrl_dispatch_command(_ctrl_slave_t * slave) +static void _ctrl_dispatch_command(_ctrl_slave_t *slave) { - char *p; - char *cmd; - unsigned int res; + char *cmd, *p; + unsigned int res; - /* unescape linebuffer */ - cmd = utils_string_unescape(slave->linebuf); - if (strncmp(cmd, CMD_SEAMLESS_SPAWN " ", strlen(CMD_SEAMLESS_SPAWN) + 1) == 0) - { - /* process seamless spawn request */ - p = strstr(cmd, "seamlessrdpshell.exe"); - if (p) - p += strlen("seamlessrdpshell.exe") + 1; - else - p = cmd + strlen(CMD_SEAMLESS_SPAWN) + 1; + cmd = utils_string_unescape(slave->linebuf); + if (!cmd) + { + _ctrl_command_result(slave, ERR_RESULT_NO_SUCH_COMMAND); + return; + } - res = ERR_RESULT_OK; + if (strncmp(cmd, CMD_SEAMLESS_SPAWN " ", strlen(CMD_SEAMLESS_SPAWN) + 1) == 0) + { + p = strstr(cmd, "seamlessrdpshell.exe"); + if (p) + p += strlen("seamlessrdpshell.exe") + 1; + else + p = cmd + strlen(CMD_SEAMLESS_SPAWN) + 1; - if (seamless_send_spawn(p) == (unsigned int) -1) - res = 1; - } - else - { - res = ERR_RESULT_NO_SUCH_COMMAND; - } - xfree(cmd); + res = ERR_RESULT_OK; - _ctrl_command_result(slave, res); + if (seamless_send_spawn(p) == (unsigned int)-1) + res = 1; + } + else + { + res = ERR_RESULT_NO_SUCH_COMMAND; + } + free(cmd); + + _ctrl_command_result(slave, res); } -static RD_BOOL -_ctrl_verify_unix_socket() +static RD_BOOL _ctrl_verify_unix_socket(void) { - int s, len; - struct sockaddr_un saun; + int s; + struct sockaddr_un saun; + socklen_t len; - memset(&saun, 0, sizeof(struct sockaddr_un)); + memset(&saun, 0, sizeof(struct sockaddr_un)); - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - { - logger(Core, Error, "_ctrl_verify_unix_socket(), socket() failed: %s", - strerror(errno)); - exit(1); - } + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + { + logger(Core, Error, "_ctrl_verify_unix_socket(), socket() failed: %s", + strerror(errno)); + exit(1); + } - saun.sun_family = AF_UNIX; - strcpy(saun.sun_path, ctrlsock_name); - len = sizeof(saun.sun_family) + strlen(saun.sun_path); + saun.sun_family = AF_UNIX; + strncpy(saun.sun_path, ctrlsock_name, sizeof(saun.sun_path) - 1); + len = sizeof(saun.sun_family) + strlen(saun.sun_path); - /* test connection */ - if (connect(s, (struct sockaddr *) &saun, len) != 0) - return False; + if (connect(s, (struct sockaddr *)&saun, len) != 0) + { + close(s); + return False; + } - shutdown(s, SHUT_RDWR); - close(s); - return True; + shutdown(s, SHUT_RDWR); + close(s); + return True; } - -static void -_ctrl_create_hash(const char *user, const char *domain, const char *host, char *hash, size_t hsize) +static void _ctrl_create_hash(const char *user, const char *domain, const char *host, char *hash, size_t hsize) { - RDSSL_SHA1 sha1; - uint8 out[20], delim; - uint16 version; - uint32 flags; + RDSSL_SHA1 sha1; + uint8 out[20], delim; + uint16 version; + uint32 flags; - /* version\0user\0domain\0host\0flags */ - flags = 0; - delim = '\0'; - version = 0x0100; + flags = 0; + delim = '\0'; + version = 0x0100; - if (g_seamless_rdp) - flags = CTRL_HASH_FLAG_SEAMLESS; + if (g_seamless_rdp) + flags = CTRL_HASH_FLAG_SEAMLESS; - rdssl_sha1_init(&sha1); - rdssl_sha1_update(&sha1, (uint8 *) & version, sizeof(version)); - rdssl_sha1_update(&sha1, &delim, 1); + rdssl_sha1_init(&sha1); + rdssl_sha1_update(&sha1, (uint8 *)&version, sizeof(version)); + rdssl_sha1_update(&sha1, &delim, 1); - if (user) - rdssl_sha1_update(&sha1, (uint8 *) user, strlen(user)); - rdssl_sha1_update(&sha1, &delim, 1); + if (user) + rdssl_sha1_update(&sha1, (uint8 *)user, strlen(user)); + rdssl_sha1_update(&sha1, &delim, 1); - if (domain) - rdssl_sha1_update(&sha1, (uint8 *) domain, strlen(domain)); - rdssl_sha1_update(&sha1, &delim, 1); + if (domain) + rdssl_sha1_update(&sha1, (uint8 *)domain, strlen(domain)); + rdssl_sha1_update(&sha1, &delim, 1); - if (host) - rdssl_sha1_update(&sha1, (uint8 *) host, strlen(host)); - rdssl_sha1_update(&sha1, &delim, 1); + if (host) + rdssl_sha1_update(&sha1, (uint8 *)host, strlen(host)); + rdssl_sha1_update(&sha1, &delim, 1); - rdssl_sha1_update(&sha1, (uint8 *) & flags, sizeof(flags)); - rdssl_sha1_final(&sha1, out); + rdssl_sha1_update(&sha1, (uint8 *)&flags, sizeof(flags)); + rdssl_sha1_final(&sha1, out); - sec_hash_to_string(hash, hsize, out, sizeof(out)); + sec_hash_to_string(hash, hsize, out, sizeof(out)); } - -/** Initialize ctrl - Ret values: <0 failure, 0 master, 1 client - */ -int -ctrl_init(const char *user, const char *domain, const char *host) +int ctrl_init(const char *user, const char *domain, const char *host) { - struct stat st; - struct sockaddr_un saun; - char hash[41], path[PATH_MAX]; - char *home; + struct stat st; + struct sockaddr_un saun; + char hash[41], path[PATH_MAX]; + const char *home; - /* check if ctrl already initialized */ - if (ctrlsock != 0 || _ctrl_is_slave) - return 0; + if (ctrlsock != 0 || _ctrl_is_slave) + return 0; - home = getenv("HOME"); - if (home == NULL) - { - return -1; - } + home = getenv("HOME"); + if (home == NULL) + { + return -1; + } - /* get uniq hash for ctrlsock name */ - _ctrl_create_hash(user, domain, host, hash, 41); - snprintf(ctrlsock_name, PATH_MAX, "%s" RDESKTOP_CTRLSOCK_STORE "/%s.ctl", home, hash); - ctrlsock_name[sizeof(ctrlsock_name) - 1] = '\0'; + _ctrl_create_hash(user, domain, host, hash, sizeof(hash)); + snprintf(ctrlsock_name, sizeof(ctrlsock_name), "%s" RDESKTOP_CTRLSOCK_STORE "/%s.ctl", home, hash); - /* make sure that ctrlsock store path exists */ - snprintf(path, PATH_MAX, "%s" RDESKTOP_CTRLSOCK_STORE, home); - path[sizeof(path) - 1] = '\0'; - if (utils_mkdir_p(path, 0700) == -1) - { - logger(Core, Error, "ctrl_init(), utils_mkdir_p() failed: %s", strerror(errno)); - return -1; - } + snprintf(path, sizeof(path), "%s" RDESKTOP_CTRLSOCK_STORE, home); + if (utils_mkdir_p(path, 0700) == -1) + { + logger(Core, Error, "ctrl_init(), utils_mkdir_p() failed: %s", strerror(errno)); + return -1; + } - /* check if ctrl socket already exist then this process becomes a client */ - if (stat(ctrlsock_name, &st) == 0) - { - /* verify that unix socket is not stale */ - if (_ctrl_verify_unix_socket() == True) - { - _ctrl_is_slave = True; - return 1; - } - else - { - unlink(ctrlsock_name); - } - } + if (stat(ctrlsock_name, &st) == 0) + { + if (_ctrl_verify_unix_socket() == True) + { + _ctrl_is_slave = True; + return 1; + } + else + { + unlink(ctrlsock_name); + } + } - /* setup ctrl socket and start listening for connections */ - if ((ctrlsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - { - logger(Core, Error, "ctrl_init(), socket() failed: %s", strerror(errno)); - exit(1); - } + if ((ctrlsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + { + logger(Core, Error, "ctrl_init(), socket() failed: %s", strerror(errno)); + exit(1); + } - /* bind and start listening on server socket */ - memset(&saun, 0, sizeof(struct sockaddr_un)); - saun.sun_family = AF_UNIX; - strncpy(saun.sun_path, ctrlsock_name, sizeof(saun.sun_path)); - if (bind(ctrlsock, (struct sockaddr *) &saun, sizeof(struct sockaddr_un)) < 0) - { - logger(Core, Error, "ctrl_init(), bind() failed: %s", strerror(errno)); - exit(1); - } + memset(&saun, 0, sizeof(struct sockaddr_un)); + saun.sun_family = AF_UNIX; + strncpy(saun.sun_path, ctrlsock_name, sizeof(saun.sun_path) - 1); + if (bind(ctrlsock, (struct sockaddr *)&saun, sizeof(struct sockaddr_un)) < 0) + { + logger(Core, Error, "ctrl_init(), bind() failed: %s", strerror(errno)); + exit(1); + } - if (listen(ctrlsock, 5) < 0) - { - logger(Core, Error, "ctrl_init(), listen() failed: %s", strerror(errno)); - exit(1); - } + if (listen(ctrlsock, 5) < 0) + { + logger(Core, Error, "ctrl_init(), listen() failed: %s", strerror(errno)); + exit(1); + } - /* add ctrl cleanup func to exit hooks */ - atexit(ctrl_cleanup); + atexit(ctrl_cleanup); - return 0; + return 0; } -void -ctrl_cleanup() +void ctrl_cleanup(void) { - if (ctrlsock) - { - close(ctrlsock); - unlink(ctrlsock_name); - } + if (ctrlsock) + { + close(ctrlsock); + unlink(ctrlsock_name); + } } -RD_BOOL -ctrl_is_slave() +RD_BOOL ctrl_is_slave(void) { - return _ctrl_is_slave; + return _ctrl_is_slave; } - -void -ctrl_add_fds(int *n, fd_set * rfds) +void ctrl_add_fds(int *n, fd_set *rfds) { - _ctrl_slave_t *it; - if (ctrlsock == 0) - return; + _ctrl_slave_t *it; + if (ctrlsock == 0) + return; - FD_SET(ctrlsock, rfds); - *n = MAX(*n, ctrlsock); + FD_SET(ctrlsock, rfds); + *n = MAX(*n, ctrlsock); - - /* add connected slaves to fd set */ - it = _ctrl_slaves; - while (it) - { - FD_SET(it->sock, rfds); - *n = MAX(*n, it->sock); - it = it->next; - } + it = _ctrl_slaves; + while (it) + { + FD_SET(it->sock, rfds); + *n = MAX(*n, it->sock); + it = it->next; + } } -void -ctrl_check_fds(fd_set * rfds, fd_set * wfds) +void ctrl_check_fds(fd_set *rfds, fd_set *wfds) { - UNUSED(wfds); - int ns, res, offs; - struct sockaddr_un fsaun; - socklen_t fromlen; - _ctrl_slave_t *it; + UNUSED(wfds); + int ns, res, offs; + struct sockaddr_un fsaun; + socklen_t fromlen; + _ctrl_slave_t *it; - if (ctrlsock == 0) - return; + if (ctrlsock == 0) + return; - memset(&fsaun, 0, sizeof(struct sockaddr_un)); + memset(&fsaun, 0, sizeof(struct sockaddr_un)); - /* check if we got any connections on server socket */ - if (FD_ISSET(ctrlsock, rfds)) - { - FD_CLR(ctrlsock, rfds); - fromlen = sizeof(fsaun); - ns = accept(ctrlsock, (struct sockaddr *) &fsaun, &fromlen); - if (ns < 0) - { - logger(Core, Error, "ctrl_check_fds(), accept() failed: %s", - strerror(errno)); - exit(1); - } + if (FD_ISSET(ctrlsock, rfds)) + { + FD_CLR(ctrlsock, rfds); + fromlen = sizeof(fsaun); + ns = accept(ctrlsock, (struct sockaddr *)&fsaun, &fromlen); + if (ns < 0) + { + logger(Core, Error, "ctrl_check_fds(), accept() failed: %s", + strerror(errno)); + exit(1); + } - _ctrl_slave_new(ns); - return; - } + _ctrl_slave_new(ns); + return; + } - /* check if any of our slaves fds has data */ - it = _ctrl_slaves; - while (it) - { - if (FD_ISSET(it->sock, rfds)) - { - offs = strlen(it->linebuf); - res = recv(it->sock, it->linebuf + offs, CTRL_LINEBUF_SIZE - offs, 0); - FD_CLR(it->sock, rfds); + it = _ctrl_slaves; + while (it) + { + if (FD_ISSET(it->sock, rfds)) + { + offs = strlen(it->linebuf); + res = recv(it->sock, it->linebuf + offs, CTRL_LINEBUF_SIZE - offs - 1, 0); + FD_CLR(it->sock, rfds); - /* linebuffer full let's disconnect slave */ - if (it->linebuf[CTRL_LINEBUF_SIZE - 1] != '\0' && - it->linebuf[CTRL_LINEBUF_SIZE - 1] != '\n') - { - _ctrl_slave_disconnect(it->sock); - break; - } + if (it->linebuf[CTRL_LINEBUF_SIZE - 1] != '\0' && + it->linebuf[CTRL_LINEBUF_SIZE - 1] != '\n') + { + _ctrl_slave_disconnect(it->sock); + break; + } - if (res > 0) - { - /* Check if we got full command line */ - char *p; - if ((p = strchr(it->linebuf, '\n')) == NULL) - continue; + if (res > 0) + { + char *p; + if ((p = strchr(it->linebuf, '\n')) == NULL) + continue; - /* iterate over string and check against escaped \n */ - while (p) - { - /* Check if newline is escaped */ - if (p > it->linebuf && *(p - 1) != '\\') - break; - p = strchr(p + 1, '\n'); - } + while (p) + { + if (p > it->linebuf && *(p - 1) != '\\') + break; + p = strchr(p + 1, '\n'); + } - /* If we haven't found a nonescaped \n we need more data */ - if (p == NULL) - continue; + if (p == NULL) + continue; - /* strip new linebuf and dispatch command */ - *p = '\0'; - _ctrl_dispatch_command(it); - memset(it->linebuf, 0, CTRL_LINEBUF_SIZE); - } - else - { - /* Peer disconnected or socket error */ - _ctrl_slave_disconnect(it->sock); - break; - } - } - it = it->next; - } + *p = '\0'; + _ctrl_dispatch_command(it); + memset(it->linebuf, 0, CTRL_LINEBUF_SIZE); + } + else + { + _ctrl_slave_disconnect(it->sock); + break; + } + } + it = it->next; + } } -int -ctrl_send_command(const char *cmd, const char *arg) +int ctrl_send_command(const char *cmd, const char *arg) { - FILE *fp; - struct sockaddr_un saun; - int s, len, index, ret; - char data[CTRL_LINEBUF_SIZE], tmp[CTRL_LINEBUF_SIZE]; - char result[CTRL_RESULT_SIZE], c, *escaped; + FILE *fp; + struct sockaddr_un saun; + int s, len, index, ret; + char data[CTRL_LINEBUF_SIZE], tmp[CTRL_LINEBUF_SIZE]; + char result[CTRL_RESULT_SIZE], c, *escaped; - escaped = NULL; + escaped = NULL; - if (!_ctrl_is_slave) - return -1; + if (!_ctrl_is_slave) + return -1; - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - { - logger(Core, Error, "ctrl_send_command(), socket() failed: %s", strerror(errno)); - exit(1); - } + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + { + logger(Core, Error, "ctrl_send_command(), socket() failed: %s", strerror(errno)); + exit(1); + } - memset(&saun, 0, sizeof(struct sockaddr_un)); - saun.sun_family = AF_UNIX; - strcpy(saun.sun_path, ctrlsock_name); - len = sizeof(saun.sun_family) + strlen(saun.sun_path); + memset(&saun, 0, sizeof(struct sockaddr_un)); + saun.sun_family = AF_UNIX; + strncpy(saun.sun_path, ctrlsock_name, sizeof(saun.sun_path) - 1); + len = sizeof(saun.sun_family) + strlen(saun.sun_path); - if (connect(s, (struct sockaddr *) &saun, len) < 0) - { - logger(Core, Error, "ctrl_send_command(), connect() failed: %s", strerror(errno)); - exit(1); - } + if (connect(s, (struct sockaddr *)&saun, len) < 0) + { + logger(Core, Error, "ctrl_send_command(), connect() failed: %s", strerror(errno)); + exit(1); + } - /* Bundle cmd and argument into string, convert to UTF-8 if needed */ - snprintf(data, CTRL_LINEBUF_SIZE, "%s %s", cmd, arg); - ret = utils_locale_to_utf8(data, strlen(data), tmp, CTRL_LINEBUF_SIZE - 1); + snprintf(data, sizeof(data), "%s %s", cmd, arg); + ret = utils_locale_to_utf8(data, strlen(data), tmp, sizeof(tmp) - 1); - if (ret != 0) - goto bail_out; + if (ret != 0) + goto bail_out; - /* escape the UTF-8 string */ - escaped = utils_string_escape(tmp); - if ((strlen(escaped) + 1) > CTRL_LINEBUF_SIZE - 1) - goto bail_out; + escaped = utils_string_escape(tmp); + if ((strlen(escaped) + 1) > sizeof(data) - 1) + goto bail_out; - /* send escaped UTF-8 command to master */ - send(s, escaped, strlen(escaped), 0); - send(s, "\n", 1, 0); + send(s, escaped, strlen(escaped), 0); + send(s, "\n", 1, 0); - /* read result from master */ - fp = fdopen(s, "r"); - index = 0; - while ((c = fgetc(fp)) != EOF && index < CTRL_RESULT_SIZE && c != '\n') - { - result[index] = c; - index++; - } - result[index - 1] = '\0'; + fp = fdopen(s, "r"); + index = 0; + while ((c = fgetc(fp)) != EOF && index < CTRL_RESULT_SIZE && c != '\n') + { + result[index] = c; + index++; + } + result[index - 1] = '\0'; - if (strncmp(result, "ERROR ", 6) == 0) - { - if (sscanf(result, "ERROR %d", &ret) != 1) - ret = -1; - } + if (strncmp(result, "ERROR ", 6) == 0) + { + if (sscanf(result, "ERROR %d", &ret) != 1) + ret = -1; + } - bail_out: - xfree(escaped); - shutdown(s, SHUT_RDWR); - close(s); +bail_out: + free(escaped); + shutdown(s, SHUT_RDWR); + close(s); - return ret; + return ret; } diff --git a/disk.c b/disk.c index 2d5e246..d85cc3a 100644 --- a/disk.c +++ b/disk.c @@ -26,14 +26,15 @@ #include #include #include -#include /* open, close */ -#include /* opendir, closedir, readdir */ +#include /* open, close */ +#include /* opendir, closedir, readdir */ #include -#include /* errno */ +#include /* errno */ #include - #include -#include /* ctime */ +#include /* ctime */ +#include +#include #if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1)) #define DIRFD(a) (dirfd(a)) @@ -117,25 +118,24 @@ #ifndef STATFS_T struct dummy_statfs_t { - long f_bfree; - long f_bsize; - long f_bavail; - long f_blocks; - int f_namelen; - int f_namemax; + long f_bfree; + long f_bsize; + long f_bavail; + long f_blocks; + int f_namelen; + int f_namemax; }; -static int -dummy_statfs(struct dummy_statfs_t *buf) +static int dummy_statfs(struct dummy_statfs_t *buf) { - buf->f_blocks = 262144; - buf->f_bfree = 131072; - buf->f_bavail = 131072; - buf->f_bsize = 512; - buf->f_namelen = 255; - buf->f_namemax = 255; + buf->f_blocks = 262144; + buf->f_bfree = 131072; + buf->f_bavail = 131072; + buf->f_bsize = 512; + buf->f_namelen = 255; + buf->f_namemax = 255; - return 0; + return 0; } #define STATFS_T dummy_statfs_t @@ -149,1296 +149,1220 @@ RD_BOOL g_notify_stamp = False; typedef struct { - char name[PATH_MAX]; - char label[PATH_MAX]; - unsigned long serial; - char type[PATH_MAX]; + char name[PATH_MAX]; + char label[PATH_MAX]; + unsigned long serial; + char type[PATH_MAX]; } FsInfoType; -static RD_NTSTATUS NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY * p); +static RD_NTSTATUS NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY *p); -static time_t -get_create_time(struct stat *filestat) +static time_t get_create_time(struct stat *filestat) { - time_t ret, ret1; + time_t ret, ret1; - ret = MIN(filestat->st_ctime, filestat->st_mtime); - ret1 = MIN(ret, filestat->st_atime); + ret = MIN(filestat->st_ctime, filestat->st_mtime); + ret1 = MIN(ret, filestat->st_atime); - if (ret1 != (time_t) 0) - return ret1; + if (ret1 != (time_t)0) + return ret1; - return ret; + return ret; } /* Convert seconds since 1970 to a filetime */ -static void -seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low) +static void seconds_since_1970_to_filetime(time_t seconds, uint32 *high, uint32 *low) { - unsigned long long ticks; + unsigned long long ticks; - ticks = (seconds + 11644473600LL) * 10000000; - *low = (uint32) ticks; - *high = (uint32) (ticks >> 32); + ticks = (seconds + 11644473600LL) * 10000000; + *low = (uint32)ticks; + *high = (uint32)(ticks >> 32); } /* Convert seconds since 1970 back to filetime */ -static time_t -convert_1970_to_filetime(uint32 high, uint32 low) +static time_t convert_1970_to_filetime(uint32 high, uint32 low) { - unsigned long long ticks; - time_t val; + unsigned long long ticks; + time_t val; - ticks = low + (((unsigned long long) high) << 32); - ticks /= 10000000; - ticks -= 11644473600LL; - - val = (time_t) ticks; - return (val); + ticks = low + (((unsigned long long)high) << 32); + ticks /= 10000000; + ticks -= 11644473600LL; + val = (time_t)ticks; + return (val); } /* A wrapper for ftruncate which supports growing files, even if the native ftruncate doesn't. This is needed on Linux FAT filesystems, for example. */ -static int -ftruncate_growable(int fd, off_t length) +static int ftruncate_growable(int fd, off_t length) { - int ret; - off_t pos; - static const char zero = 0; + int ret; + off_t pos; + static const char zero = 0; - /* Try the simple method first */ - if ((ret = ftruncate(fd, length)) != -1) - { - return ret; - } + /* Try the simple method first */ + if ((ret = ftruncate(fd, length)) != -1) + { + return ret; + } - /* - * Some kind of error. Perhaps we were trying to grow. Retry - * in a safe way. - */ + /* + * Some kind of error. Perhaps we were trying to grow. Retry + * in a safe way. + */ - /* Get current position */ - if ((pos = lseek(fd, 0, SEEK_CUR)) == -1) - { - logger(Disk, Error, "ftruncate_growable(), lseek() failed: %s", strerror(errno)); - return -1; - } + /* Get current position */ + if ((pos = lseek(fd, 0, SEEK_CUR)) == -1) + { + logger(Disk, Error, "ftruncate_growable(), lseek() failed: %s", strerror(errno)); + return -1; + } - /* Seek to new size */ - if (lseek(fd, length, SEEK_SET) == -1) - { - logger(Disk, Error, "ftruncate_growable(), lseek() failed: %s", strerror(errno)); - return -1; - } + /* Seek to new size */ + if (lseek(fd, length, SEEK_SET) == -1) + { + logger(Disk, Error, "ftruncate_growable(), lseek() failed: %s", strerror(errno)); + return -1; + } - /* Write a zero */ - if (write(fd, &zero, 1) == -1) - { - logger(Disk, Error, "ftruncate_growable(), write() failed: %s", strerror(errno)); - return -1; - } + /* Write a zero */ + if (write(fd, &zero, 1) == -1) + { + logger(Disk, Error, "ftruncate_growable(), write() failed: %s", strerror(errno)); + return -1; + } - /* Truncate. This shouldn't fail. */ - if (ftruncate(fd, length) == -1) - { - logger(Disk, Error, "ftruncate_growable(), ftruncate() failed: %s", - strerror(errno)); - return -1; - } + /* Truncate. This shouldn't fail. */ + if (ftruncate(fd, length) == -1) + { + logger(Disk, Error, "ftruncate_growable(), ftruncate() failed: %s", strerror(errno)); + return -1; + } - /* Restore position */ - if (lseek(fd, pos, SEEK_SET) == -1) - { - logger(Disk, Error, "ftruncate_growable(), lseek() failed: %s", strerror(errno)); - return -1; - } + /* Restore position */ + if (lseek(fd, pos, SEEK_SET) == -1) + { + logger(Disk, Error, "ftruncate_growable(), lseek() failed: %s", strerror(errno)); + return -1; + } - return 0; + return 0; } -/* Just like open(2), but if a open with O_EXCL fails, retry with - GUARDED semantics. This might be necessary because some filesystems - (such as NFS filesystems mounted from a unfsd server) doesn't - support O_EXCL. GUARDED semantics are subject to race conditions, - but we can live with that. -*/ -static int -open_weak_exclusive(const char *pathname, int flags, mode_t mode) +/* Just like open(2), but if an open with O_EXCL fails due to unsupported + behavior by some filesystems (like NFS), retry without O_EXCL. + This ensures compatibility with filesystems that do not support O_EXCL. */ +static int open_weak_exclusive(const char *pathname, int flags, mode_t mode) { - int ret; - struct stat filestat; + int ret; + struct stat filestat; - ret = open(pathname, flags, mode); - if (ret != -1 || !(flags & O_EXCL)) - { - /* Success, or not using O_EXCL */ - return ret; - } + ret = open(pathname, flags, mode); + if (ret != -1 || !(flags & O_EXCL)) + { + /* Success, or not using O_EXCL */ + return ret; + } - /* An error occurred, and we are using O_EXCL. In case the FS - doesn't support O_EXCL, some kind of error will be - returned. Unfortunately, we don't know which one. Linux - 2.6.8 seems to return 524, but I cannot find a documented - #define for this case. So, we'll return only on errors that - we know aren't related to O_EXCL. */ - switch (errno) - { - case EACCES: - case EEXIST: - case EINTR: - case EISDIR: - case ELOOP: - case ENAMETOOLONG: - case ENOENT: - case ENOTDIR: - return ret; - } + /* An error occurred, and we are using O_EXCL. + Handle specific known errors directly. */ + switch (errno) + { + case EACCES: + case EEXIST: + case EINTR: + case EISDIR: + case ELOOP: + case ENAMETOOLONG: + case ENOENT: + case ENOTDIR: + return ret; + } - /* Retry with GUARDED semantics */ - if (stat(pathname, &filestat) != -1) - { - /* File exists */ - errno = EEXIST; - return -1; - } - else - { - return open(pathname, flags & ~O_EXCL, mode); - } + /* For other errors, assume it's due to O_EXCL not being supported + by the filesystem and retry without O_EXCL. */ + if (stat(pathname, &filestat) == 0) + { + /* File exists */ + errno = EEXIST; + return -1; + } + else if (errno == ENOENT) + { + /* File does not exist, retry without O_EXCL */ + return open(pathname, flags & ~O_EXCL, mode); + } + else + { + /* Some other error occurred */ + return -1; + } } -/* Enumeration of devices from rdesktop.c */ -/* returns number of units found and initialized. */ -/* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' */ -/* when it arrives to this function. */ -int -disk_enum_devices(uint32 * id, char *optarg) +/* Enumeration of devices from rdesktop.c + * returns number of units found and initialized. + * optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' + * when it arrives at this function. + */ +int disk_enum_devices(uint32 *id, char *optarg) { - char *pos = optarg; - char *pos2; - int count = 0; - DISK_DEVICE *pdisk_data; + char *pos = optarg; + char *pos2; + int count = 0; + DISK_DEVICE *pdisk_data; - /* skip the first colon */ - optarg++; - while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES) - { - pos2 = next_arg(optarg, '='); + /* skip the first colon */ + optarg++; + while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES) + { + pos2 = next_arg(optarg, '='); - pdisk_data = (DISK_DEVICE *) xmalloc(sizeof(DISK_DEVICE)); - memset(pdisk_data, 0, sizeof(DISK_DEVICE)); - strncpy(pdisk_data->name, optarg, sizeof(pdisk_data->name) - 1); - strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1); + pdisk_data = (DISK_DEVICE *)xmalloc(sizeof(DISK_DEVICE)); + memset(pdisk_data, 0, sizeof(DISK_DEVICE)); + strncpy(pdisk_data->name, optarg, sizeof(pdisk_data->name) - 1); + strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1); - g_rdpdr_device[*id].local_path = (char *) xmalloc(strlen(pos2) + 1); - strcpy(g_rdpdr_device[*id].local_path, pos2); - g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK; - g_rdpdr_device[*id].pdevice_data = (void *) pdisk_data; + g_rdpdr_device[*id].local_path = (char *)xmalloc(strlen(pos2) + 1); + strcpy(g_rdpdr_device[*id].local_path, pos2); + g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK; + g_rdpdr_device[*id].pdevice_data = (void *)pdisk_data; - count++; - (*id)++; + count++; + (*id)++; - optarg = pos; - } - return count; + optarg = pos; + } + return count; } /* Opens or creates a file or directory */ -static RD_NTSTATUS -disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition, - uint32 flags_and_attributes, char *filename, RD_NTHANDLE * phandle) +static RD_NTSTATUS disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, + uint32 create_disposition, uint32 flags_and_attributes, + char *filename, RD_NTHANDLE *phandle) { - int handle; - DIR *dirp; - int flags, mode; - char path[PATH_MAX]; - struct stat filestat; + int handle; + DIR *dirp; + int flags, mode; + char path[PATH_MAX]; + struct stat filestat; - logger(Disk, Debug, "disk_create(device_id=0x%x, accessmask=0x%x, sharemode=0x%x, " - "create_disp=%d, flags=0x%x, fname=%s, ...)", device_id, accessmask, - sharemode, create_disposition, flags_and_attributes, filename); - handle = 0; - dirp = NULL; - flags = 0; - mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + logger(Disk, Debug, "disk_create(device_id=0x%x, accessmask=0x%x, sharemode=0x%x, " + "create_disp=%d, flags=0x%x, fname=%s, ...)", + device_id, accessmask, sharemode, create_disposition, flags_and_attributes, filename); + handle = 0; + dirp = NULL; + flags = 0; + mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - if (filename && *filename && filename[strlen(filename) - 1] == '/') - filename[strlen(filename) - 1] = 0; + if (filename && *filename && filename[strlen(filename) - 1] == '/') + filename[strlen(filename) - 1] = 0; - sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename ? filename : ""); + snprintf(path, sizeof(path), "%s%s", g_rdpdr_device[device_id].local_path, filename ? filename : ""); - /* Protect against malicious servers: - somelongpath/.. not allowed - somelongpath/../b not allowed - somelongpath/..b in principle ok, but currently not allowed - somelongpath/b.. ok - somelongpath/b..b ok - somelongpath/b../c ok - */ - if (strstr(path, "/..")) - { - return RD_STATUS_ACCESS_DENIED; - } + /* Protect against malicious servers: + somelongpath/.. not allowed + somelongpath/../b not allowed + somelongpath/..b in principle ok, but currently not allowed + somelongpath/b.. ok + somelongpath/b..b ok + somelongpath/b../c ok + */ + if (strstr(path, "/..")) + { + return RD_STATUS_ACCESS_DENIED; + } - switch (create_disposition) - { - case CREATE_ALWAYS: + switch (create_disposition) + { + case CREATE_ALWAYS: + /* Delete existing file/link. */ + unlink(path); + flags |= O_CREAT; + break; - /* Delete existing file/link. */ - unlink(path); - flags |= O_CREAT; - break; + case CREATE_NEW: + /* If the file already exists, then fail. */ + flags |= O_CREAT | O_EXCL; + break; - case CREATE_NEW: + case OPEN_ALWAYS: + /* Create if not already exists. */ + flags |= O_CREAT; + break; - /* If the file already exists, then fail. */ - flags |= O_CREAT | O_EXCL; - break; + case OPEN_EXISTING: + /* Default behaviour */ + break; - case OPEN_ALWAYS: + case TRUNCATE_EXISTING: + /* If the file does not exist, then fail. */ + flags |= O_TRUNC; + break; + } - /* Create if not already exists. */ - flags |= O_CREAT; - break; + /*printf("Open: \"%s\" flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); */ - case OPEN_EXISTING: + /* Get information about file and set that flag ourselves */ + if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode))) + { + if (flags_and_attributes & FILE_NON_DIRECTORY_FILE) + return RD_STATUS_FILE_IS_A_DIRECTORY; + else + flags_and_attributes |= FILE_DIRECTORY_FILE; + } - /* Default behaviour */ - break; + if (flags_and_attributes & FILE_DIRECTORY_FILE) + { + if (flags & O_CREAT) + { + mkdir(path, mode); + } - case TRUNCATE_EXISTING: + dirp = opendir(path); + if (!dirp) + { + switch (errno) + { + case EACCES: + return RD_STATUS_ACCESS_DENIED; - /* If the file does not exist, then fail. */ - flags |= O_TRUNC; - break; - } + case ENOENT: + return RD_STATUS_NO_SUCH_FILE; - /*printf("Open: \"%s\" flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); */ + default: + logger(Disk, Error, "disk_create(), opendir() failed: %s", strerror(errno)); + return RD_STATUS_NO_SUCH_FILE; + } + } + handle = DIRFD(dirp); + } + else + { + if (accessmask & GENERIC_ALL || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE)) + { + flags |= O_RDWR; + } + else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ)) + { + flags |= O_WRONLY; + } + else + { + flags |= O_RDONLY; + } - /* Get information about file and set that flag ourselves */ - if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode))) - { - if (flags_and_attributes & FILE_NON_DIRECTORY_FILE) - return RD_STATUS_FILE_IS_A_DIRECTORY; - else - flags_and_attributes |= FILE_DIRECTORY_FILE; - } + handle = open_weak_exclusive(path, flags, mode); + if (handle == -1) + { + switch (errno) + { + case EISDIR: + return RD_STATUS_FILE_IS_A_DIRECTORY; - if (flags_and_attributes & FILE_DIRECTORY_FILE) - { - if (flags & O_CREAT) - { - mkdir(path, mode); - } + case EACCES: + return RD_STATUS_ACCESS_DENIED; - dirp = opendir(path); - if (!dirp) - { - switch (errno) - { - case EACCES: + case ENOENT: + return RD_STATUS_NO_SUCH_FILE; + case EEXIST: + return RD_STATUS_OBJECT_NAME_COLLISION; + default: + logger(Disk, Error, "disk_create(), open() failed: %s", strerror(errno)); + return RD_STATUS_NO_SUCH_FILE; + } + } - return RD_STATUS_ACCESS_DENIED; + /* all read and writes of files should be non-blocking */ + if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1) + logger(Disk, Error, "disk_create(), fcntl() failed: %s", strerror(errno)); + } - case ENOENT: + if (handle >= MAX_OPEN_FILES) + { + logger(Disk, Error, + "disk_create(), handle (%d) is greater than or equal to MAX_OPEN_FILES (%d)!", + handle, MAX_OPEN_FILES); + exit(EX_SOFTWARE); + } - return RD_STATUS_NO_SUCH_FILE; + if (dirp) + g_fileinfo[handle].pdir = dirp; + else + g_fileinfo[handle].pdir = NULL; - default: - logger(Disk, Error, "disk_create(), opendir() failed: %s", - strerror(errno)); - return RD_STATUS_NO_SUCH_FILE; - } - } - handle = DIRFD(dirp); - } - else - { + g_fileinfo[handle].device_id = device_id; + g_fileinfo[handle].flags_and_attributes = flags_and_attributes; + g_fileinfo[handle].accessmask = accessmask; + strncpy(g_fileinfo[handle].path, path, PATH_MAX - 1); + g_fileinfo[handle].delete_on_close = False; - if (accessmask & GENERIC_ALL - || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE)) - { - flags |= O_RDWR; - } - else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ)) - { - flags |= O_WRONLY; - } - else - { - flags |= O_RDONLY; - } + if (accessmask & GENERIC_ALL || accessmask & GENERIC_WRITE) + g_notify_stamp = True; - handle = open_weak_exclusive(path, flags, mode); - if (handle == -1) - { - switch (errno) - { - case EISDIR: - - return RD_STATUS_FILE_IS_A_DIRECTORY; - - case EACCES: - - return RD_STATUS_ACCESS_DENIED; - - case ENOENT: - - return RD_STATUS_NO_SUCH_FILE; - case EEXIST: - - return RD_STATUS_OBJECT_NAME_COLLISION; - default: - logger(Disk, Error, "disk_create(), open() failed: %s", - strerror(errno)); - return RD_STATUS_NO_SUCH_FILE; - } - } - - /* all read and writes of files should be non blocking */ - if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1) - logger(Disk, Error, "disk_create(), fcntl() failed: %s", strerror(errno)); - - } - - if (handle >= MAX_OPEN_FILES) - { - logger(Disk, Error, - "disk_create(), handle (%d) is greater than or equal to MAX_OPEN_FILES (%d)!", - handle, MAX_OPEN_FILES); - exit(EX_SOFTWARE); - } - - if (dirp) - g_fileinfo[handle].pdir = dirp; - else - g_fileinfo[handle].pdir = NULL; - - g_fileinfo[handle].device_id = device_id; - g_fileinfo[handle].flags_and_attributes = flags_and_attributes; - g_fileinfo[handle].accessmask = accessmask; - strncpy(g_fileinfo[handle].path, path, PATH_MAX - 1); - g_fileinfo[handle].delete_on_close = False; - - if (accessmask & GENERIC_ALL || accessmask & GENERIC_WRITE) - g_notify_stamp = True; - - *phandle = handle; - return RD_STATUS_SUCCESS; + *phandle = handle; + return RD_STATUS_SUCCESS; } -static RD_NTSTATUS -disk_close(RD_NTHANDLE handle) +static RD_NTSTATUS disk_close(RD_NTHANDLE handle) { - struct fileinfo *pfinfo; + struct fileinfo *pfinfo; - logger(Disk, Debug, "disk_close(handle=0x%x)", handle); + logger(Disk, Debug, "disk_close(handle=0x%x)", handle); - pfinfo = &(g_fileinfo[handle]); + pfinfo = &(g_fileinfo[handle]); - if (pfinfo->accessmask & GENERIC_ALL || pfinfo->accessmask & GENERIC_WRITE) - g_notify_stamp = True; + if (pfinfo->accessmask & GENERIC_ALL || pfinfo->accessmask & GENERIC_WRITE) + g_notify_stamp = True; - rdpdr_abort_io(handle, 0, RD_STATUS_CANCELLED); + rdpdr_abort_io(handle, 0, RD_STATUS_CANCELLED); - if (pfinfo->pdir) - { - if (closedir(pfinfo->pdir) < 0) - { - logger(Disk, Error, "disk_close(), closedir() failed: %s", strerror(errno)); - return RD_STATUS_INVALID_HANDLE; - } + if (pfinfo->pdir) + { + if (closedir(pfinfo->pdir) < 0) + { + logger(Disk, Error, "disk_close(), closedir() failed: %s", strerror(errno)); + return RD_STATUS_INVALID_HANDLE; + } - if (pfinfo->delete_on_close) - if (rmdir(pfinfo->path) < 0) - { - logger(Disk, Error, "disk_close(), rmdir() failed: %s", - strerror(errno)); - return RD_STATUS_ACCESS_DENIED; - } - pfinfo->delete_on_close = False; - } - else - { - if (close(handle) < 0) - { - logger(Disk, Error, "disk_close(), close() failed: %s", strerror(errno)); - return RD_STATUS_INVALID_HANDLE; - } - if (pfinfo->delete_on_close) - if (unlink(pfinfo->path) < 0) - { - logger(Disk, Error, "disk_close(), unlink() failed: %s", - strerror(errno)); - return RD_STATUS_ACCESS_DENIED; - } + if (pfinfo->delete_on_close) + if (rmdir(pfinfo->path) < 0) + { + logger(Disk, Error, "disk_close(), rmdir() failed: %s", strerror(errno)); + return RD_STATUS_ACCESS_DENIED; + } + pfinfo->delete_on_close = False; + } + else + { + if (close(handle) < 0) + { + logger(Disk, Error, "disk_close(), close() failed: %s", strerror(errno)); + return RD_STATUS_INVALID_HANDLE; + } + if (pfinfo->delete_on_close) + if (unlink(pfinfo->path) < 0) + { + logger(Disk, Error, "disk_close(), unlink() failed: %s", strerror(errno)); + return RD_STATUS_ACCESS_DENIED; + } - pfinfo->delete_on_close = False; - } + pfinfo->delete_on_close = False; + } - return RD_STATUS_SUCCESS; + return RD_STATUS_SUCCESS; } -static RD_NTSTATUS -disk_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint64 offset, uint32 * result) +static RD_NTSTATUS disk_read(RD_NTHANDLE handle, uint8 *data, uint32 length, uint64 offset, uint32 *result) { - int n; + int n; #if 0 - /* browsing dir ???? */ - /* each request is 24 bytes */ - if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE) - { - *result = 0; - return STATUS_SUCCESS; - } + /* browsing dir ???? */ + /* each request is 24 bytes */ + if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE) + { + *result = 0; + return STATUS_SUCCESS; + } #endif - lseek(handle, offset, SEEK_SET); + lseek(handle, offset, SEEK_SET); - n = read(handle, data, length); + n = read(handle, data, length); - if (n < 0) - { - *result = 0; - switch (errno) - { - case EISDIR: - /* Implement 24 Byte directory read ?? - with STATUS_NOT_IMPLEMENTED server doesn't read again */ - /* return STATUS_FILE_IS_A_DIRECTORY; */ - return RD_STATUS_NOT_IMPLEMENTED; - default: - logger(Disk, Error, "disk_read(), read failed: %s", - strerror(errno)); - return RD_STATUS_INVALID_PARAMETER; - } - } + if (n < 0) + { + *result = 0; + switch (errno) + { + case EISDIR: + /* Implement 24 Byte directory read ?? + with STATUS_NOT_IMPLEMENTED server doesn't read again */ + /* return STATUS_FILE_IS_A_DIRECTORY; */ + return RD_STATUS_NOT_IMPLEMENTED; + default: + logger(Disk, Error, "disk_read(), read failed: %s", strerror(errno)); + return RD_STATUS_INVALID_PARAMETER; + } + } - *result = n; + *result = n; - return RD_STATUS_SUCCESS; + return RD_STATUS_SUCCESS; } -static RD_NTSTATUS -disk_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint64 offset, uint32 * result) +static RD_NTSTATUS disk_write(RD_NTHANDLE handle, uint8 *data, uint32 length, uint64 offset, uint32 *result) { - int n; + int n; - lseek(handle, offset, SEEK_SET); + lseek(handle, offset, SEEK_SET); - n = write(handle, data, length); + n = write(handle, data, length); - if (n < 0) - { - logger(Disk, Error, "disk_write(), write() failed: %s", strerror(errno)); - *result = 0; - switch (errno) - { - case ENOSPC: - return RD_STATUS_DISK_FULL; - default: - return RD_STATUS_ACCESS_DENIED; - } - } + if (n < 0) + { + logger(Disk, Error, "disk_write(), write() failed: %s", strerror(errno)); + *result = 0; + switch (errno) + { + case ENOSPC: + return RD_STATUS_DISK_FULL; + default: + return RD_STATUS_ACCESS_DENIED; + } + } - *result = n; + *result = n; - return RD_STATUS_SUCCESS; + return RD_STATUS_SUCCESS; } -/* Btw, all used Flie* structures are described in [MS-FSCC] */ -RD_NTSTATUS -disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out) +/* Btw, all used File* structures are described in [MS-FSCC] */ +RD_NTSTATUS disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out) { - uint32 file_attributes, ft_high, ft_low; - struct stat filestat; - char *path, *filename; + uint32 file_attributes, ft_high, ft_low; + struct stat filestat; + char *path, *filename; - logger(Disk, Debug, "disk_query_information(handle=0x%x, info_class=0x%x)", handle, - info_class); + logger(Disk, Debug, "disk_query_information(handle=0x%x, info_class=0x%x)", handle, info_class); - path = g_fileinfo[handle].path; + path = g_fileinfo[handle].path; - /* Get information about file */ - if (fstat(handle, &filestat) != 0) - { - logger(Disk, Error, "disk_query_information(), stat() failed: %s", strerror(errno)); - out_uint8(out, 0); - return RD_STATUS_ACCESS_DENIED; - } + /* Get information about file */ + if (fstat(handle, &filestat) != 0) + { + logger(Disk, Error, "disk_query_information(), stat() failed: %s", strerror(errno)); + out_uint8(out, 0); + return RD_STATUS_ACCESS_DENIED; + } - /* Set file attributes */ - file_attributes = 0; - if (S_ISDIR(filestat.st_mode)) - file_attributes |= FILE_ATTRIBUTE_DIRECTORY; + /* Set file attributes */ + file_attributes = 0; + if (S_ISDIR(filestat.st_mode)) + file_attributes |= FILE_ATTRIBUTE_DIRECTORY; - filename = strrchr(path, '/'); - if (filename) - filename += 1; + filename = strrchr(path, '/'); + if (filename) + filename += 1; - if (filename && filename[0] == '.') - file_attributes |= FILE_ATTRIBUTE_HIDDEN; + if (filename && filename[0] == '.') + file_attributes |= FILE_ATTRIBUTE_HIDDEN; - if (!file_attributes) - file_attributes |= FILE_ATTRIBUTE_NORMAL; + if (!file_attributes) + file_attributes |= FILE_ATTRIBUTE_NORMAL; - if (!(filestat.st_mode & S_IWUSR)) - file_attributes |= FILE_ATTRIBUTE_READONLY; + if (!(filestat.st_mode & S_IWUSR)) + file_attributes |= FILE_ATTRIBUTE_READONLY; - /* Return requested data */ - switch (info_class) - { - case FileBasicInformation: - seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, - &ft_low); - out_uint32_le(out, ft_low); /* create_access_time */ - out_uint32_le(out, ft_high); + /* Return requested data */ + switch (info_class) + { + case FileBasicInformation: + seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* create_access_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_access_time */ - out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_access_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_write_time */ - out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_write_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_change_time */ - out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_change_time */ + out_uint32_le(out, ft_high); - out_uint32_le(out, file_attributes); - break; + out_uint32_le(out, file_attributes); + break; - case FileStandardInformation: + case FileStandardInformation: + out_uint64_le(out, filestat.st_size); /* Allocation size */ + out_uint64_le(out, filestat.st_size); /* End of file */ - out_uint64_le(out, filestat.st_size); /* Allocation size */ - out_uint64_le(out, filestat.st_size); /* End of file */ + out_uint32_le(out, filestat.st_nlink); /* Number of links */ + out_uint8(out, 0); /* Delete pending */ + out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); /* Directory */ + break; - out_uint32_le(out, filestat.st_nlink); /* Number of links */ - out_uint8(out, 0); /* Delete pending */ - out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); /* Directory */ - break; + case FileObjectIdInformation: + out_uint32_le(out, file_attributes); /* File Attributes */ + out_uint32_le(out, 0); /* Reparse Tag */ + break; - case FileObjectIdInformation: - - out_uint32_le(out, file_attributes); /* File Attributes */ - out_uint32_le(out, 0); /* Reparse Tag */ - break; - - default: - logger(Disk, Warning, - "disk_query_information(), unhandled query information class 0x%x", - info_class); - return RD_STATUS_INVALID_PARAMETER; - } - return RD_STATUS_SUCCESS; + default: + logger(Disk, Warning, + "disk_query_information(), unhandled query information class 0x%x", + info_class); + return RD_STATUS_INVALID_PARAMETER; + } + return RD_STATUS_SUCCESS; } /* 2.2.3.3.9 [MS-RDPEFS] */ -RD_NTSTATUS -disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out) +RD_NTSTATUS disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out) { - UNUSED(out); - uint32 length, file_attributes, ft_high, ft_low; - char *newname, fullpath[PATH_MAX]; - struct fileinfo *pfinfo; - int mode; - struct stat filestat; - time_t write_time, change_time, access_time, mod_time; - struct utimbuf tvs; - struct STATFS_T stat_fs; + UNUSED(out); + uint32 length, file_attributes, ft_high, ft_low; + char *newname, fullpath[PATH_MAX]; + struct fileinfo *pfinfo; + int mode; + struct stat filestat; + time_t write_time, change_time, access_time, mod_time; + struct utimbuf tvs; + struct STATFS_T stat_fs; - logger(Disk, Debug, "disk_set_information(handle=0x%x, info_class=0x%x, ...)", handle, - info_class); + logger(Disk, Debug, "disk_set_information(handle=0x%x, info_class=0x%x, ...)", handle, info_class); - pfinfo = &(g_fileinfo[handle]); - g_notify_stamp = True; - newname = NULL; + pfinfo = &(g_fileinfo[handle]); + g_notify_stamp = True; + newname = NULL; - switch (info_class) - { - case FileBasicInformation: - write_time = change_time = access_time = 0; + switch (info_class) + { + case FileBasicInformation: + write_time = change_time = access_time = 0; - in_uint8s(in, 4); /* length of SetBuffer */ - in_uint8s(in, 24); /* padding */ + in_uint8s(in, 4); /* length of SetBuffer */ + in_uint8s(in, 24); /* padding */ - /* CreationTime */ - in_uint32_le(in, ft_low); - in_uint32_le(in, ft_high); + /* CreationTime */ + in_uint32_le(in, ft_low); + in_uint32_le(in, ft_high); - /* AccessTime */ - in_uint32_le(in, ft_low); - in_uint32_le(in, ft_high); - if (ft_low || ft_high) - access_time = convert_1970_to_filetime(ft_high, ft_low); + /* AccessTime */ + in_uint32_le(in, ft_low); + in_uint32_le(in, ft_high); + if (ft_low || ft_high) + access_time = convert_1970_to_filetime(ft_high, ft_low); - /* WriteTime */ - in_uint32_le(in, ft_low); - in_uint32_le(in, ft_high); - if (ft_low || ft_high) - write_time = convert_1970_to_filetime(ft_high, ft_low); + /* WriteTime */ + in_uint32_le(in, ft_low); + in_uint32_le(in, ft_high); + if (ft_low || ft_high) + write_time = convert_1970_to_filetime(ft_high, ft_low); - /* ChangeTime */ - in_uint32_le(in, ft_low); - in_uint32_le(in, ft_high); - if (ft_low || ft_high) - change_time = convert_1970_to_filetime(ft_high, ft_low); + /* ChangeTime */ + in_uint32_le(in, ft_low); + in_uint32_le(in, ft_high); + if (ft_low || ft_high) + change_time = convert_1970_to_filetime(ft_high, ft_low); - in_uint32_le(in, file_attributes); + in_uint32_le(in, file_attributes); - if (fstat(handle, &filestat)) - return RD_STATUS_ACCESS_DENIED; + if (fstat(handle, &filestat)) + return RD_STATUS_ACCESS_DENIED; - tvs.modtime = filestat.st_mtime; - tvs.actime = filestat.st_atime; - if (access_time) - tvs.actime = access_time; + tvs.modtime = filestat.st_mtime; + tvs.actime = filestat.st_atime; + if (access_time) + tvs.actime = access_time; + if (write_time || change_time) + mod_time = MIN(write_time, change_time); + else + mod_time = write_time ? write_time : change_time; - if (write_time || change_time) - mod_time = MIN(write_time, change_time); - else - mod_time = write_time ? write_time : change_time; + if (mod_time) + tvs.modtime = mod_time; - if (mod_time) - tvs.modtime = mod_time; + if (access_time || write_time || change_time) + { + logger(Disk, Debug, + "disk_set_information(), access time='%s', modify time='%s'", + ctime(&tvs.actime), ctime(&tvs.modtime)); + if (utime(pfinfo->path, &tvs) && errno != EPERM) + return RD_STATUS_ACCESS_DENIED; + } + if (!file_attributes) + break; /* not valid */ - if (access_time || write_time || change_time) - { - logger(Disk, Debug, - "disk_set_information(), access time='%s', modify time='%s'", - ctime(&tvs.actime), ctime(&tvs.modtime)); - if (utime(pfinfo->path, &tvs) && errno != EPERM) - return RD_STATUS_ACCESS_DENIED; - } + mode = filestat.st_mode; - if (!file_attributes) - break; /* not valid */ + if (file_attributes & FILE_ATTRIBUTE_READONLY) + mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + else + mode |= S_IWUSR; - mode = filestat.st_mode; + mode &= 0777; - if (file_attributes & FILE_ATTRIBUTE_READONLY) - mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - else - mode |= S_IWUSR; + logger(Disk, Debug, "disk_set_information(), access mode 0%o", mode); - mode &= 0777; + if (fchmod(handle, mode)) + return RD_STATUS_ACCESS_DENIED; - logger(Disk, Debug, "disk_set_information(), access mode 0%o", mode); + break; - if (fchmod(handle, mode)) - return RD_STATUS_ACCESS_DENIED; + case FileRenameInformation: + in_uint8s(in, 4); /* Handle of root dir? */ + in_uint8s(in, 0x1a); /* unknown */ + in_uint32_le(in, length); - break; + if (length && (length / 2) >= 256) + return RD_STATUS_INVALID_PARAMETER; - case FileRenameInformation: + rdp_in_unistr(in, length, &newname, &length); + if (newname == NULL) + return RD_STATUS_INVALID_PARAMETER; - in_uint8s(in, 4); /* Handle of root dir? */ - in_uint8s(in, 0x1a); /* unknown */ - in_uint32_le(in, length); + convert_to_unix_filename(newname); - if (length && (length / 2) >= 256) - return RD_STATUS_INVALID_PARAMETER; + snprintf(fullpath, sizeof(fullpath), "%s%s", g_rdpdr_device[pfinfo->device_id].local_path, newname); - rdp_in_unistr(in, length, &newname, &length); - if (newname == NULL) - return RD_STATUS_INVALID_PARAMETER; + free(newname); - convert_to_unix_filename(newname); + if (rename(pfinfo->path, fullpath) != 0) + { + logger(Disk, Error, "disk_set_information(), rename() failed: %s", strerror(errno)); + return RD_STATUS_ACCESS_DENIED; + } + break; - sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path, - newname); + case FileDispositionInformation: + /* As far as I understand it, the correct + thing to do here is to *schedule* a delete, + so it will be deleted when the file is + closed. Subsequent + FileDispositionInformation requests with + DeleteFile set to FALSE should unschedule + the delete. See + http://www.osronline.com/article.cfm?article=245. */ - free(newname); + /* FileDispositionInformation always sets delete_on_close to true. + "STREAM in" includes Length(4bytes) , Padding(24bytes) and SetBuffer(zero byte). + Length is always set to zero. + [MS-RDPEFS] http://msdn.microsoft.com/en-us/library/cc241305%28PROT.10%29.aspx + - 2.2.3.3.9 Server Drive Set Information Request + - 2.2.3.4.9 Client Drive Set Information Response + [MS-FSCC] http://msdn.microsoft.com/en-us/library/cc231987%28PROT.10%29.aspx + - 2.4.11 FileDispositionInformation + [FSBO] http://msdn.microsoft.com/en-us/library/cc246487%28PROT.13%29.aspx + - 4.3.2 Set Delete-on-close using FileDispositionInformation Information Class (IRP_MJ_SET_INFORMATION) + */ + in_uint8s(in, 4); /* length of SetBuffer */ + in_uint8s(in, 24); /* padding */ - if (rename(pfinfo->path, fullpath) != 0) - { - logger(Disk, Error, "disk_set_information(), rename() failed: %s", - strerror(errno)); - return RD_STATUS_ACCESS_DENIED; - } - break; + if ((pfinfo->accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED))) + { + /* if file exists in directory, necessary to return RD_STATUS_DIRECTORY_NOT_EMPTY with win2008 + [MS-RDPEFS] http://msdn.microsoft.com/en-us/library/cc241305%28PROT.10%29.aspx + - 2.2.3.3.9 Server Drive Set Information Request + - 2.2.3.4.9 Client Drive Set Information Response + [MS-FSCC] http://msdn.microsoft.com/en-us/library/cc231987%28PROT.10%29.aspx + - 2.4.11 FileDispositionInformation + [FSBO] http://msdn.microsoft.com/en-us/library/cc246487%28PROT.13%29.aspx + - 4.3.2 Set Delete-on-close using FileDispositionInformation Information Class (IRP_MJ_SET_INFORMATION) + */ + if (pfinfo->pdir) + { + DIR *dp = opendir(pfinfo->path); + struct dirent *dir; - case FileDispositionInformation: - /* As far as I understand it, the correct - thing to do here is to *schedule* a delete, - so it will be deleted when the file is - closed. Subsequent - FileDispositionInformation requests with - DeleteFile set to FALSE should unschedule - the delete. See - http://www.osronline.com/article.cfm?article=245. */ + while ((dir = readdir(dp)) != NULL) + { + if (strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0) + { + closedir(dp); + return RD_STATUS_DIRECTORY_NOT_EMPTY; + } + } + closedir(dp); + } - /* FileDispositionInformation always sets delete_on_close to true. - "STREAM in" includes Length(4bytes) , Padding(24bytes) and SetBuffer(zero byte). - Length is always set to zero. - [MS-RDPEFS] http://msdn.microsoft.com/en-us/library/cc241305%28PROT.10%29.aspx - - 2.2.3.3.9 Server Drive Set Information Request - */ - in_uint8s(in, 4); /* length of SetBuffer */ - in_uint8s(in, 24); /* padding */ + pfinfo->delete_on_close = True; + } + break; - if ((pfinfo->accessmask & - (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED))) - { - /* if file exists in directory , necessary to return RD_STATUS_DIRECTORY_NOT_EMPTY with win2008 - [MS-RDPEFS] http://msdn.microsoft.com/en-us/library/cc241305%28PROT.10%29.aspx - - 2.2.3.3.9 Server Drive Set Information Request - - 2.2.3.4.9 Client Drive Set Information Response - [MS-FSCC] http://msdn.microsoft.com/en-us/library/cc231987%28PROT.10%29.aspx - - 2.4.11 FileDispositionInformation - [FSBO] http://msdn.microsoft.com/en-us/library/cc246487%28PROT.13%29.aspx - - 4.3.2 Set Delete-on-close using FileDispositionInformation Information Class (IRP_MJ_SET_INFORMATION) - */ - if (pfinfo->pdir) - { - DIR *dp = opendir(pfinfo->path); - struct dirent *dir; + case FileAllocationInformation: + /* Fall through to FileEndOfFileInformation, + which uses ftrunc. This is like Samba with + "strict allocation = false", and means that + we won't detect out-of-quota errors, for + example. */ - while ((dir = readdir(dp)) != NULL) - { - if (strcmp(dir->d_name, ".") != 0 - && strcmp(dir->d_name, "..") != 0) - { - closedir(dp); - return RD_STATUS_DIRECTORY_NOT_EMPTY; - } - } - closedir(dp); - } + case FileEndOfFileInformation: + in_uint8s(in, 28); /* unknown */ + in_uint32_le(in, length); /* file size */ - pfinfo->delete_on_close = True; - } + /* prevents start of writing if not enough space left on device */ + if (STATFS_FN(pfinfo->path, &stat_fs) == 0) + if (stat_fs.f_bfree * stat_fs.f_bsize < length) + return RD_STATUS_DISK_FULL; - break; + if (ftruncate_growable(handle, length) != 0) + { + return RD_STATUS_DISK_FULL; + } - case FileAllocationInformation: - /* Fall through to FileEndOfFileInformation, - which uses ftrunc. This is like Samba with - "strict allocation = false", and means that - we won't detect out-of-quota errors, for - example. */ - - case FileEndOfFileInformation: - in_uint8s(in, 28); /* unknown */ - in_uint32_le(in, length); /* file size */ - - /* prevents start of writing if not enough space left on device */ - if (STATFS_FN(pfinfo->path, &stat_fs) == 0) - if (stat_fs.f_bfree * stat_fs.f_bsize < length) - return RD_STATUS_DISK_FULL; - - if (ftruncate_growable(handle, length) != 0) - { - return RD_STATUS_DISK_FULL; - } - - break; - default: - logger(Disk, Warning, - "disk_set_information(), unhandled information class 0x%x", - info_class); - return RD_STATUS_INVALID_PARAMETER; - } - return RD_STATUS_SUCCESS; + break; + default: + logger(Disk, Warning, + "disk_set_information(), unhandled information class 0x%x", + info_class); + return RD_STATUS_INVALID_PARAMETER; + } + return RD_STATUS_SUCCESS; } -RD_NTSTATUS -disk_check_notify(RD_NTHANDLE handle) +RD_NTSTATUS disk_check_notify(RD_NTHANDLE handle) { - struct fileinfo *pfinfo; - RD_NTSTATUS status = RD_STATUS_PENDING; - NOTIFY notify; + struct fileinfo *pfinfo; + RD_NTSTATUS status = RD_STATUS_PENDING; + NOTIFY notify; - logger(Disk, Debug, "disk_check_notify(handle=0x%x)", handle); + logger(Disk, Debug, "disk_check_notify(handle=0x%x)", handle); - pfinfo = &(g_fileinfo[handle]); - if (!pfinfo->pdir) - return RD_STATUS_INVALID_DEVICE_REQUEST; + pfinfo = &(g_fileinfo[handle]); + if (!pfinfo->pdir) + return RD_STATUS_INVALID_DEVICE_REQUEST; + status = NotifyInfo(handle, pfinfo->info_class, ¬ify); + if (status != RD_STATUS_PENDING) + return status; - status = NotifyInfo(handle, pfinfo->info_class, ¬ify); - - if (status != RD_STATUS_PENDING) - return status; - - if (memcmp(&pfinfo->notify, ¬ify, sizeof(NOTIFY))) - { - /*printf("disk_check_notify found changed event\n"); */ - memcpy(&pfinfo->notify, ¬ify, sizeof(NOTIFY)); - status = RD_STATUS_NOTIFY_ENUM_DIR; - } - - return status; - + if (memcmp(&pfinfo->notify, ¬ify, sizeof(NOTIFY))) + { + /*printf("disk_check_notify found changed event\n"); */ + memcpy(&pfinfo->notify, ¬ify, sizeof(NOTIFY)); + status = RD_STATUS_NOTIFY_ENUM_DIR; + } + return status; } -RD_NTSTATUS -disk_create_notify(RD_NTHANDLE handle, uint32 info_class) +RD_NTSTATUS disk_create_notify(RD_NTHANDLE handle, uint32 info_class) { - struct fileinfo *pfinfo; - RD_NTSTATUS ret = RD_STATUS_PENDING; + struct fileinfo *pfinfo; + RD_NTSTATUS ret = RD_STATUS_PENDING; - logger(Disk, Debug, "disk_create_notify(handle=0x%x, info_class=0x%x)", handle, info_class); + logger(Disk, Debug, "disk_create_notify(handle=0x%x, info_class=0x%x)", handle, info_class); - pfinfo = &(g_fileinfo[handle]); - pfinfo->info_class = info_class; + pfinfo = &(g_fileinfo[handle]); + pfinfo->info_class = info_class; - ret = NotifyInfo(handle, info_class, &pfinfo->notify); + ret = NotifyInfo(handle, info_class, &pfinfo->notify); - if (info_class & 0x1000) - { /* ???? */ - if (ret == RD_STATUS_PENDING) - return RD_STATUS_SUCCESS; - } + if (info_class & 0x1000) + { /* ???? */ + if (ret == RD_STATUS_PENDING) + return RD_STATUS_SUCCESS; + } - /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */ - - - return ret; + /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */ + return ret; } -static RD_NTSTATUS -NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY * p) +static RD_NTSTATUS NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY *p) { - UNUSED(info_class); - struct fileinfo *pfinfo; - struct stat filestat; - struct dirent *dp; - char *fullname; - DIR *dpr; + UNUSED(info_class); + struct fileinfo *pfinfo; + struct stat filestat; + struct dirent *dp; + char *fullname; + DIR *dpr; - pfinfo = &(g_fileinfo[handle]); - if (fstat(handle, &filestat) < 0) - { - logger(Disk, Error, "NotifyInfo(), fstat failed: %s", strerror(errno)); - return RD_STATUS_ACCESS_DENIED; - } - p->modify_time = filestat.st_mtime; - p->status_time = filestat.st_ctime; - p->num_entries = 0; - p->total_time = 0; + pfinfo = &(g_fileinfo[handle]); + if (fstat(handle, &filestat) < 0) + { + logger(Disk, Error, "NotifyInfo(), fstat failed: %s", strerror(errno)); + return RD_STATUS_ACCESS_DENIED; + } + p->modify_time = filestat.st_mtime; + p->status_time = filestat.st_ctime; + p->num_entries = 0; + p->total_time = 0; + dpr = opendir(pfinfo->path); + if (!dpr) + { + logger(Disk, Error, "NotifyInfo(), opendir failed: %s", strerror(errno)); + return RD_STATUS_ACCESS_DENIED; + } - dpr = opendir(pfinfo->path); - if (!dpr) - { - logger(Disk, Error, "NotifyInfo(), opendir failed: %s", strerror(errno)); - return RD_STATUS_ACCESS_DENIED; - } + while ((dp = readdir(dpr))) + { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + p->num_entries++; + fullname = (char *)xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2); + sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name); + if (!stat(fullname, &filestat)) + { + p->total_time += (filestat.st_mtime + filestat.st_ctime); + } - while ((dp = readdir(dpr))) - { - if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) - continue; - p->num_entries++; - fullname = (char *) xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2); - sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name); + xfree(fullname); + } + closedir(dpr); - if (!stat(fullname, &filestat)) - { - p->total_time += (filestat.st_mtime + filestat.st_ctime); - } - - xfree(fullname); - } - closedir(dpr); - - return RD_STATUS_PENDING; + return RD_STATUS_PENDING; } -static FsInfoType * -FsVolumeInfo(char *fpath) +static FsInfoType *FsVolumeInfo(char *fpath) { - - static FsInfoType info; + static FsInfoType info; #ifdef USE_SETMNTENT - FILE *fdfs; - struct mntent *e; + FILE *fdfs; + struct mntent *e; #endif - /* initialize */ - memset(&info, 0, sizeof(info)); - strcpy(info.label, "RDESKTOP"); - strcpy(info.type, "RDPFS"); + /* initialize */ + memset(&info, 0, sizeof(info)); + strcpy(info.label, "RDESKTOP"); + strcpy(info.type, "RDPFS"); #ifdef USE_SETMNTENT - fdfs = setmntent(MNTENT_PATH, "r"); - if (!fdfs) - return &info; + fdfs = setmntent(MNTENT_PATH, "r"); + if (!fdfs) + return &info; - while ((e = getmntent(fdfs))) - { - if (str_startswith(e->mnt_dir, fpath)) - { - strcpy(info.type, e->mnt_type); - strcpy(info.name, e->mnt_fsname); - if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660")) - { - int fd = open(e->mnt_fsname, O_RDONLY); - if (fd >= 0) - { - unsigned char buf[512]; - memset(buf, 0, sizeof(buf)); - if (strstr(e->mnt_opts, "vfat")) - /*FAT*/ - { - strcpy(info.type, "vfat"); - read(fd, buf, sizeof(buf)); - info.serial = - (buf[42] << 24) + (buf[41] << 16) + - (buf[40] << 8) + buf[39]; - strncpy(info.label, (char *) buf + 43, 10); - info.label[10] = '\0'; - } - else if (lseek(fd, 32767, SEEK_SET) >= 0) /* ISO9660 */ - { - read(fd, buf, sizeof(buf)); - strncpy(info.label, (char *) buf + 41, 32); - info.label[32] = '\0'; - /* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */ - } - close(fd); - } - } - } - } - endmntent(fdfs); + while ((e = getmntent(fdfs))) + { + if (str_startswith(e->mnt_dir, fpath)) + { + strcpy(info.type, e->mnt_type); + strcpy(info.name, e->mnt_fsname); + if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660")) + { + int fd = open(e->mnt_fsname, O_RDONLY); + if (fd >= 0) + { + unsigned char buf[512]; + memset(buf, 0, sizeof(buf)); + if (strstr(e->mnt_opts, "vfat")) + { + /*FAT*/ + strcpy(info.type, "vfat"); + read(fd, buf, sizeof(buf)); + info.serial = (buf[42] << 24) + (buf[41] << 16) + (buf[40] << 8) + buf[39]; + strncpy(info.label, (char *)buf + 43, 10); + info.label[10] = '\0'; + } + else if (lseek(fd, 32767, SEEK_SET) >= 0) + { /* ISO9660 */ + read(fd, buf, sizeof(buf)); + strncpy(info.label, (char *)buf + 41, 32); + info.label[32] = '\0'; + /* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */ + } + close(fd); + } + } + } + } + endmntent(fdfs); #else - /* initialize */ - memset(&info, 0, sizeof(info)); - strcpy(info.label, "RDESKTOP"); - strcpy(info.type, "RDPFS"); + /* initialize */ + memset(&info, 0, sizeof(info)); + strcpy(info.label, "RDESKTOP"); + strcpy(info.type, "RDPFS"); #endif - return &info; + return &info; } - -RD_NTSTATUS -disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out) +RD_NTSTATUS disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out) { - struct STATFS_T stat_fs; - struct fileinfo *pfinfo; - FsInfoType *fsinfo; - STREAM stmp; + struct STATFS_T stat_fs; + struct fileinfo *pfinfo; + FsInfoType *fsinfo; + STREAM stmp; - logger(Disk, Debug, "disk_query_volume_information(handle=0x%x, info_class=0x%x)", handle, - info_class); + logger(Disk, Debug, "disk_query_volume_information(handle=0x%x, info_class=0x%x)", handle, info_class); - pfinfo = &(g_fileinfo[handle]); + pfinfo = &(g_fileinfo[handle]); - if (STATFS_FN(pfinfo->path, &stat_fs) != 0) - { - logger(Disk, Error, "disk_query_volume_information(), statfs() failed: %s", - strerror(errno)); - return RD_STATUS_ACCESS_DENIED; - } + if (STATFS_FN(pfinfo->path, &stat_fs) != 0) + { + logger(Disk, Error, "disk_query_volume_information(), statfs() failed: %s", strerror(errno)); + return RD_STATUS_ACCESS_DENIED; + } - fsinfo = FsVolumeInfo(pfinfo->path); + fsinfo = FsVolumeInfo(pfinfo->path); - switch (info_class) - { - case FileFsVolumeInformation: - stmp = s_alloc(PATH_MAX * 4); - out_utf16s(stmp, fsinfo->label); - s_mark_end(stmp); + switch (info_class) + { + case FileFsVolumeInformation: + stmp = s_alloc(PATH_MAX * 4); + out_utf16s(stmp, fsinfo->label); + s_mark_end(stmp); - out_uint32_le(out, 0); /* volume creation time low */ - out_uint32_le(out, 0); /* volume creation time high */ - out_uint32_le(out, fsinfo->serial); /* serial */ - out_uint32_le(out, s_length(stmp)); /* length of string */ - out_uint8(out, 0); /* support objects? */ - out_stream(out, stmp); /* fsinfo->label string */ - s_free(stmp); - break; + out_uint32_le(out, 0); /* volume creation time low */ + out_uint32_le(out, 0); /* volume creation time high */ + out_uint32_le(out, fsinfo->serial); /* serial */ + out_uint32_le(out, s_length(stmp)); /* length of string */ + out_uint8(out, 0); /* support objects? */ + out_stream(out, stmp); /* fsinfo->label string */ + s_free(stmp); + break; - case FileFsSizeInformation: + case FileFsSizeInformation: + out_uint64_le(out, stat_fs.f_blocks); /* Total allocation units */ + out_uint64_le(out, stat_fs.f_bfree); /* Available allocation units */ + out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */ + out_uint32_le(out, 0x200); /* Bytes per sector */ + break; - out_uint64_le(out, stat_fs.f_blocks); /* Total allocation units */ - out_uint64_le(out, stat_fs.f_bfree); /* Available allocation units */ - out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */ - out_uint32_le(out, 0x200); /* Bytes per sector */ - break; + case FileFsFullSizeInformation: + out_uint64_le(out, stat_fs.f_blocks); /* Total allocation units */ + out_uint64_le(out, stat_fs.f_bavail); /* Caller allocation units */ + out_uint64_le(out, stat_fs.f_bfree); /* Available allocation units */ + out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */ + out_uint32_le(out, 0x200); /* Bytes per sector */ + break; - case FileFsFullSizeInformation: + case FileFsAttributeInformation: + stmp = s_alloc(PATH_MAX * 4); + out_utf16s_no_eos(stmp, fsinfo->type); + s_mark_end(stmp); - out_uint64_le(out, stat_fs.f_blocks); /* Total allocation units */ - out_uint64_le(out, stat_fs.f_bavail); /* Caller allocation units */ - out_uint64_le(out, stat_fs.f_bfree); /* Available allocation units */ - out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */ - out_uint32_le(out, 0x200); /* Bytes per sector */ - break; + out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */ + out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */ - case FileFsAttributeInformation: - stmp = s_alloc(PATH_MAX * 4); - out_utf16s_no_eos(stmp, fsinfo->type); - s_mark_end(stmp); + out_uint32_le(out, s_length(stmp)); /* length of fsinfo->type string */ + out_stream(out, stmp); /* fsinfo->typ string */ + s_free(stmp); + break; - out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */ - out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */ + case FileFsLabelInformation: + case FileFsDeviceInformation: + case FileFsControlInformation: + case FileFsObjectIdInformation: + case FileFsMaximumInformation: - out_uint32_le(out, s_length(stmp)); /* length of fsinfo->type string */ - out_stream(out, stmp); /* fsinfo->typ string */ - s_free(stmp); - break; - - case FileFsLabelInformation: - case FileFsDeviceInformation: - case FileFsControlInformation: - case FileFsObjectIdInformation: - case FileFsMaximumInformation: - - default: - logger(Disk, Warning, - "disk_query_volume_information(), unhandled volume info class 0x%x", - info_class); - return RD_STATUS_INVALID_PARAMETER; - } - return RD_STATUS_SUCCESS; + default: + logger(Disk, Warning, + "disk_query_volume_information(), unhandled volume info class 0x%x", + info_class); + return RD_STATUS_INVALID_PARAMETER; + } + return RD_STATUS_SUCCESS; } -RD_NTSTATUS -disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out) +RD_NTSTATUS disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out) { - uint32 file_attributes, ft_low, ft_high; - char *dirname, fullpath[PATH_MAX]; - DIR *pdir; - struct dirent *pdirent; - struct stat filestat; - struct fileinfo *pfinfo; - STREAM stmp; + uint32 file_attributes, ft_low, ft_high; + char *dirname, fullpath[PATH_MAX]; + DIR *pdir; + struct dirent *pdirent; + struct stat filestat; + struct fileinfo *pfinfo; + STREAM stmp; - logger(Disk, Debug, "disk_query_directory(handle=0x%x, info_class=0x%x, pattern=%s, ...)", - handle, info_class, pattern); + logger(Disk, Debug, "disk_query_directory(handle=0x%x, info_class=0x%x, pattern=%s, ...)", + handle, info_class, pattern); - pfinfo = &(g_fileinfo[handle]); - pdir = pfinfo->pdir; - dirname = pfinfo->path; - file_attributes = 0; + pfinfo = &(g_fileinfo[handle]); + pdir = pfinfo->pdir; + dirname = pfinfo->path; + file_attributes = 0; - switch (info_class) - { - case FileBothDirectoryInformation: - case FileDirectoryInformation: - case FileFullDirectoryInformation: - case FileNamesInformation: + switch (info_class) + { + case FileBothDirectoryInformation: + case FileDirectoryInformation: + case FileFullDirectoryInformation: + case FileNamesInformation: + /* If a search pattern is received, remember this pattern, and restart search */ + if (pattern != NULL && pattern[0] != 0) + { + strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), PATH_MAX - 1); + rewinddir(pdir); + } - /* If a search pattern is received, remember this pattern, and restart search */ - if (pattern != NULL && pattern[0] != 0) - { - strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), PATH_MAX - 1); - rewinddir(pdir); - } + /* find next dirent matching pattern */ + pdirent = readdir(pdir); + while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0) + pdirent = readdir(pdir); - /* find next dirent matching pattern */ - pdirent = readdir(pdir); - while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0) - pdirent = readdir(pdir); + if (pdirent == NULL) + return RD_STATUS_NO_MORE_FILES; - if (pdirent == NULL) - return RD_STATUS_NO_MORE_FILES; + /* Get information for directory entry */ + snprintf(fullpath, sizeof(fullpath), "%s/%s", dirname, pdirent->d_name); - /* Get information for directory entry */ - sprintf(fullpath, "%s/%s", dirname, pdirent->d_name); + if (stat(fullpath, &filestat)) + { + switch (errno) + { + case ENOENT: + case ELOOP: + case EACCES: + /* These are non-fatal errors. */ + memset(&filestat, 0, sizeof(filestat)); + break; + default: + /* Fatal error. By returning STATUS_NO_SUCH_FILE, + the directory list operation will be aborted */ + logger(Disk, Error, + "disk_query_directory(), stat() failed: %s", + strerror(errno)); + out_uint8(out, 0); + return RD_STATUS_NO_SUCH_FILE; + } + } - if (stat(fullpath, &filestat)) - { - switch (errno) - { - case ENOENT: - case ELOOP: - case EACCES: - /* These are non-fatal errors. */ - memset(&filestat, 0, sizeof(filestat)); - break; - default: - /* Fatal error. By returning STATUS_NO_SUCH_FILE, - the directory list operation will be aborted */ - logger(Disk, Error, - "disk_query_directory(), stat() failed: %s", - strerror(errno)); - out_uint8(out, 0); - return RD_STATUS_NO_SUCH_FILE; - } - } + if (S_ISDIR(filestat.st_mode)) + file_attributes |= FILE_ATTRIBUTE_DIRECTORY; + if (pdirent->d_name[0] == '.') + file_attributes |= FILE_ATTRIBUTE_HIDDEN; + if (!file_attributes) + file_attributes |= FILE_ATTRIBUTE_NORMAL; + if (!(filestat.st_mode & S_IWUSR)) + file_attributes |= FILE_ATTRIBUTE_READONLY; - if (S_ISDIR(filestat.st_mode)) - file_attributes |= FILE_ATTRIBUTE_DIRECTORY; - if (pdirent->d_name[0] == '.') - file_attributes |= FILE_ATTRIBUTE_HIDDEN; - if (!file_attributes) - file_attributes |= FILE_ATTRIBUTE_NORMAL; - if (!(filestat.st_mode & S_IWUSR)) - file_attributes |= FILE_ATTRIBUTE_READONLY; + /* Return requested information */ + out_uint32_le(out, 0); /* NextEntryOffset */ + out_uint32_le(out, 0); /* FileIndex zero */ + break; - /* Return requested information */ - out_uint32_le(out, 0); /* NextEntryOffset */ - out_uint32_le(out, 0); /* FileIndex zero */ - break; + default: + logger(Disk, Warning, + "disk_query_directory(), unhandled directory info class 0x%x", + info_class); + return RD_STATUS_INVALID_PARAMETER; + } - default: - logger(Disk, Warning, - "disk_query_directory(), unhandled directory info class 0x%x", - info_class); - return RD_STATUS_INVALID_PARAMETER; - } + // Write entry name as utf16 into stmp + stmp = s_alloc(PATH_MAX * 4); + out_utf16s_no_eos(stmp, pdirent->d_name); + s_mark_end(stmp); - // Write entry name as utf16 into stmp - stmp = s_alloc(PATH_MAX * 4); - out_utf16s_no_eos(stmp, pdirent->d_name); - s_mark_end(stmp); + switch (info_class) + { + case FileBothDirectoryInformation: + seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* create time */ + out_uint32_le(out, ft_high); - switch (info_class) - { - case FileBothDirectoryInformation: + seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_access_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, - &ft_low); - out_uint32_le(out, ft_low); /* create time */ - out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_write_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_access_time */ - out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* change_write_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_write_time */ - out_uint32_le(out, ft_high); + out_uint64_le(out, filestat.st_size); /* filesize */ + out_uint64_le(out, filestat.st_size); /* filesize */ + out_uint32_le(out, file_attributes); /* FileAttributes */ + out_uint32_le(out, s_length(stmp)); /* length of dir entry name string */ + out_uint32_le(out, 0); /* EaSize */ + out_uint8(out, 0); /* ShortNameLength */ + out_uint8s(out, 24); /* ShortName (8.3 name) */ + out_stream(out, stmp); /* dir entry name string */ + break; - seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* change_write_time */ - out_uint32_le(out, ft_high); + case FileDirectoryInformation: + seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* create time */ + out_uint32_le(out, ft_high); - out_uint64_le(out, filestat.st_size); /* filesize */ - out_uint64_le(out, filestat.st_size); /* filesize */ - out_uint32_le(out, file_attributes); /* FileAttributes */ - out_uint32_le(out, s_length(stmp)); /* length of dir entry name string */ - out_uint32_le(out, 0); /* EaSize */ - out_uint8(out, 0); /* ShortNameLength */ - out_uint8s(out, 24); /* ShortName (8.3 name) */ - out_stream(out, stmp); /* dir entry name string */ - break; + seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_access_time */ + out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_write_time */ + out_uint32_le(out, ft_high); - case FileDirectoryInformation: + seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* change_write_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, - &ft_low); - out_uint32_le(out, ft_low); /* create time */ - out_uint32_le(out, ft_high); + out_uint64_le(out, filestat.st_size); /* filesize */ + out_uint64_le(out, filestat.st_size); /* filesize */ + out_uint32_le(out, file_attributes); + out_uint32_le(out, s_length(stmp)); /* dir entry name string length */ + out_stream(out, stmp); /* dir entry name */ + break; - seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_access_time */ - out_uint32_le(out, ft_high); + case FileFullDirectoryInformation: + seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* create time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_write_time */ - out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_access_time */ + out_uint32_le(out, ft_high); - seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* change_write_time */ - out_uint32_le(out, ft_high); + seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* last_write_time */ + out_uint32_le(out, ft_high); - out_uint64_le(out, filestat.st_size); /* filesize */ - out_uint64_le(out, filestat.st_size); /* filesize */ - out_uint32_le(out, file_attributes); - out_uint32_le(out, s_length(stmp)); /* dir entry name string length */ - out_stream(out, stmp); /* dir entry name */ - break; + seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); + out_uint32_le(out, ft_low); /* change_write_time */ + out_uint32_le(out, ft_high); + out_uint64_le(out, filestat.st_size); /* filesize */ + out_uint64_le(out, filestat.st_size); /* filesize */ + out_uint32_le(out, file_attributes); + out_uint32_le(out, s_length(stmp)); /* dir entry name string length */ + out_uint32_le(out, 0); /* EaSize */ + out_stream(out, stmp); /* dir entry name */ + break; - case FileFullDirectoryInformation: + case FileNamesInformation: + out_uint32_le(out, s_length(stmp)); /* dir entry name string length */ + out_stream(out, stmp); /* dir entry name */ + break; - seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high, - &ft_low); - out_uint32_le(out, ft_low); /* create time */ - out_uint32_le(out, ft_high); + default: + logger(Disk, Warning, + "disk_query_directory(), unhandled directory info class 0x%x", + info_class); + s_free(stmp); + return RD_STATUS_INVALID_PARAMETER; + } - seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_access_time */ - out_uint32_le(out, ft_high); + s_free(stmp); - seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* last_write_time */ - out_uint32_le(out, ft_high); - - seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low); - out_uint32_le(out, ft_low); /* change_write_time */ - out_uint32_le(out, ft_high); - - out_uint64_le(out, filestat.st_size); /* filesize */ - out_uint64_le(out, filestat.st_size); /* filesize */ - out_uint32_le(out, file_attributes); - out_uint32_le(out, s_length(stmp)); /* dir entry name string length */ - out_uint32_le(out, 0); /* EaSize */ - out_stream(out, stmp); /* dir entry name */ - break; - - - case FileNamesInformation: - - out_uint32_le(out, s_length(stmp)); /* dir entry name string length */ - out_stream(out, stmp); /* dir entry name */ - break; - - - default: - logger(Disk, Warning, - "disk_query_directory(), unhandled directory info class 0x%x", - info_class); - s_free(stmp); - return RD_STATUS_INVALID_PARAMETER; - } - - s_free(stmp); - - return RD_STATUS_SUCCESS; + return RD_STATUS_SUCCESS; } - - -static RD_NTSTATUS -disk_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out) +static RD_NTSTATUS disk_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out) { - UNUSED(in); - UNUSED(out); + UNUSED(in); + UNUSED(out); - logger(Disk, Debug, "disk_device_control(handle=0x%x, request=0x%x, ...)", handle, request); - if (((request >> 16) != 20) || ((request >> 16) != 9)) - return RD_STATUS_INVALID_PARAMETER; + logger(Disk, Debug, "disk_device_control(handle=0x%x, request=0x%x, ...)", handle, request); + if (((request >> 16) != 20) || ((request >> 16) != 9)) + return RD_STATUS_INVALID_PARAMETER; - /* extract operation */ - request >>= 2; - request &= 0xfff; + /* extract operation */ + request >>= 2; + request &= 0xfff; - switch (request) - { - case 25: /* ? */ - case 42: /* ? */ - default: - logger(Disk, Warning, "disk_device_control(), unhandled disk ioctl %d", - request); - return RD_STATUS_INVALID_PARAMETER; - } + switch (request) + { + case 25: /* ? */ + case 42: /* ? */ + default: + logger(Disk, Warning, "disk_device_control(), unhandled disk ioctl %d", + request); + return RD_STATUS_INVALID_PARAMETER; + } - return RD_STATUS_SUCCESS; + return RD_STATUS_SUCCESS; } DEVICE_FNS disk_fns = { - disk_create, - disk_close, - disk_read, - disk_write, - disk_device_control /* device_control */ + disk_create, + disk_close, + disk_read, + disk_write, + disk_device_control /* device_control */ }; diff --git a/disk.h b/disk.h index 36378f8..23a60ed 100644 --- a/disk.h +++ b/disk.h @@ -18,123 +18,137 @@ along with this program. If not, see . */ -#define FILE_ATTRIBUTE_READONLY 0x00000001 -#define FILE_ATTRIBUTE_HIDDEN 0x00000002 -#define FILE_ATTRIBUTE_SYSTEM 0x00000004 -#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 -#define FILE_ATTRIBUTE_ARCHIVE 0x00000020 -#define FILE_ATTRIBUTE_DEVICE 0x00000040 -#define FILE_ATTRIBUTE_UNKNOWNXXX0 0x00000060 /* ??? ACTION i.e. 0x860 == compress this file ? */ -#define FILE_ATTRIBUTE_NORMAL 0x00000080 -#define FILE_ATTRIBUTE_TEMPORARY 0x00000100 -#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200 -#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 -#define FILE_ATTRIBUTE_COMPRESSED 0x00000800 -#define FILE_ATTRIBUTE_OFFLINE 0x00001000 -#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 -#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 +#ifndef DISK_REDIRECTION_DEFINITIONS_H +#define DISK_REDIRECTION_DEFINITIONS_H -#define FILE_FLAG_OPEN_NO_RECALL 0x00100000 -#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000 -#define FILE_FLAG_POSIX_SEMANTICS 0x01000000 -#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000 /* sometimes used to create a directory */ -#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000 -#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000 -#define FILE_FLAG_RANDOM_ACCESS 0x10000000 -#define FILE_FLAG_NO_BUFFERING 0x20000000 -#define FILE_FLAG_OVERLAPPED 0x40000000 -#define FILE_FLAG_WRITE_THROUGH 0x80000000 +#include -#define FILE_SHARE_READ 0x01 -#define FILE_SHARE_WRITE 0x02 -#define FILE_SHARE_DELETE 0x04 +// File attribute constants +#define FILE_ATTRIBUTE_READONLY 0x00000001 +#define FILE_ATTRIBUTE_HIDDEN 0x00000002 +#define FILE_ATTRIBUTE_SYSTEM 0x00000004 +#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 +#define FILE_ATTRIBUTE_ARCHIVE 0x00000020 +#define FILE_ATTRIBUTE_DEVICE 0x00000040 +#define FILE_ATTRIBUTE_NORMAL 0x00000080 +#define FILE_ATTRIBUTE_TEMPORARY 0x00000100 +#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200 +#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 +#define FILE_ATTRIBUTE_COMPRESSED 0x00000800 +#define FILE_ATTRIBUTE_OFFLINE 0x00001000 +#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 +#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 -#define FILE_BASIC_INFORMATION 0x04 -#define FILE_STANDARD_INFORMATION 0x05 +// File flag constants +#define FILE_FLAG_OPEN_NO_RECALL 0x00100000 +#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000 +#define FILE_FLAG_POSIX_SEMANTICS 0x01000000 +#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000 +#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000 +#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000 +#define FILE_FLAG_RANDOM_ACCESS 0x10000000 +#define FILE_FLAG_NO_BUFFERING 0x20000000 +#define FILE_FLAG_OVERLAPPED 0x40000000 +#define FILE_FLAG_WRITE_THROUGH 0x80000000 -#define FS_CASE_SENSITIVE 0x00000001 -#define FS_CASE_IS_PRESERVED 0x00000002 -#define FS_UNICODE_STORED_ON_DISK 0x00000004 -#define FS_PERSISTENT_ACLS 0x00000008 -#define FS_FILE_COMPRESSION 0x00000010 -#define FS_VOLUME_QUOTAS 0x00000020 -#define FS_SUPPORTS_SPARSE_FILES 0x00000040 -#define FS_SUPPORTS_REPARSE_POINTS 0x00000080 -#define FS_SUPPORTS_REMOTE_STORAGE 0X00000100 -#define FS_VOL_IS_COMPRESSED 0x00008000 -#define FILE_READ_ONLY_VOLUME 0x00080000 +// File share mode constants +#define FILE_SHARE_READ 0x00000001 +#define FILE_SHARE_WRITE 0x00000002 +#define FILE_SHARE_DELETE 0x00000004 -#define OPEN_EXISTING 1 -#define CREATE_NEW 2 -#define OPEN_ALWAYS 3 -#define TRUNCATE_EXISTING 4 -#define CREATE_ALWAYS 5 +// File information constants +#define FILE_BASIC_INFORMATION 0x00000004 +#define FILE_STANDARD_INFORMATION 0x00000005 -#define GENERIC_READ 0x80000000 -#define GENERIC_WRITE 0x40000000 -#define GENERIC_EXECUTE 0x20000000 -#define GENERIC_ALL 0x10000000 +// File system attribute constants +#define FS_CASE_SENSITIVE 0x00000001 +#define FS_CASE_IS_PRESERVED 0x00000002 +#define FS_UNICODE_STORED_ON_DISK 0x00000004 +#define FS_PERSISTENT_ACLS 0x00000008 +#define FS_FILE_COMPRESSION 0x00000010 +#define FS_VOLUME_QUOTAS 0x00000020 +#define FS_SUPPORTS_SPARSE_FILES 0x00000040 +#define FS_SUPPORTS_REPARSE_POINTS 0x00000080 +#define FS_SUPPORTS_REMOTE_STORAGE 0x00000100 +#define FS_VOL_IS_COMPRESSED 0x00008000 +#define FILE_READ_ONLY_VOLUME 0x00080000 -#define ERROR_FILE_NOT_FOUND 2L -#define ERROR_ALREADY_EXISTS 183L +// File creation disposition constants +#define OPEN_EXISTING 3 +#define CREATE_NEW 1 +#define OPEN_ALWAYS 4 +#define TRUNCATE_EXISTING 5 +#define CREATE_ALWAYS 2 -#define MAX_OPEN_FILES 0x100 +// Generic access rights constants +#define GENERIC_READ 0x80000000 +#define GENERIC_WRITE 0x40000000 +#define GENERIC_EXECUTE 0x20000000 +#define GENERIC_ALL 0x10000000 + +// Error codes +#define ERROR_FILE_NOT_FOUND 2L +#define ERROR_ALREADY_EXISTS 183L + +#define MAX_OPEN_FILES 256 typedef enum _FILE_INFORMATION_CLASS { - FileDirectoryInformation = 1, - FileFullDirectoryInformation, - FileBothDirectoryInformation, - FileBasicInformation, - FileStandardInformation, - FileInternalInformation, - FileEaInformation, - FileAccessInformation, - FileNameInformation, - FileRenameInformation, - FileLinkInformation, - FileNamesInformation, - FileDispositionInformation, - FilePositionInformation, - FileFullEaInformation, - FileModeInformation, - FileAlignmentInformation, - FileAllInformation, - FileAllocationInformation, - FileEndOfFileInformation, - FileAlternateNameInformation, - FileStreamInformation, - FilePipeInformation, - FilePipeLocalInformation, - FilePipeRemoteInformation, - FileMailslotQueryInformation, - FileMailslotSetInformation, - FileCompressionInformation, - FileCopyOnWriteInformation, - FileCompletionInformation, - FileMoveClusterInformation, - FileOleClassIdInformation, - FileOleStateBitsInformation, - FileNetworkOpenInformation, - FileObjectIdInformation, - FileOleAllInformation, - FileOleDirectoryInformation, - FileContentIndexInformation, - FileInheritContentIndexInformation, - FileOleInformation, - FileMaximumInformation + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileCopyOnWriteInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileOleClassIdInformation, + FileOleStateBitsInformation, + FileNetworkOpenInformation, + FileObjectIdInformation, + FileOleAllInformation, + FileOleDirectoryInformation, + FileContentIndexInformation, + FileInheritContentIndexInformation, + FileOleInformation, + FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; -typedef enum _FSINFOCLASS +typedef enum _FS_INFORMATION_CLASS { - FileFsVolumeInformation = 1, - FileFsLabelInformation, - FileFsSizeInformation, - FileFsDeviceInformation, - FileFsAttributeInformation, - FileFsControlInformation, - FileFsFullSizeInformation, - FileFsObjectIdInformation, - FileFsDriverPathInformation, - FileFsMaximumInformation + FileFsVolumeInformation = 1, + FileFsLabelInformation, + FileFsSizeInformation, + FileFsDeviceInformation, + FileFsAttributeInformation, + FileFsControlInformation, + FileFsFullSizeInformation, + FileFsObjectIdInformation, + FileFsDriverPathInformation, + FileFsMaximumInformation } FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; + +#endif // DISK_REDIRECTION_DEFINITIONS_H diff --git a/dvc.c b/dvc.c index cb0f95a..338190e 100644 --- a/dvc.c +++ b/dvc.c @@ -1,4 +1,5 @@ -/* -*- c-basic-offset: 8 -*- +/* + -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. Dynamic Channel Virtual Channel Extension. Copyright 2017 Henrik Andersson for Cendio AB @@ -19,451 +20,320 @@ */ #include "rdesktop.h" +#include +#include +#include #define MAX_DVC_CHANNELS 20 -#define INVALID_CHANNEL ((uint32)-1) +#define INVALID_CHANNEL ((uint32_t)-1) -#define DYNVC_CREATE_REQ 0x01 -#define DYNVC_DATA_FIRST 0x02 -#define DYNVC_DATA 0x03 -#define DYNVC_CLOSE 0x04 -#define DYNVC_CAPABILITIES 0x05 -#define DYNVC_DATA_FIRST_COMPRESSED 0x06 -#define DYNVC_DATA_COMPRESSED 0x07 -#define DYNVC_SOFT_SYNC_REQUEST 0x08 -#define DYNVC_SOFT_SYNC_RESPONSE 0x09 +#define DYNVC_CREATE_REQ 0x01 +#define DYNVC_DATA_FIRST 0x02 +#define DYNVC_DATA 0x03 +#define DYNVC_CLOSE 0x04 +#define DYNVC_CAPABILITIES 0x05 +#define DYNVC_DATA_FIRST_COMPRESSED 0x06 +#define DYNVC_DATA_COMPRESSED 0x07 +#define DYNVC_SOFT_SYNC_REQUEST 0x08 +#define DYNVC_SOFT_SYNC_RESPONSE 0x09 -typedef union dvc_hdr_t -{ - uint8 data; - struct - { - uint8 cbid:2; - uint8 sp:2; - uint8 cmd:4; - } hdr; +typedef union { + uint8_t data; + struct { + uint8_t cbid : 2; + uint8_t sp : 2; + uint8_t cmd : 4; + } hdr; } dvc_hdr_t; -typedef struct dvc_channel_t -{ - uint32 hash; - uint32 channel_id; - dvc_channel_process_fn handler; +typedef struct { + uint32_t hash; + uint32_t channel_id; + dvc_channel_process_fn handler; } dvc_channel_t; static VCHANNEL *dvc_channel; static dvc_channel_t channels[MAX_DVC_CHANNELS]; -static uint32 dvc_in_channelid(STREAM s, dvc_hdr_t hdr); +static uint32_t dvc_in_channelid(STREAM s, dvc_hdr_t hdr); -static RD_BOOL -dvc_channels_exists(const char *name) -{ - int i; - uint32 hash; - hash = utils_djb2_hash(name); - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (channels[i].hash == hash) - return True; - } - - return False; +static bool dvc_channels_exists(const char *name) { + uint32_t hash = utils_djb2_hash(name); + for (int i = 0; i < MAX_DVC_CHANNELS; i++) { + if (channels[i].hash == hash) + return true; + } + return false; } -static const dvc_channel_t * -dvc_channels_get_by_id(uint32 id) -{ - int i; - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (channels[i].channel_id == id) - { - return &channels[i]; - } - } - - return NULL; +static const dvc_channel_t *dvc_channels_get_by_id(uint32_t id) { + for (int i = 0; i < MAX_DVC_CHANNELS; i++) { + if (channels[i].channel_id == id) { + return &channels[i]; + } + } + return NULL; } -static uint32 -dvc_channels_get_id(const char *name) -{ - int i; - uint32 hash; - hash = utils_djb2_hash(name); - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (channels[i].hash == hash) - { - return channels[i].channel_id; - } - } - - return INVALID_CHANNEL; +static uint32_t dvc_channels_get_id(const char *name) { + uint32_t hash = utils_djb2_hash(name); + for (int i = 0; i < MAX_DVC_CHANNELS; i++) { + if (channels[i].hash == hash) { + return channels[i].channel_id; + } + } + return INVALID_CHANNEL; } -static RD_BOOL -dvc_channels_remove_by_id(uint32 channelid) -{ - int i; - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (channels[i].channel_id == channelid) - { - memset(&channels[i], 0, sizeof(dvc_channel_t)); - return True; - } - } - return False; +static bool dvc_channels_remove_by_id(uint32_t channelid) { + for (int i = 0; i < MAX_DVC_CHANNELS; i++) { + if (channels[i].channel_id == channelid) { + memset(&channels[i], 0, sizeof(dvc_channel_t)); + return true; + } + } + return false; } -static RD_BOOL -dvc_channels_add(const char *name, dvc_channel_process_fn handler, uint32 channel_id) -{ - int i; - uint32 hash; +static bool dvc_channels_add(const char *name, dvc_channel_process_fn handler, uint32_t channel_id) { + if (dvc_channels_exists(name)) { + logger(Core, Warning, "dvc_channels_add(), channel with name '%s' already exists", name); + return false; + } - if (dvc_channels_exists(name) == True) - { - logger(Core, Warning, "dvc_channels_add(), channel with name '%s' already exists", - name); - return False; - } + for (int i = 0; i < MAX_DVC_CHANNELS; i++) { + if (channels[i].hash == 0) { + uint32_t hash = utils_djb2_hash(name); + channels[i].hash = hash; + channels[i].handler = handler; + channels[i].channel_id = channel_id; + logger(Core, Debug, "dvc_channels_add(), Added hash=%x, channel_id=%d, name=%s, handler=%p", + hash, channel_id, name, handler); + return true; + } + } - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (channels[i].hash == 0) - { - hash = utils_djb2_hash(name); - channels[i].hash = hash; - channels[i].handler = handler; - channels[i].channel_id = channel_id; - logger(Core, Debug, - "dvc_channels_add(), Added hash=%x, channel_id=%d, name=%s, handler=%p", - hash, channel_id, name, handler); - return True; - } - } - - logger(Core, Warning, - "dvc_channels_add(), Failed to add channel, maximum number of channels are being used"); - return False; + logger(Core, Warning, "dvc_channels_add(), Failed to add channel, maximum number of channels are being used"); + return false; } -static int -dvc_channels_set_id(const char *name, uint32 channel_id) -{ - int i; - uint32 hash; - - hash = utils_djb2_hash(name); - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (channels[i].hash == hash) - { - logger(Core, Debug, "dvc_channels_set_id(), name = '%s', channel_id = %d", - name, channel_id); - channels[i].channel_id = channel_id; - return 0; - } - } - - return -1; +static int dvc_channels_set_id(const char *name, uint32_t channel_id) { + uint32_t hash = utils_djb2_hash(name); + for (int i = 0; i < MAX_DVC_CHANNELS; i++) { + if (channels[i].hash == hash) { + logger(Core, Debug, "dvc_channels_set_id(), name = '%s', channel_id = %d", name, channel_id); + channels[i].channel_id = channel_id; + return 0; + } + } + return -1; } -RD_BOOL -dvc_channels_is_available(const char *name) -{ - int i; - uint32 hash; - hash = utils_djb2_hash(name); - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (channels[i].hash == hash) - { - return (channels[i].channel_id != INVALID_CHANNEL); - } - } - - return False; +bool dvc_channels_is_available(const char *name) { + uint32_t hash = utils_djb2_hash(name); + for (int i = 0; i < MAX_DVC_CHANNELS; i++) { + if (channels[i].hash == hash) { + return (channels[i].channel_id != INVALID_CHANNEL); + } + } + return false; } -RD_BOOL -dvc_channels_register(const char *name, dvc_channel_process_fn handler) -{ - return dvc_channels_add(name, handler, INVALID_CHANNEL); +bool dvc_channels_register(const char *name, dvc_channel_process_fn handler) { + return dvc_channels_add(name, handler, INVALID_CHANNEL); } +static STREAM dvc_init_packet(dvc_hdr_t hdr, uint32_t channelid, size_t length) { + STREAM s; + length += 1; // add 1 byte hdr -static STREAM -dvc_init_packet(dvc_hdr_t hdr, uint32 channelid, size_t length) -{ - STREAM s; + if (channelid != INVALID_CHANNEL) { + if (hdr.hdr.cbid == 0) + length += 1; + else if (hdr.hdr.cbid == 1) + length += 2; + else if (hdr.hdr.cbid == 2) + length += 4; + } - length += 1; /* add 1 byte hdr */ + s = channel_init(dvc_channel, length); + out_uint8(s, hdr.data); // DVC header - if (channelid != INVALID_CHANNEL) - { - if (hdr.hdr.cbid == 0) - length += 1; - else if (hdr.hdr.cbid == 1) - length += 2; - else if (hdr.hdr.cbid == 2) - length += 4; - } + if (channelid != INVALID_CHANNEL) { + if (hdr.hdr.cbid == 0) { + out_uint8(s, channelid); + } else if (hdr.hdr.cbid == 1) { + out_uint16_le(s, channelid); + } else if (hdr.hdr.cbid == 2) { + out_uint32_le(s, channelid); + } + } - s = channel_init(dvc_channel, length); - out_uint8(s, hdr.data); /* DVC header */ - - if (channelid != INVALID_CHANNEL) - { - if (hdr.hdr.cbid == 0) - { - out_uint8(s, channelid); - } - else if (hdr.hdr.cbid == 1) - { - out_uint16_le(s, channelid); - } - else if (hdr.hdr.cbid == 2) - { - out_uint32_le(s, channelid); - } - } - - return s; + return s; } -void -dvc_send(const char *name, STREAM s) -{ - STREAM ls; - dvc_hdr_t hdr; - uint32 channel_id; +void dvc_send(const char *name, STREAM s) { + STREAM ls; + dvc_hdr_t hdr; + uint32_t channel_id = dvc_channels_get_id(name); - channel_id = dvc_channels_get_id(name); - if (channel_id == INVALID_CHANNEL) - { - logger(Core, Error, "dvc_send(), Trying to send data on invalid channel '%s'", - name); - return; - } + if (channel_id == INVALID_CHANNEL) { + logger(Core, Error, "dvc_send(), Trying to send data on invalid channel '%s'", name); + return; + } - /* FIXME: we assume length is less than 1600 */ + // FIXME: we assume length is less than 1600 + hdr.hdr.cmd = DYNVC_DATA; + hdr.hdr.cbid = 2; + hdr.hdr.sp = 0; - hdr.hdr.cmd = DYNVC_DATA; - hdr.hdr.cbid = 2; - hdr.hdr.sp = 0; - - ls = dvc_init_packet(hdr, channel_id, s_length(s)); - - out_stream(ls, s); - - s_mark_end(ls); - - channel_send(ls, dvc_channel); - s_free(ls); + ls = dvc_init_packet(hdr, channel_id, s_length(s)); + out_stream(ls, s); + s_mark_end(ls); + channel_send(ls, dvc_channel); + s_free(ls); } +static void dvc_send_capabilities_response() { + STREAM s; + dvc_hdr_t hdr; + uint16_t supportedversion = 0x01; -static void -dvc_send_capabilities_response() -{ - STREAM s; - dvc_hdr_t hdr; - uint16 supportedversion = 0x01; + hdr.hdr.cbid = 0x00; + hdr.hdr.sp = 0x00; + hdr.hdr.cmd = DYNVC_CAPABILITIES; - hdr.hdr.cbid = 0x00; - hdr.hdr.sp = 0x00; - hdr.hdr.cmd = DYNVC_CAPABILITIES; + logger(Protocol, Debug, "dvc_send_capabilities_response(), offering support for dvc %d", supportedversion); - logger(Protocol, Debug, - "dvc_send_capabilities_response(), offering support for dvc %d", supportedversion); - - s = dvc_init_packet(hdr, -1, 3); - out_uint8(s, 0x00); /* pad */ - out_uint16_le(s, supportedversion); /* version */ - - s_mark_end(s); - - channel_send(s, dvc_channel); - s_free(s); + s = dvc_init_packet(hdr, (uint32_t)-1, 3); + out_uint8(s, 0x00); // pad + out_uint16_le(s, supportedversion); // version + s_mark_end(s); + channel_send(s, dvc_channel); + s_free(s); } -static void -dvc_process_caps_pdu(STREAM s) -{ - uint16 version; +static void dvc_process_caps_pdu(STREAM s) { + uint16_t version; - /* VERSION1 */ - in_uint8s(s, 1); /* pad */ - in_uint16_le(s, version); /* version */ + in_uint8s(s, 1); // pad + in_uint16_le(s, version); // version - logger(Protocol, Debug, "dvc_process_caps(), server supports dvc %d", version); + logger(Protocol, Debug, "dvc_process_caps(), server supports dvc %d", version); - dvc_send_capabilities_response(); + dvc_send_capabilities_response(); } -static void -dvc_send_create_response(RD_BOOL success, dvc_hdr_t hdr, uint32 channelid) -{ - STREAM s; +static void dvc_send_create_response(bool success, dvc_hdr_t hdr, uint32_t channelid) { + STREAM s; - logger(Protocol, Debug, "dvc_send_create_response(), %s request to create channelid %d", - (success ? "granted" : "denied"), channelid); - s = dvc_init_packet(hdr, channelid, 4); - out_uint32_le(s, success ? 0 : -1); - s_mark_end(s); - - channel_send(s, dvc_channel); - s_free(s); + logger(Protocol, Debug, "dvc_send_create_response(), %s request to create channelid %d", + (success ? "granted" : "denied"), channelid); + s = dvc_init_packet(hdr, channelid, 4); + out_uint32_le(s, success ? 0 : (uint32_t)-1); + s_mark_end(s); + channel_send(s, dvc_channel); + s_free(s); } -static void -dvc_process_create_pdu(STREAM s, dvc_hdr_t hdr) -{ - char name[512]; - uint32 channelid; +static void dvc_process_create_pdu(STREAM s, dvc_hdr_t hdr) { + char name[512]; + uint32_t channelid; - channelid = dvc_in_channelid(s, hdr); + channelid = dvc_in_channelid(s, hdr); + in_ansi_string(s, name, sizeof(name)); - in_ansi_string(s, name, sizeof(name)); - - logger(Protocol, Debug, "dvc_process_create(), server requests channelid = %d, name = '%s'", - channelid, name); - - if (dvc_channels_exists(name)) - { - logger(Core, Verbose, "Established dynamic virtual channel '%s'", name); - - dvc_channels_set_id(name, channelid); - dvc_send_create_response(True, hdr, channelid); - } - else - { - dvc_send_create_response(False, hdr, channelid); - } + logger(Protocol, Debug, "dvc_process_create(), server requests channelid = %d, name = '%s'", channelid, name); + if (dvc_channels_exists(name)) { + logger(Core, Verbose, "Established dynamic virtual channel '%s'", name); + dvc_channels_set_id(name, channelid); + dvc_send_create_response(true, hdr, channelid); + } else { + dvc_send_create_response(false, hdr, channelid); + } } -static uint32 -dvc_in_channelid(STREAM s, dvc_hdr_t hdr) -{ - uint32 id; +static uint32_t dvc_in_channelid(STREAM s, dvc_hdr_t hdr) { + uint32_t id = (uint32_t)-1; - id = (uint32) - 1; - - switch (hdr.hdr.cbid) - { - case 0: - in_uint8(s, id); - break; - case 1: - in_uint16_le(s, id); - break; - case 2: - in_uint32_le(s, id); - break; - } - return id; + switch (hdr.hdr.cbid) { + case 0: + in_uint8(s, id); + break; + case 1: + in_uint16_le(s, id); + break; + case 2: + in_uint32_le(s, id); + break; + } + return id; } -static void -dvc_process_data_pdu(STREAM s, dvc_hdr_t hdr) -{ - const dvc_channel_t *ch; - uint32 channelid; +static void dvc_process_data_pdu(STREAM s, dvc_hdr_t hdr) { + const dvc_channel_t *ch; + uint32_t channelid = dvc_in_channelid(s, hdr); - channelid = dvc_in_channelid(s, hdr); - ch = dvc_channels_get_by_id(channelid); - if (ch == NULL) - { - logger(Protocol, Warning, - "dvc_process_data(), Received data on unregistered channel %d", channelid); - return; - } + ch = dvc_channels_get_by_id(channelid); + if (ch == NULL) { + logger(Protocol, Warning, "dvc_process_data(), Received data on unregistered channel %d", channelid); + return; + } - /* dispatch packet to channel handler */ - ch->handler(s); + // Dispatch packet to channel handler + ch->handler(s); } -static void -dvc_process_close_pdu(STREAM s, dvc_hdr_t hdr) -{ - uint32 channelid; +static void dvc_process_close_pdu(STREAM s, dvc_hdr_t hdr) { + uint32_t channelid = dvc_in_channelid(s, hdr); + logger(Protocol, Debug, "dvc_process_close_pdu(), close channel %d", channelid); - channelid = dvc_in_channelid(s, hdr); - logger(Protocol, Debug, "dvc_process_close_pdu(), close channel %d", channelid); - - if (!dvc_channels_remove_by_id(channelid)) - { - logger(Protocol, Warning, - "dvc_process_close_pdu(), Received close request for unregistered channel %d", - channelid); - return; - } + if (!dvc_channels_remove_by_id(channelid)) { + logger(Protocol, Warning, "dvc_process_close_pdu(), Received close request for unregistered channel %d", channelid); + } } +static void dvc_process_pdu(STREAM s) { + dvc_hdr_t hdr; -static void -dvc_process_pdu(STREAM s) -{ - dvc_hdr_t hdr; + in_uint8(s, hdr.data); - in_uint8(s, hdr.data); - - switch (hdr.hdr.cmd) - { - case DYNVC_CAPABILITIES: - dvc_process_caps_pdu(s); - break; - case DYNVC_CREATE_REQ: - dvc_process_create_pdu(s, hdr); - break; - - case DYNVC_DATA: - dvc_process_data_pdu(s, hdr); - break; - - case DYNVC_CLOSE: - dvc_process_close_pdu(s, hdr); - break; - -#if 0 /* Unimplemented */ - - case DYNVC_DATA_FIRST: - break; - case DYNVC_DATA_FIRST_COMPRESSED: - break; - case DYNVC_DATA_COMPRESSED: - break; - case DYNVC_SOFT_SYNC_REQUEST: - break; - case DYNVC_SOFT_SYNC_RESPONSE: - break; + switch (hdr.hdr.cmd) { + case DYNVC_CAPABILITIES: + dvc_process_caps_pdu(s); + break; + case DYNVC_CREATE_REQ: + dvc_process_create_pdu(s, hdr); + break; + case DYNVC_DATA: + dvc_process_data_pdu(s, hdr); + break; + case DYNVC_CLOSE: + dvc_process_close_pdu(s, hdr); + break; +#if 0 // Unimplemented + case DYNVC_DATA_FIRST: + break; + case DYNVC_DATA_FIRST_COMPRESSED: + break; + case DYNVC_DATA_COMPRESSED: + break; + case DYNVC_SOFT_SYNC_REQUEST: + break; + case DYNVC_SOFT_SYNC_RESPONSE: + break; #endif - default: - logger(Protocol, Warning, "dvc_process_pdu(), Unhandled command type 0x%x", - hdr.hdr.cmd); - break; - } + default: + logger(Protocol, Warning, "dvc_process_pdu(), Unhandled command type 0x%x", hdr.hdr.cmd); + break; + } } -RD_BOOL -dvc_init() -{ - memset(channels, 0, sizeof(channels)); - dvc_channel = channel_register("drdynvc", - CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, - dvc_process_pdu); - - return (dvc_channel != NULL); +bool dvc_init() { + memset(channels, 0, sizeof(channels)); + dvc_channel = channel_register("drdynvc", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, dvc_process_pdu); + return (dvc_channel != NULL); } diff --git a/ewmhints.c b/ewmhints.c index e4a746f..aac807f 100644 --- a/ewmhints.c +++ b/ewmhints.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "rdesktop.h" #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ @@ -45,7 +47,7 @@ Atom g_net_wm_state_atom, g_net_wm_desktop_atom, g_net_wm_ping_atom; Returns zero on success, -1 on error */ static int -get_property_value(Window wnd, char *propname, long max_length, +get_property_value(Window wnd, const char *propname, long max_length, unsigned long *nitems_return, unsigned char **prop_return, int nowarn) { int result; @@ -57,7 +59,8 @@ get_property_value(Window wnd, char *propname, long max_length, property = XInternAtom(g_display, propname, True); if (property == None) { - logger(GUI, Error, "get_property_value(), atom '%s' does not exist", propname); + if (!nowarn) + logger(GUI, Error, "get_property_value(), atom '%s' does not exist", propname); return (-1); } @@ -71,7 +74,8 @@ get_property_value(Window wnd, char *propname, long max_length, if (result != Success) { - logger(GUI, Error, "get_property_value(), XGetWindowProperty failed"); + if (!nowarn) + logger(GUI, Error, "get_property_value(), XGetWindowProperty failed"); return (-1); } @@ -106,7 +110,7 @@ static int get_current_desktop(void) { unsigned long nitems_return; - unsigned char *prop_return; + unsigned char *prop_return = NULL; int current_desktop; if (get_property_value @@ -117,6 +121,7 @@ get_current_desktop(void) if (nitems_return != 1) { logger(GUI, Error, "get_current_desktop(), _NET_CURRENT_DESKTOP has bad length"); + if (prop_return) XFree(prop_return); return (-1); } @@ -135,7 +140,7 @@ get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height) { int current_desktop; unsigned long nitems_return; - unsigned char *prop_return; + unsigned char *prop_return = NULL; long *return_words; const uint32 net_workarea_x_offset = 0; const uint32 net_workarea_y_offset = 1; @@ -151,13 +156,17 @@ get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height) if (nitems_return % 4) { logger(GUI, Error, "get_current_workarea(),_NET_WORKAREA has bad length"); + XFree(prop_return); return (-1); } current_desktop = get_current_desktop(); if (current_desktop < 0) + { + XFree(prop_return); return -1; + } return_words = (long *) prop_return; @@ -206,7 +215,7 @@ int ewmh_get_window_state(Window w) { unsigned long nitems_return; - unsigned char *prop_return; + unsigned char *prop_return = NULL; unsigned long *return_words; unsigned long item; RD_BOOL maximized_vert, maximized_horz, hidden; @@ -247,7 +256,7 @@ ewmh_modify_state(Window wnd, int add, Atom atom1, Atom atom2) int result; unsigned long i, nitems; - unsigned char *props; + unsigned char *props = NULL; uint32 state = WithdrawnState; /* The spec states that the window manager must respect any @@ -312,10 +321,7 @@ ewmh_modify_state(Window wnd, int add, Atom atom1, Atom atom2) xevent.xclient.window = wnd; xevent.xclient.message_type = g_net_wm_state_atom; xevent.xclient.format = 32; - if (add) - xevent.xclient.data.l[0] = _NET_WM_STATE_ADD; - else - xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE; + xevent.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; xevent.xclient.data.l[1] = atom1; xevent.xclient.data.l[2] = atom2; xevent.xclient.data.l[3] = 0; @@ -361,7 +367,7 @@ int ewmh_get_window_desktop(Window wnd) { unsigned long nitems_return; - unsigned char *prop_return; + unsigned char *prop_return = NULL; int desktop; if (get_property_value(wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return, 0) < 0) @@ -370,6 +376,7 @@ ewmh_get_window_desktop(Window wnd) if (nitems_return != 1) { logger(GUI, Error, "ewmh_get_window_desktop(), _NET_WM_DESKTOP has bad length"); + if (prop_return) XFree(prop_return); return (-1); } @@ -440,7 +447,7 @@ void ewmh_set_icon(Window wnd, uint32 width, uint32 height, const char *rgba_data) { unsigned long nitems, i; - unsigned char *props; + unsigned char *props = NULL; unsigned long *cur_set, *new_set; unsigned long *icon; @@ -463,7 +470,7 @@ ewmh_set_icon(Window wnd, uint32 width, uint32 height, const char *rgba_data) icon = cur_set + i; else { - new_set = xmalloc((nitems + width * height + 2) * sizeof(unsigned long)); + new_set = (unsigned long *)malloc((nitems + width * height + 2) * sizeof(unsigned long)); memcpy(new_set, cur_set, nitems * sizeof(unsigned long)); icon = new_set + nitems; nitems += width * height + 2; @@ -471,7 +478,7 @@ ewmh_set_icon(Window wnd, uint32 width, uint32 height, const char *rgba_data) } else { - new_set = xmalloc((width * height + 2) * sizeof(unsigned long)); + new_set = (unsigned long *)malloc((width * height + 2) * sizeof(unsigned long)); icon = new_set; nitems = width * height + 2; } @@ -483,10 +490,10 @@ ewmh_set_icon(Window wnd, uint32 width, uint32 height, const char *rgba_data) for (i = 0; i < (width * height); i++) { icon[i + 2] = - rgba_data[i * 4 + 3] << 24 | - ((rgba_data[i * 4 + 0] << 16) & 0x00FF0000) | - ((rgba_data[i * 4 + 1] << 8) & 0x0000FF00) | - ((rgba_data[i * 4 + 2] << 0) & 0x000000FF); + ((unsigned char)rgba_data[i * 4 + 3] << 24) | + (((unsigned char)rgba_data[i * 4 + 0] << 16) & 0x00FF0000) | + (((unsigned char)rgba_data[i * 4 + 1] << 8) & 0x0000FF00) | + (((unsigned char)rgba_data[i * 4 + 2] << 0) & 0x000000FF); } XChangeProperty(g_display, wnd, g_net_wm_icon_atom, XA_CARDINAL, 32, @@ -495,14 +502,14 @@ ewmh_set_icon(Window wnd, uint32 width, uint32 height, const char *rgba_data) if (cur_set) XFree(cur_set); if (new_set) - xfree(new_set); + free(new_set); } void ewmh_del_icon(Window wnd, uint32 width, uint32 height) { unsigned long nitems, i, icon_size; - unsigned char *props; + unsigned char *props = NULL; unsigned long *cur_set, *new_set; cur_set = NULL; @@ -525,7 +532,7 @@ ewmh_del_icon(Window wnd, uint32 width, uint32 height) goto out; icon_size = width * height + 2; - new_set = xmalloc((nitems - icon_size) * sizeof(unsigned long)); + new_set = (unsigned long *)malloc((nitems - icon_size) * sizeof(unsigned long)); if (i != 0) memcpy(new_set, cur_set, i * sizeof(unsigned long)); @@ -538,7 +545,7 @@ ewmh_del_icon(Window wnd, uint32 width, uint32 height) XChangeProperty(g_display, wnd, g_net_wm_icon_atom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) new_set, nitems); - xfree(new_set); + free(new_set); out: XFree(cur_set); @@ -556,7 +563,7 @@ RD_BOOL ewmh_is_window_above(Window w) { unsigned long nitems_return; - unsigned char *prop_return; + unsigned char *prop_return = NULL; unsigned long *return_words; unsigned long item; RD_BOOL above;