mirror of
https://github.com/tio/tio.git
synced 2026-05-01 14:57:59 +02:00
Add new ways to manage serial devices
* Rename --list-devices to --list
* Rename --no-autoconnect to --no-reconnect
* Switch -l and -L options
* -l now lists available serial devices
* -L enables log to file
* Add option --auto-connect <strategy>
* Supported strategies:
* "new" - Waits to connect first new appearing serial device
* "latest" - Connects to latest registered serial device
* "direct" - Connect directly to specified serial device (default)
* Add options to exclude serial devices from auto connect strategy by
pattern
* Supported exclude options:
* --exclude-devices <pattern>
Example: '--exclude-devices "/dev/ttyUSB2,/dev/ttyS?"'
* --exclude-drivers <pattern>
Example: '--exclude-drivers "cdc_acm"'
* --exclude-tids <pattern>
Example: '--exclude-tids "yW07,bCC2"'
* Patterns support '*' and '?'
* Connect to same port/device combination via unique topology ID (TID)
* Topology ID is a 4 digit base62 encoded hash of a device topology
string coming from the Linux kernel. This means that whenever you
plug in the same e.g. USB serial port device to the same USB hub
port connected via the exact same hub topology all the way to your
computer, you will get the same unique TID.
* Useful for stable reconnections when serial device has no serial
device by ID
* For now, only tested on Linux.
* Reworked and improved listing of serial devices to show serial devices:
* By device
* Including TID, uptime, driver, and description.
* Sorted by uptime (newest device listed last)
* By unique topology ID
* By ID
* By path
* Add script interface 'list = tty_search()' for searching for serial
devices.
This commit is contained in:
parent
ae76f8f58d
commit
d19ba1c492
22 changed files with 1468 additions and 150 deletions
205
src/fs.c
Normal file
205
src/fs.c
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* tio - a serial device I/O tool
|
||||
*
|
||||
* Copyright (c) 2014-2024 Martin Lund
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE // For statx()
|
||||
#include "config.h"
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <regex.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/poll.h>
|
||||
#include <termios.h>
|
||||
#include "error.h"
|
||||
#include "print.h"
|
||||
#include "options.h"
|
||||
|
||||
bool fs_dir_exists(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(path, &st) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!S_ISDIR(st.st_mode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function to read the content of a file but stripped of newline
|
||||
ssize_t fs_read_file_stripped(char *buf, size_t bufsiz, const char *format, ...)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
int bytes_printed = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
bytes_printed = vsnprintf(filename, sizeof(filename), format, args);
|
||||
va_end(args);
|
||||
|
||||
if (bytes_printed < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *file = fopen(filename, "r");
|
||||
if (!file)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
ssize_t length = fread(buf, 1, bufsiz - 1, file);
|
||||
if (length == -1)
|
||||
{
|
||||
fclose(file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Strip any newline
|
||||
buf[strcspn(buf, "\n")] = 0;
|
||||
buf[length] = '\0'; // Make sure to null-terminate the string
|
||||
|
||||
fclose(file);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
bool fs_file_exists(const char *format, ...)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
int bytes_printed = 0;
|
||||
struct stat st;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
bytes_printed = vsnprintf(filename, sizeof(filename), format, args);
|
||||
va_end(args);
|
||||
|
||||
if (bytes_printed < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return stat(filename, &st) == 0;
|
||||
}
|
||||
|
||||
char* fs_search_directory(const char *dir_path, const char *dirname)
|
||||
{
|
||||
struct dirent *entry;
|
||||
char path[PATH_MAX];
|
||||
struct stat st;
|
||||
DIR *dir;
|
||||
|
||||
if ((dir = opendir(dir_path)) == NULL)
|
||||
{
|
||||
// Error opening directory
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
snprintf(path, PATH_MAX, "%s/%s", dir_path, entry->d_name);
|
||||
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lstat(path, &st) == -1)
|
||||
{
|
||||
// Error getting directory status
|
||||
closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (S_ISLNK(st.st_mode))
|
||||
{
|
||||
// Skip symbolic links
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
// If it's a directory, check if it's the one we're looking for
|
||||
if (strcmp(entry->d_name, dirname) == 0)
|
||||
{
|
||||
char* result = malloc(strlen(path) + 1);
|
||||
if (result == NULL)
|
||||
{
|
||||
// Error allocating memory
|
||||
closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(result, path);
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Recursively search within directories
|
||||
char* result = fs_search_directory(path, dirname);
|
||||
if (result != NULL)
|
||||
{
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Function to return creation time of file
|
||||
double fs_get_creation_time(const char *path)
|
||||
{
|
||||
struct statx stx;
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
// Error
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = statx(fd, "", AT_EMPTY_PATH, STATX_ALL, &stx);
|
||||
if (ret == -1)
|
||||
{
|
||||
// Error
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Close the file
|
||||
close(fd);
|
||||
|
||||
return stx.stx_btime.tv_sec + stx.stx_btime.tv_nsec / 1e9;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue