mirror of
https://github.com/zhaojh329/rtty.git
synced 2026-02-27 09:53:17 +08:00
Redesign file transfers
Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
This commit is contained in:
@@ -11,9 +11,6 @@ find_package(Libev REQUIRED)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/buffer ${LIBEV_INCLUDE_DIR})
|
||||
set(EXTRA_LIBS ${LIBEV_LIBRARY} util crypt m)
|
||||
|
||||
add_definitions(-DRTTY_FILE_UNIX_SOCKET_S="/var/run/rttyfile.sock")
|
||||
add_definitions(-DRTTY_FILE_UNIX_SOCKET_C="/var/run/rttyfile_c.sock")
|
||||
|
||||
set(RTTY_SSL_SUPPORT_CONFIG 1)
|
||||
option(RTTY_SSL_SUPPORT "SSL support" ON)
|
||||
|
||||
@@ -95,7 +92,7 @@ else()
|
||||
endif()
|
||||
|
||||
add_executable(rtty main.c utils.c buffer/buffer.c log.c net.c net.h rtty.c rtty.h command.c
|
||||
file.c upfile.c upfile.h downfile.c downfile.h ssl.c ssl.h web.c)
|
||||
file.c filectl.c ssl.c ssl.h web.c)
|
||||
target_link_libraries(rtty ${EXTRA_LIBS})
|
||||
|
||||
# configure a header file to pass some of the CMake settings to the source code
|
||||
|
||||
108
src/downfile.c
108
src/downfile.c
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "file.h"
|
||||
|
||||
static char abspath[PATH_MAX];
|
||||
static ev_tstamp start_time;
|
||||
static struct buffer b;
|
||||
static int sock;
|
||||
|
||||
static void signal_cb(struct ev_loop *loop, ev_signal *w, int revents)
|
||||
{
|
||||
cancel_file_operation(loop, sock);
|
||||
}
|
||||
|
||||
static void on_socket_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
int type = read_file_msg(w->fd, &b);
|
||||
|
||||
switch (type) {
|
||||
case RTTY_FILE_MSG_REQUEST_ACCEPT:
|
||||
buffer_put_u8(&b, RTTY_FILE_MSG_SAVE_PATH);
|
||||
buffer_put_string(&b, abspath);
|
||||
buffer_put_zero(&b, 1);
|
||||
buffer_pull_to_fd(&b, w->fd, -1);
|
||||
break;
|
||||
case RTTY_FILE_MSG_INFO:
|
||||
printf("Transferring '%s'...\n", (char *)buffer_data(&b));
|
||||
buffer_pull(&b, NULL, buffer_length(&b));
|
||||
start_time = ev_now(loop);
|
||||
break;
|
||||
case RTTY_FILE_MSG_PROGRESS:
|
||||
update_progress(loop, start_time, &b);
|
||||
break;
|
||||
case RTTY_FILE_MSG_BUSY:
|
||||
fprintf(stderr, "\033[31mRtty is busy\033[0m\n");
|
||||
ev_break(loop, EVBREAK_ALL);
|
||||
break;
|
||||
case RTTY_FILE_MSG_CANCELED:
|
||||
puts("");
|
||||
ev_break(loop, EVBREAK_ALL);
|
||||
break;
|
||||
case RTTY_FILE_MSG_NO_SPACE:
|
||||
fprintf(stderr, "\033[31mNo enough space\033[0m\n");
|
||||
ev_break(loop, EVBREAK_ALL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void download_file()
|
||||
{
|
||||
struct ev_loop *loop = EV_DEFAULT;
|
||||
static struct ev_signal sw;
|
||||
struct ev_io ior;
|
||||
|
||||
if (getuid() > 0) {
|
||||
fprintf(stderr, "Operation not permitted, must be run as root\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!realpath(".", abspath))
|
||||
return;
|
||||
|
||||
sock = connect_rtty_file_service();
|
||||
if (sock < 0)
|
||||
return;
|
||||
|
||||
request_transfer_file();
|
||||
|
||||
ev_io_init(&ior, on_socket_read, sock, EV_READ);
|
||||
ev_io_start(loop, &ior);
|
||||
|
||||
ev_signal_init(&sw, signal_cb, SIGINT);
|
||||
ev_signal_start(loop, &sw);
|
||||
|
||||
printf("Waiting to receive. Press Ctrl+C to cancel\n");
|
||||
|
||||
ev_run(loop, 0);
|
||||
|
||||
buffer_free(&b);
|
||||
close(sock);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef RTTY_DOWNFILE_H_
|
||||
#define RTTY_DOWNFILE_H_
|
||||
|
||||
void download_file();
|
||||
|
||||
#endif
|
||||
460
src/file.c
460
src/file.c
@@ -27,10 +27,10 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <mntent.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "file.h"
|
||||
@@ -40,23 +40,56 @@
|
||||
|
||||
static uint8_t RTTY_FILE_MAGIC[] = {0xb6, 0xbc, 0xbd};
|
||||
static char abspath[PATH_MAX];
|
||||
static struct buffer b;
|
||||
|
||||
static void notify_progress(struct file_context *ctx)
|
||||
static int send_file_control_msg(int fd, struct file_control_msg *msg)
|
||||
{
|
||||
if (write(fd, msg, sizeof(struct file_control_msg)) < 0) {
|
||||
log_err("write fifo: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void file_context_reset(struct file_context *ctx)
|
||||
{
|
||||
if (ctx->fd > 0) {
|
||||
close(ctx->fd);
|
||||
ctx->fd = -1;
|
||||
}
|
||||
|
||||
close(ctx->ctlfd);
|
||||
|
||||
ctx->busy = false;
|
||||
}
|
||||
|
||||
static void notify_user_canceled(struct rtty *rtty)
|
||||
{
|
||||
buffer_put_u8(&rtty->wb, MSG_TYPE_FILE);
|
||||
buffer_put_u16be(&rtty->wb, 2);
|
||||
buffer_put_u8(&rtty->wb, rtty->file_context.sid);
|
||||
buffer_put_u8(&rtty->wb, RTTY_FILE_MSG_CANCELED);
|
||||
ev_io_start(rtty->loop, &rtty->iow);
|
||||
}
|
||||
|
||||
static int notify_progress(struct file_context *ctx)
|
||||
{
|
||||
struct rtty *rtty = container_of(ctx, struct rtty, file_context);
|
||||
struct file_control_msg msg = {
|
||||
.type = RTTY_FILE_MSG_PROGRESS
|
||||
};
|
||||
ev_tstamp now = ev_now(rtty->loop);
|
||||
|
||||
if (ctx->remain_size > 0 && now - ctx->last_notify_progress < 0.1)
|
||||
return;
|
||||
return 0;
|
||||
ctx->last_notify_progress = now;
|
||||
|
||||
buffer_truncate(&b, 0);
|
||||
buffer_put_u8(&b, RTTY_FILE_MSG_PROGRESS);
|
||||
buffer_put_u32(&b, ctx->remain_size);
|
||||
buffer_put_u32(&b, ctx->total_size);
|
||||
sendto(ctx->sock, buffer_data(&b), buffer_length(&b), 0,
|
||||
(struct sockaddr *)&ctx->peer_sun, sizeof(struct sockaddr_un));
|
||||
memcpy(msg.buf, &ctx->remain_size, 4);
|
||||
|
||||
if (send_file_control_msg(ctx->ctlfd, &msg) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void on_file_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
@@ -70,6 +103,15 @@ static void on_file_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
return;
|
||||
|
||||
ret = read(w->fd, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
struct file_control_msg msg = {
|
||||
.type = RTTY_FILE_MSG_ERR
|
||||
};
|
||||
|
||||
send_file_control_msg(ctx->ctlfd, &msg);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx->remain_size -= ret;
|
||||
|
||||
buffer_put_u8(&rtty->wb, MSG_TYPE_FILE);
|
||||
@@ -79,30 +121,38 @@ static void on_file_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
buffer_put_data(&rtty->wb, buf, ret);
|
||||
ev_io_start(rtty->loop, &rtty->iow);
|
||||
|
||||
notify_progress(ctx);
|
||||
|
||||
if (ret == 0) {
|
||||
ctx->busy = false;
|
||||
ev_io_stop(loop, w);
|
||||
close(ctx->fd);
|
||||
ctx->fd = -1;
|
||||
file_context_reset(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (notify_progress(ctx) < 0)
|
||||
goto err;
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
ev_io_stop(loop, w);
|
||||
notify_user_canceled(rtty);
|
||||
file_context_reset(ctx);
|
||||
}
|
||||
|
||||
static void start_upload_file(struct file_context *ctx, struct buffer *info)
|
||||
static int start_upload_file(struct file_context *ctx, const char *path)
|
||||
{
|
||||
struct rtty *rtty = container_of(ctx, struct rtty, file_context);
|
||||
uint32_t size = buffer_pull_u32(info);
|
||||
const char *path = buffer_data(info);
|
||||
const char *name = basename(path);
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
log_err("open '%s' fail\n", path, strerror(errno));
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fstat(fd, &st);
|
||||
|
||||
buffer_put_u8(&rtty->wb, MSG_TYPE_FILE);
|
||||
buffer_put_u16be(&rtty->wb, 2 + strlen(name));
|
||||
buffer_put_u8(&rtty->wb, ctx->sid);
|
||||
@@ -114,24 +164,105 @@ static void start_upload_file(struct file_context *ctx, struct buffer *info)
|
||||
ev_io_start(rtty->loop, &ctx->iof);
|
||||
|
||||
ctx->fd = fd;
|
||||
ctx->total_size = size;
|
||||
ctx->remain_size = size;
|
||||
ctx->total_size = st.st_size;
|
||||
ctx->remain_size = st.st_size;
|
||||
|
||||
log_info("upload file: %s\n", path);
|
||||
log_info("upload file: %s, size: %" PRIu64 "\n", path, (uint64_t)st.st_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_canceled_msg(struct rtty *rtty)
|
||||
bool detect_file_operation(uint8_t *buf, int len, int sid, struct file_context *ctx)
|
||||
{
|
||||
buffer_put_u8(&rtty->wb, MSG_TYPE_FILE);
|
||||
buffer_put_u16be(&rtty->wb, 2);
|
||||
buffer_put_u8(&rtty->wb, rtty->file_context.sid);
|
||||
buffer_put_u8(&rtty->wb, RTTY_FILE_MSG_CANCELED);
|
||||
ev_io_start(rtty->loop, &rtty->iow);
|
||||
struct rtty *rtty = container_of(ctx, struct rtty, file_context);
|
||||
struct file_control_msg msg = {};
|
||||
char fifo_name[128];
|
||||
pid_t pid;
|
||||
int ctlfd;
|
||||
|
||||
if (len != 12)
|
||||
return false;
|
||||
|
||||
if (memcmp(buf, RTTY_FILE_MAGIC, 3))
|
||||
return false;
|
||||
|
||||
memcpy(&pid, buf + 4, 4);
|
||||
|
||||
memset(abspath, 0, sizeof(abspath));
|
||||
getcwd_pid(pid, abspath, sizeof(abspath) - 1);
|
||||
|
||||
sprintf(fifo_name, "/tmp/rtty-file-%d.fifo", pid);
|
||||
|
||||
ctlfd = open(fifo_name, O_WRONLY);
|
||||
if (ctlfd < 0) {
|
||||
log_err("Could not open fifo %s\n", fifo_name);
|
||||
kill(pid, SIGTERM);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ctx->busy) {
|
||||
msg.type = RTTY_FILE_MSG_BUSY;
|
||||
|
||||
send_file_control_msg(ctlfd, &msg);
|
||||
close(ctlfd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (buf[3] == 'R') {
|
||||
msg.type = RTTY_FILE_MSG_REQUEST_ACCEPT;
|
||||
|
||||
buffer_put_u8(&rtty->wb, MSG_TYPE_FILE);
|
||||
buffer_put_u16be(&rtty->wb, 2);
|
||||
buffer_put_u8(&rtty->wb, ctx->sid);
|
||||
buffer_put_u8(&rtty->wb, RTTY_FILE_MSG_START_DOWNLOAD);
|
||||
ev_io_start(rtty->loop, &rtty->iow);
|
||||
|
||||
send_file_control_msg(ctlfd, &msg);
|
||||
} else {
|
||||
char path[PATH_MAX] = "";
|
||||
char link[128];
|
||||
int fd;
|
||||
|
||||
memcpy(&fd, buf + 8, 4);
|
||||
|
||||
sprintf(link, "/proc/%d/fd/%d", pid, fd);
|
||||
|
||||
if (readlink(link, path, sizeof(path) - 1) < 0) {
|
||||
log_err("readlink: %s\n", strerror(errno));
|
||||
|
||||
msg.type = RTTY_FILE_MSG_ERR;
|
||||
|
||||
send_file_control_msg(ctlfd, &msg);
|
||||
close(ctlfd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
msg.type = RTTY_FILE_MSG_REQUEST_ACCEPT;
|
||||
send_file_control_msg(ctlfd, &msg);
|
||||
|
||||
if (start_upload_file(ctx, path) < 0) {
|
||||
msg.type = RTTY_FILE_MSG_ERR;
|
||||
|
||||
send_file_control_msg(ctlfd, &msg);
|
||||
close(ctlfd);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->sid = sid;
|
||||
ctx->ctlfd = ctlfd;
|
||||
ctx->busy = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void start_download_file(struct file_context *ctx, struct buffer *info, int len)
|
||||
{
|
||||
struct rtty *rtty = container_of(ctx, struct rtty, file_context);
|
||||
struct file_control_msg msg = {};
|
||||
struct mntent *ment;
|
||||
struct statvfs sfs;
|
||||
char *name;
|
||||
@@ -144,15 +275,18 @@ static void start_download_file(struct file_context *ctx, struct buffer *info, i
|
||||
ment = find_mount_point(abspath);
|
||||
if (ment) {
|
||||
if (statvfs(ment->mnt_dir, &sfs) == 0 && ctx->total_size > sfs.f_bavail * sfs.f_frsize) {
|
||||
uint8_t type = RTTY_FILE_MSG_NO_SPACE;
|
||||
msg.type = RTTY_FILE_MSG_NO_SPACE;
|
||||
|
||||
notify_user_canceled(rtty);
|
||||
|
||||
send_file_control_msg(ctx->ctlfd, &msg);
|
||||
|
||||
send_canceled_msg(rtty);
|
||||
sendto(ctx->sock, &type, 1, 0, (struct sockaddr *) &ctx->peer_sun, sizeof(struct sockaddr_un));
|
||||
log_err("download file fail: no enough space\n");
|
||||
goto free_name;
|
||||
}
|
||||
}
|
||||
|
||||
strcat(abspath, "/");
|
||||
strcat(abspath, name);
|
||||
|
||||
fd = open(abspath, O_WRONLY | O_TRUNC | O_CREAT, 0644);
|
||||
@@ -161,248 +295,68 @@ static void start_download_file(struct file_context *ctx, struct buffer *info, i
|
||||
goto free_name;
|
||||
}
|
||||
|
||||
ctx->fd = fd;
|
||||
|
||||
log_info("download file: %s, size: %u\n", abspath, ctx->total_size);
|
||||
|
||||
buffer_truncate(&b, 0);
|
||||
buffer_put_u8(&b, RTTY_FILE_MSG_INFO);
|
||||
buffer_put_string(&b, name);
|
||||
buffer_put_zero(&b, 1);
|
||||
sendto(ctx->sock, buffer_data(&b), buffer_length(&b), 0,
|
||||
(struct sockaddr *)&ctx->peer_sun, sizeof(struct sockaddr_un));
|
||||
if (ctx->total_size == 0)
|
||||
close(fd);
|
||||
else
|
||||
ctx->fd = fd;
|
||||
|
||||
msg.type = RTTY_FILE_MSG_INFO;
|
||||
memcpy(msg.buf, &ctx->total_size, 4);
|
||||
strcpy((char *)msg.buf + 4, name);
|
||||
|
||||
send_file_control_msg(ctx->ctlfd, &msg);
|
||||
|
||||
free_name:
|
||||
free(name);
|
||||
}
|
||||
|
||||
static void notify_busy(struct file_context *ctx)
|
||||
{
|
||||
uint8_t type = RTTY_FILE_MSG_BUSY;
|
||||
|
||||
log_err("upload file is busy\n");
|
||||
sendto(ctx->sock, &type, 1, 0,
|
||||
(struct sockaddr *)&ctx->peer_sun, sizeof(struct sockaddr_un));
|
||||
}
|
||||
|
||||
static void on_socket_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
struct file_context *ctx = container_of(w, struct file_context, ios);
|
||||
struct rtty *rtty = container_of(ctx, struct rtty, file_context);
|
||||
int type = read_file_msg(w->fd, &b);
|
||||
|
||||
switch (type) {
|
||||
case RTTY_FILE_MSG_INFO:
|
||||
start_upload_file(ctx, &b);
|
||||
break;
|
||||
case RTTY_FILE_MSG_CANCELED:
|
||||
if (ctx->fd > -1) {
|
||||
close(ctx->fd);
|
||||
ctx->fd = -1;
|
||||
ev_io_stop(loop, &ctx->iof);
|
||||
}
|
||||
|
||||
ctx->busy = false;
|
||||
send_canceled_msg(rtty);
|
||||
break;
|
||||
case RTTY_FILE_MSG_SAVE_PATH:
|
||||
strcpy(abspath, buffer_data(&b));
|
||||
strcat(abspath, "/");
|
||||
buffer_put_u8(&rtty->wb, MSG_TYPE_FILE);
|
||||
buffer_put_u16be(&rtty->wb, 2);
|
||||
buffer_put_u8(&rtty->wb, ctx->sid);
|
||||
buffer_put_u8(&rtty->wb, RTTY_FILE_MSG_START_DOWNLOAD);
|
||||
ev_io_start(loop, &rtty->iow);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int start_file_service(struct file_context *ctx)
|
||||
void parse_file_msg(struct file_context *ctx, struct buffer *data, int len)
|
||||
{
|
||||
struct rtty *rtty = container_of(ctx, struct rtty, file_context);
|
||||
struct sockaddr_un sun = {
|
||||
.sun_family = AF_UNIX
|
||||
};
|
||||
int sock;
|
||||
struct file_control_msg msg = {};
|
||||
int type = buffer_pull_u8(data);
|
||||
|
||||
if (strlen(RTTY_FILE_UNIX_SOCKET_S) >= sizeof(sun.sun_path)) {
|
||||
log_err("unix socket path too long\n");
|
||||
return -1;
|
||||
}
|
||||
len--;
|
||||
|
||||
sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
|
||||
if (sock < 0) {
|
||||
log_err("create socket fail: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(sun.sun_path, RTTY_FILE_UNIX_SOCKET_S);
|
||||
|
||||
unlink(RTTY_FILE_UNIX_SOCKET_S);
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
|
||||
log_err("bind socket fail: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
ev_io_init(&ctx->ios, on_socket_read, sock, EV_READ);
|
||||
ev_io_start(rtty->loop, &ctx->ios);
|
||||
|
||||
ctx->fd = -1;
|
||||
ctx->sock = sock;
|
||||
ctx->peer_sun.sun_family = AF_UNIX;
|
||||
strcpy(ctx->peer_sun.sun_path, RTTY_FILE_UNIX_SOCKET_C);
|
||||
|
||||
return sock;
|
||||
|
||||
err:
|
||||
if (sock > -1)
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void parse_file_msg(struct file_context *ctx, uint8_t type, struct buffer *data, int len)
|
||||
{
|
||||
switch (type) {
|
||||
case RTTY_FILE_MSG_INFO:
|
||||
start_download_file(ctx, data, len);
|
||||
break;
|
||||
case RTTY_FILE_MSG_DATA:
|
||||
if (ctx->fd > -1) {
|
||||
buffer_pull_to_fd(data, ctx->fd, len);
|
||||
ctx->remain_size -= len;
|
||||
notify_progress(ctx);
|
||||
} else {
|
||||
buffer_pull(data, NULL, len);
|
||||
}
|
||||
|
||||
if (len == 0 && ctx->fd > -1) {
|
||||
case RTTY_FILE_MSG_DATA:
|
||||
if (len > 0) {
|
||||
if (ctx->fd > -1) {
|
||||
buffer_pull_to_fd(data, ctx->fd, len);
|
||||
ctx->remain_size -= len;
|
||||
|
||||
if (notify_progress(ctx) < 0) {
|
||||
notify_user_canceled(rtty);
|
||||
file_context_reset(ctx);
|
||||
}
|
||||
} else {
|
||||
buffer_pull(data, NULL, len);
|
||||
}
|
||||
} else {
|
||||
file_context_reset(ctx);
|
||||
}
|
||||
break;
|
||||
|
||||
case RTTY_FILE_MSG_CANCELED:
|
||||
if (ctx->fd > -1) {
|
||||
close(ctx->fd);
|
||||
ctx->fd = -1;
|
||||
ctx->busy = false;
|
||||
}
|
||||
break;
|
||||
case RTTY_FILE_MSG_CANCELED:
|
||||
if (ctx->fd > -1)
|
||||
close(ctx->fd);
|
||||
ctx->fd = -1;
|
||||
|
||||
msg.type = RTTY_FILE_MSG_CANCELED;
|
||||
send_file_control_msg(ctx->ctlfd, &msg);
|
||||
close(ctx->ctlfd);
|
||||
|
||||
ctx->busy = false;
|
||||
sendto(ctx->sock, &type, 1, 0, (struct sockaddr *) &ctx->peer_sun, sizeof(struct sockaddr_un));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int connect_rtty_file_service()
|
||||
{
|
||||
struct sockaddr_un sun = { .sun_family = AF_UNIX };
|
||||
int sock = -1;
|
||||
|
||||
sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
|
||||
if (sock < 0) {
|
||||
fprintf(stderr, "create socket fail: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(sun.sun_path, RTTY_FILE_UNIX_SOCKET_C);
|
||||
|
||||
unlink(RTTY_FILE_UNIX_SOCKET_C);
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
|
||||
log_err("bind socket fail: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
strcpy(sun.sun_path, RTTY_FILE_UNIX_SOCKET_S);
|
||||
|
||||
if (connect(sock, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
|
||||
fprintf(stderr, "connect to rtty fail: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
return sock;
|
||||
|
||||
err:
|
||||
if (sock > -1)
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void request_transfer_file()
|
||||
{
|
||||
fwrite(RTTY_FILE_MAGIC, sizeof(RTTY_FILE_MAGIC), 1, stdout);
|
||||
fflush(stdout);
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
static void accept_file_request(struct file_context *ctx)
|
||||
{
|
||||
uint8_t type = RTTY_FILE_MSG_REQUEST_ACCEPT;
|
||||
|
||||
ctx->fd = -1;
|
||||
ctx->busy = true;
|
||||
ctx->last_notify_progress = 0;
|
||||
sendto(ctx->sock, &type, 1, 0,
|
||||
(struct sockaddr *)&ctx->peer_sun, sizeof(struct sockaddr_un));
|
||||
}
|
||||
|
||||
bool detect_file_operation(uint8_t *buf, int len, int sid, struct file_context *ctx)
|
||||
{
|
||||
if (len != 3)
|
||||
return false;
|
||||
|
||||
if (memcmp(buf, RTTY_FILE_MAGIC, sizeof(RTTY_FILE_MAGIC)))
|
||||
return false;
|
||||
|
||||
ctx->sid = sid;
|
||||
|
||||
if (ctx->busy) {
|
||||
notify_busy(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
accept_file_request(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void update_progress(struct ev_loop *loop, ev_tstamp start_time, struct buffer *info)
|
||||
{
|
||||
uint32_t remain = buffer_pull_u32(info);
|
||||
uint32_t total = buffer_pull_u32(info);
|
||||
|
||||
if (total == 0)
|
||||
goto done;
|
||||
|
||||
printf("%100c\r", ' ');
|
||||
printf(" %lu%% %s %.3lfs\r", (total - remain) * 100UL / total,
|
||||
format_size(total - remain), ev_now(loop) - start_time);
|
||||
fflush(stdout);
|
||||
|
||||
if (remain > 0)
|
||||
return;
|
||||
|
||||
done:
|
||||
ev_break(loop, EVBREAK_ALL);
|
||||
puts("");
|
||||
}
|
||||
|
||||
void cancel_file_operation(struct ev_loop *loop, int sock)
|
||||
{
|
||||
uint8_t type = RTTY_FILE_MSG_CANCELED;
|
||||
send(sock, &type, 1, 0);;
|
||||
ev_break(loop, EVBREAK_ALL);
|
||||
puts("");
|
||||
}
|
||||
|
||||
int read_file_msg(int sock, struct buffer *out)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
int ret = read(sock, buf, sizeof(buf));
|
||||
buffer_truncate(out, 0);
|
||||
buffer_put_data(out, buf, ret);
|
||||
return buffer_pull_u8(out);
|
||||
}
|
||||
|
||||
29
src/file.h
29
src/file.h
@@ -26,7 +26,6 @@
|
||||
#define RTTY_FILE_H
|
||||
|
||||
#include <ev.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
@@ -38,37 +37,31 @@ enum {
|
||||
RTTY_FILE_MSG_BUSY,
|
||||
RTTY_FILE_MSG_PROGRESS,
|
||||
RTTY_FILE_MSG_REQUEST_ACCEPT,
|
||||
RTTY_FILE_MSG_SAVE_PATH,
|
||||
RTTY_FILE_MSG_NO_SPACE
|
||||
RTTY_FILE_MSG_NO_SPACE,
|
||||
RTTY_FILE_MSG_ERR
|
||||
};
|
||||
|
||||
struct file_control_msg {
|
||||
int type;
|
||||
uint8_t buf[128];
|
||||
};
|
||||
|
||||
struct file_context {
|
||||
int sid;
|
||||
int fd;
|
||||
int sock;
|
||||
bool busy;
|
||||
int ctlfd;
|
||||
uint32_t total_size;
|
||||
uint32_t remain_size;
|
||||
struct sockaddr_un peer_sun;
|
||||
struct ev_io ios; /* used for unix socket */
|
||||
struct ev_io iof; /* used for upload file */
|
||||
ev_tstamp last_notify_progress;
|
||||
};
|
||||
|
||||
int start_file_service(struct file_context *ctx);
|
||||
void request_transfer_file(char type, const char *path);
|
||||
|
||||
void parse_file_msg(struct file_context *ctx, uint8_t type, struct buffer *data, int len);
|
||||
|
||||
void update_progress(struct ev_loop *loop, ev_tstamp start_time, struct buffer *info);
|
||||
|
||||
void cancel_file_operation(struct ev_loop *loop, int sock);
|
||||
|
||||
int read_file_msg(int sock, struct buffer *out);
|
||||
|
||||
int connect_rtty_file_service();
|
||||
|
||||
void request_transfer_file();
|
||||
bool detect_file_operation(uint8_t *buf, int len, int sid, struct file_context *ctx);
|
||||
|
||||
void parse_file_msg(struct file_context *ctx, struct buffer *data, int len);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
213
src/filectl.c
Normal file
213
src/filectl.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "file.h"
|
||||
|
||||
static uint8_t RTTY_FILE_MAGIC[12] = {0xb6, 0xbc, 0xbd};
|
||||
|
||||
static struct timeval start_time;
|
||||
|
||||
static uint32_t total_size;
|
||||
|
||||
static char fifo_name[128];
|
||||
|
||||
static void clear_fifo()
|
||||
{
|
||||
unlink(fifo_name);
|
||||
}
|
||||
|
||||
static void signal_handler(int sig)
|
||||
{
|
||||
puts("");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static u_int32_t update_progress(uint8_t *buf)
|
||||
{
|
||||
struct timeval now;
|
||||
uint32_t remain;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
memcpy(&remain, buf, 4);
|
||||
|
||||
printf("%100c\r", ' ');
|
||||
printf(" %lu%% %s %.3fs\r", (total_size - remain) * 100UL / total_size,
|
||||
format_size(total_size - remain),
|
||||
(now.tv_sec + now.tv_usec / 1000.0 / 1000) - (start_time.tv_sec + start_time.tv_usec / 1000.0 / 1000));
|
||||
fflush(stdout);
|
||||
|
||||
return remain;
|
||||
}
|
||||
|
||||
static void handle_file_control_msg(int fd, int sfd)
|
||||
{
|
||||
struct file_control_msg msg;
|
||||
struct buffer b = {};
|
||||
|
||||
while (true) {
|
||||
if (buffer_put_fd(&b, fd, -1, NULL) < 0)
|
||||
break;
|
||||
|
||||
if (buffer_length(&b) < sizeof(msg))
|
||||
continue;
|
||||
|
||||
buffer_pull(&b, &msg, sizeof(msg));
|
||||
|
||||
switch (msg.type) {
|
||||
case RTTY_FILE_MSG_REQUEST_ACCEPT:
|
||||
if (sfd > -1)
|
||||
close(sfd);
|
||||
else
|
||||
printf("Waiting to receive. Press Ctrl+C to cancel\n");
|
||||
break;
|
||||
|
||||
case RTTY_FILE_MSG_INFO:
|
||||
memcpy(&total_size, msg.buf, 4);
|
||||
|
||||
printf("Transferring '%s'...\n", (char *)(msg.buf + 4));
|
||||
|
||||
if (total_size == 0) {
|
||||
printf(" 100%% 0 B 0s\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
|
||||
break;
|
||||
|
||||
case RTTY_FILE_MSG_PROGRESS:
|
||||
if (update_progress(msg.buf) == 0) {
|
||||
puts("");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
case RTTY_FILE_MSG_CANCELED:
|
||||
puts("");
|
||||
goto done;
|
||||
|
||||
case RTTY_FILE_MSG_BUSY:
|
||||
printf("\033[31mRtty is busy to transfer file\033[0m\n");
|
||||
goto done;
|
||||
|
||||
case RTTY_FILE_MSG_NO_SPACE:
|
||||
printf("\033[31mNo enough space\033[0m\n");
|
||||
goto done;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
buffer_free(&b);
|
||||
}
|
||||
|
||||
void request_transfer_file(char type, const char *path)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
struct stat st;
|
||||
int sfd = -1;
|
||||
int ctlfd;
|
||||
|
||||
sprintf(fifo_name, "/tmp/rtty-file-%d.fifo", pid);
|
||||
|
||||
if (mkfifo(fifo_name, 0644) < 0) {
|
||||
fprintf(stderr, "Could not create fifo %s\n", fifo_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
atexit(clear_fifo);
|
||||
|
||||
usleep(10000);
|
||||
|
||||
RTTY_FILE_MAGIC[3] = type;
|
||||
|
||||
memcpy(RTTY_FILE_MAGIC + 4, &pid, 4);
|
||||
|
||||
if (type == 'S') {
|
||||
sfd = open(path, O_RDONLY);
|
||||
if (sfd < 0) {
|
||||
printf("open '%s' failed: ", path);
|
||||
if (errno == ENOENT)
|
||||
printf("No such file\n");
|
||||
else
|
||||
printf("%s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
fstat(sfd, &st);
|
||||
if (!(st.st_mode & S_IFREG)) {
|
||||
printf("'%s' is not a regular file\n", path);
|
||||
close(sfd);
|
||||
return;
|
||||
}
|
||||
|
||||
total_size = st.st_size;
|
||||
|
||||
memcpy(RTTY_FILE_MAGIC + 8, &sfd, 4);
|
||||
}
|
||||
|
||||
fwrite(RTTY_FILE_MAGIC, sizeof(RTTY_FILE_MAGIC), 1, stdout);
|
||||
fflush(stdout);
|
||||
|
||||
ctlfd = open(fifo_name, O_RDONLY | O_NONBLOCK);
|
||||
if (ctlfd < 0) {
|
||||
fprintf(stderr, "Could not open fifo %s\n", fifo_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (type == 'S') {
|
||||
usleep(1000 * 10);
|
||||
printf("Transferring '%s'...Press Ctrl+C to cancel\n", basename(path));
|
||||
|
||||
if (total_size == 0) {
|
||||
printf(" 100%% 0 B 0s\n");
|
||||
|
||||
close(sfd);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
}
|
||||
|
||||
handle_file_control_msg(ctlfd, sfd);
|
||||
|
||||
done:
|
||||
close(ctlfd);
|
||||
}
|
||||
@@ -30,8 +30,6 @@
|
||||
#include "log.h"
|
||||
#include "rtty.h"
|
||||
#include "config.h"
|
||||
#include "upfile.h"
|
||||
#include "downfile.h"
|
||||
|
||||
enum {
|
||||
LONG_OPT_HELP = 1
|
||||
@@ -132,10 +130,10 @@ int main(int argc, char **argv)
|
||||
rtty.username = optarg;
|
||||
break;
|
||||
case 'R':
|
||||
download_file();
|
||||
request_transfer_file('R', NULL);
|
||||
return 0;
|
||||
case 'S':
|
||||
upload_file(optarg);
|
||||
request_transfer_file('S', optarg);
|
||||
return 0;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
@@ -152,6 +150,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (background && daemon(0, 0))
|
||||
log_err("Can't run in the background: %s\n", strerror(errno));
|
||||
|
||||
|
||||
@@ -335,7 +335,7 @@ static int parse_msg(struct rtty *rtty)
|
||||
break;
|
||||
|
||||
case MSG_TYPE_FILE:
|
||||
parse_file_msg(&rtty->file_context, buffer_pull_u8(rb), rb, msglen - 1);
|
||||
parse_file_msg(&rtty->file_context, rb, msglen);
|
||||
break;
|
||||
|
||||
case MSG_TYPE_WEB:
|
||||
@@ -504,7 +504,7 @@ int rtty_start(struct rtty *rtty)
|
||||
&& !rtty->reconnect)
|
||||
return -1;
|
||||
|
||||
start_file_service(&rtty->file_context);
|
||||
rtty->file_context.fd = -1;
|
||||
|
||||
INIT_LIST_HEAD(&rtty->web_reqs);
|
||||
|
||||
|
||||
122
src/upfile.c
122
src/upfile.c
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "file.h"
|
||||
|
||||
static ev_tstamp start_time;
|
||||
static char abspath[PATH_MAX];
|
||||
static uint32_t file_size;
|
||||
static struct buffer b;
|
||||
static int sock;
|
||||
|
||||
static void signal_cb(struct ev_loop *loop, ev_signal *w, int revents)
|
||||
{
|
||||
cancel_file_operation(loop, sock);
|
||||
}
|
||||
|
||||
static void on_socket_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
int type = read_file_msg(w->fd, &b);
|
||||
|
||||
switch (type) {
|
||||
case RTTY_FILE_MSG_REQUEST_ACCEPT:
|
||||
buffer_put_u8(&b, RTTY_FILE_MSG_INFO);
|
||||
buffer_put_u32(&b, file_size);
|
||||
buffer_put_string(&b, abspath);
|
||||
buffer_put_zero(&b, 1);
|
||||
buffer_pull_to_fd(&b, w->fd, -1);
|
||||
start_time = ev_now(loop);
|
||||
break;
|
||||
case RTTY_FILE_MSG_PROGRESS:
|
||||
update_progress(loop, start_time, &b);
|
||||
break;
|
||||
case RTTY_FILE_MSG_BUSY:
|
||||
fprintf(stderr, "\033[31mRtty is busy\033[0m\n");
|
||||
ev_break(loop, EVBREAK_ALL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void upload_file(const char *path)
|
||||
{
|
||||
struct ev_loop *loop = EV_DEFAULT;
|
||||
struct ev_signal sw;
|
||||
struct ev_io ior;
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
if (getuid() > 0) {
|
||||
fprintf(stderr, "Operation not permitted, must be run as root\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "open '%s' failed: ", path);
|
||||
if (errno == ENOENT)
|
||||
fprintf(stderr, "No such file\n");
|
||||
else
|
||||
fprintf(stderr, "%s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
fstat(fd, &st);
|
||||
if (!(st.st_mode & S_IFREG)) {
|
||||
fprintf(stderr, "'%s' is not a regular file\n", path);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
file_size = st.st_size;
|
||||
|
||||
sock = connect_rtty_file_service();
|
||||
if (sock < 0)
|
||||
return;
|
||||
|
||||
if (!realpath(path, abspath))
|
||||
return;
|
||||
|
||||
request_transfer_file();
|
||||
|
||||
ev_io_init(&ior, on_socket_read, sock, EV_READ);
|
||||
ev_io_start(loop, &ior);
|
||||
|
||||
ev_signal_init(&sw, signal_cb, SIGINT);
|
||||
ev_signal_start(loop, &sw);
|
||||
|
||||
printf("Transferring '%s'...Press Ctrl+C to cancel\n", basename(path));
|
||||
|
||||
ev_run(loop, 0);
|
||||
|
||||
buffer_free(&b);
|
||||
close(sock);
|
||||
}
|
||||
30
src/upfile.h
30
src/upfile.h
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef RTTY_UPFILE_H_
|
||||
#define RTTY_UPFILE_H_
|
||||
|
||||
void upload_file(const char *path);
|
||||
|
||||
#endif
|
||||
14
src/utils.c
14
src/utils.c
@@ -28,6 +28,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
@@ -154,3 +155,16 @@ struct mntent *find_mount_point(const char *name)
|
||||
|
||||
return ment;
|
||||
}
|
||||
|
||||
/*
|
||||
* getcwd_pid does not append a null byte to buf. It will (silently) truncate the contents (to
|
||||
* a length of bufsiz characters), in case the buffer is too small to hold all of the contents.
|
||||
*/
|
||||
ssize_t getcwd_pid(pid_t pid, char *buf, size_t bufsiz)
|
||||
{
|
||||
char link[128];
|
||||
|
||||
sprintf(link, "/proc/%d/cwd", pid);
|
||||
|
||||
return readlink(link, buf, bufsiz);
|
||||
}
|
||||
@@ -38,4 +38,6 @@ const char *format_size(size_t size);
|
||||
|
||||
struct mntent *find_mount_point(const char *name);
|
||||
|
||||
ssize_t getcwd_pid(pid_t pid, char *buf, size_t bufsiz);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user