/* * Project Acrn * Acrn-dm-pty * * Copyright (C) 2019-2022 Intel Corporation. * * SPDX-License-Identifier: BSD-3-Clause * */ #include #include #include #include #include #include #include #include #include #include #include #include "log.h" /* * Check and create the directory. * To avoid symlink failure if the directory does not exist. */ static int check_dir(const char *file) { char *tmp, *dir; tmp = strdup(file); if (!tmp) { pr_err("failed to dup file, error:%s\n", strerror(errno)); return -1; } dir = dirname(tmp); if (access(dir, F_OK) && mkdir(dir, 0666)) { pr_err("failed to create dir:%s, erorr:%s\n", dir, strerror(errno)); free(tmp); return -1; } free(tmp); return 0; } /* * Open PTY host device to used by caller and the PTY client device for virtual * UART. The pair(host/client) can work as a communication channel between * the caller and virtual UART. */ int pty_open_virtual_uart(const char *dev_name) { int fd; char *client_name; struct termios attr; fd = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) goto open_err; if (grantpt(fd) < 0) goto pty_err; if (unlockpt(fd) < 0) goto pty_err; client_name = ptsname(fd); if (!client_name) goto pty_err; if ((unlink(dev_name) < 0) && errno != ENOENT) goto pty_err; /* * The check_dir restriction is that only create one directory * not support multi-level directroy. */ if (check_dir(dev_name) < 0) goto pty_err; if (symlink(client_name, dev_name) < 0) goto pty_err; if (chmod(dev_name, 0660) < 0) goto attr_err; if (tcgetattr(fd, &attr) < 0) goto attr_err; cfmakeraw(&attr); attr.c_cflag |= CLOCAL; if (tcsetattr(fd, TCSANOW, &attr) < 0) goto attr_err; return fd; attr_err: unlink(dev_name); pty_err: close(fd); open_err: return -1; }