Skip to content

Commit

Permalink
Sanity checks on serial port
Browse files Browse the repository at this point in the history
  • Loading branch information
Ricc68 committed Jan 6, 2025
1 parent c33946f commit 90b3245
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 0 deletions.
76 changes: 76 additions & 0 deletions lib/util/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import path from 'node:path';

import equals from 'fast-deep-equal/es6';
import humanizeDuration from 'humanize-duration';
import logger from './logger';

import { globSync } from 'glob';

import data from './data';

Expand Down Expand Up @@ -395,6 +398,78 @@ function saveBase64DeviceIcon(base64Match: {extension: string; data: string}): s
return fileSettings;
}

function checkSerial(serialPath: string): boolean {
var realPath: string;

// If it is a network path, ignore
if (serialPath.indexOf('tcp://') === 0) {
return true;
}

// Throw an error in case of non existent file
try {
// Extract the real device file if it is a symlink
if (fs.lstatSync(serialPath).isSymbolicLink()) {
realPath = fs.readlinkSync(serialPath);
} else {
realPath = serialPath;
}
logger.info(`Checking serial port: '${serialPath}' ['${realPath}']`);
// Now check the existence of the real file
fs.statSync(realPath);
} catch (error) {
logger.error(`Unable to find serial port device, check configuration.yaml`);
throw error;
return false;
}

// Check if /proc filesystem is available otherwise skip further checks
try {
const procFile = `/proc/cpuinfo`;

fs.statSync(procFile);
} catch (error) {
logger.debug(`/proc filesystem unavailable, skipping further checks`);
return true;
}

// Obtain a list of open files from /proc filesystem: returned files are symlinks to real files
const procFolders = `/proc/*/fd/*`;
const openSymlinks = globSync(procFolders);

// Traverse the list of open files symlinks
for (const openSymlink of openSymlinks) {
var openFile: string;

// ignore all open files related to self process (it's ourself or one of our thread)
if (openSymlink.includes('self') === true) {
continue;
}

// Extract the PID from the symlink path
const pathElements = openSymlink.split('/');
const openFilePid = pathElements[2];

// Follow the symlink to detect the real open file path
try {
openFile = fs.readlinkSync(openSymlink);
} catch (error) {
// Ignore errors while traversing symlinks because files may be closed between glob and readlink
continue;
}

// Check if serial file is already opened by another process
if (openFile === realPath) {
const exeSymlink = '/proc/' + openFilePid + '/exe';
const exeFile = fs.readlinkSync(exeSymlink);
logger.error(`Serial port device is opened by process '${exeFile}' with PID '${openFilePid}'`);
throw new Error();
return false;
}
}
return true;
}

/* v8 ignore next */
const noop = (): void => {};

Expand Down Expand Up @@ -429,5 +504,6 @@ export default {
arrayUnique,
getScenes,
deviceNotCoordinator,
checkSerial,
noop,
};
7 changes: 7 additions & 0 deletions lib/zigbee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ export default class Zigbee {
acceptJoiningDeviceHandler: this.acceptJoiningDeviceHandler,
};

try {
utils.checkSerial(`${herdsmanSettings.serialPort.path}`);
} catch (error) {
logger.error(`Error while checking serial port`);
throw error;
}

logger.debug(
() =>
`Using zigbee-herdsman with settings: '${stringify(JSON.stringify(herdsmanSettings).replaceAll(JSON.stringify(herdsmanSettings.network.networkKey), '"HIDDEN"'))}'`,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"fast-deep-equal": "^3.1.3",
"finalhandler": "^1.3.1",
"git-last-commit": "^1.0.1",
"glob": "^11.0.0",
"humanize-duration": "^3.32.1",
"js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 90b3245

Please sign in to comment.