/* Copyright (C) 2023 Pasha 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 3 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, see . */ #include "../lib/cgroup_file_handle.h" #include #include #include #include #include #include enum output_pref { DEFAULT = 0, PATH = 1, CGROUPID = 2 }; static inline void print_cgroup_file_handle(const char *pathname, enum output_pref output_type) { unsigned char *cgroupfhp = (unsigned char *)malloc(CGROUP_FILE_HANDLE_BYTES); if (!cgroupfhp) { fprintf(stderr, "Cannot allocate memory for cgroup file handle\n"); return; } if (!get_cgroup_file_handle(pathname, cgroupfhp)) { printf("unable to get cgroup file handle for path %s\n", pathname); free(cgroupfhp); return; } if (output_type != CGROUPID) { printf("cgroupid:\t"); } for (int i = 0; i < CGROUP_FILE_HANDLE_BYTES; ++i) { printf("%02x%s", (unsigned char)cgroupfhp[i], i == 7 ? "\n" : " "); } free(cgroupfhp); } static void print_info(struct cgroup_file_info *info, int len, const char *ctr_path, enum output_pref output_type) { char buffer[FILENAME_MAX]; if (info->type == CGROUP_FILE_TYPE_DIR) { if (info->full_path[len] == '/') { snprintf(buffer, FILENAME_MAX, "%s%s", ctr_path, &info->full_path[len]); } else { snprintf(buffer, FILENAME_MAX, "%s/%s", ctr_path, &info->full_path[len]); } if (output_type == DEFAULT) { printf("cgroup path:\t"); } if (output_type != CGROUPID) { printf("%s\n", buffer); } if (output_type != PATH) { print_cgroup_file_handle(buffer, output_type); } } } static inline void trim_path(char *path) { int len = strlen(path) - 1; while (path[len] == '/') { len--; } path[len + 1] = '\0'; } static inline int compare_cgroup_search_name(const char *info_path, const char *cgroup_search_name) { int info_path_len = strlen(info_path); int search_name_len = strlen(cgroup_search_name); int start_comp_idx = 0; if (info_path_len < search_name_len) { return 0; } else if (info_path_len > search_name_len) { start_comp_idx = info_path_len - search_name_len; } if (!strcmp(&info_path[start_comp_idx], cgroup_search_name)) { return 1; } return 0; } static int display_controller_data(char *ctr_name, char *ctr_path, char *cgroup_search_name, enum output_pref output_type) { void *handle; int ret, base_level, len, depth; struct cgroup_file_info info; char base_path[FILENAME_MAX]; char cgroup_dir_path[FILENAME_MAX]; base_path[0] = '/'; base_path[1] = '\0'; depth = 0; ret = cgroup_walk_tree_begin(ctr_name, base_path, depth, &handle, &info, &base_level); if (ret != 0) return ret; strncpy(cgroup_dir_path, info.full_path, FILENAME_MAX); cgroup_dir_path[sizeof(cgroup_dir_path) - 1] = '\0'; trim_path(cgroup_dir_path); base_path[sizeof(base_path) - 1] = '\0'; trim_path(base_path); len = strlen(cgroup_dir_path) - strlen(base_path); if (compare_cgroup_search_name(info.path, cgroup_search_name)) { print_info(&info, len, ctr_path, output_type); cgroup_walk_tree_end(&handle); return 1; } while ((ret = cgroup_walk_tree_next(depth, &handle, &info, base_level)) == 0) { if (compare_cgroup_search_name(info.path, cgroup_search_name)) { print_info(&info, len, ctr_path, output_type); break; } } cgroup_walk_tree_end(&handle); if (ret == ECGEOF) ret = 0; return ret; } int print_cgroup(char *cgroup_search_name, enum output_pref output_type) { void *handle; int ret = 0; int output = 0; struct cgroup_mount_point cg_mount_point; char ctr_path[FILENAME_MAX]; char ctr_name[FILENAME_MAX]; ctr_path[0] = '\0'; ctr_name[0] = '\0'; ret = cgroup_get_controller_begin(&handle, &cg_mount_point); while (ret == 0) { if (strcmp(ctr_path, cg_mount_point.path)) { // new mount point strncpy(ctr_name, cg_mount_point.name, FILENAME_MAX); ctr_name[sizeof(ctr_name) - 1] = '\0'; strncpy(ctr_path, cg_mount_point.path, FILENAME_MAX); ctr_path[sizeof(ctr_path) - 1] = '\0'; ret = display_controller_data(ctr_name, ctr_path, cgroup_search_name, output_type); if (ret) break; } /* else { printf("same mount point found with name:%s\n", cg_mount_point.name); } */ ret = cgroup_get_controller_next(&handle, &cg_mount_point); } cgroup_get_controller_end(&handle); if (ret == ECGEOF) ret = 0; return ret; } void print_version() { printf("v0.1a\n"); } void usage() { printf("Usage: " "containercgroup container_id\n\n"); printf("containercgroup path container_id\n\n"); printf("containercgroup cgroupid container_id\n\n"); printf("Example: containercgroup " "ac7c62839226963db81ecae66be4457d944b99e1d937ce069225bf3b57bee6f6\n"); printf(" containercgroup $(docker inspect " "--format=\"{{.Id}}\" 6aa6f3065e1c)\n"); printf(" containercgroup path $(docker inspect " "--format=\"{{.Id}}\" 6aa6f3065e1c)\n"); printf(" containercgroup id $(docker inspect " "--format=\"{{.Id}}\" 6aa6f3065e1c)\n"); printf(" containercgroup $(kubectl get pods -o jsonpath='{range " ".items[*].status.containerStatuses[*]}{.containerID}{\"\\n\"}{end}' " "--field-selector metadata.name=test-deployment-7f456874f4-mxjg4 | " "cut -b 10-)\n"); printf("\n"); } int main(int argc, char **argv) { int ret = 0; enum output_pref output_type = DEFAULT; if (argc < 2) { usage(); exit(1); } if (argc == 2 && !strcmp(argv[1], "-v")) { print_version(); } if (argc == 3) { if (strcmp(argv[1], "path") == 0) { output_type = PATH; } else if (strcmp(argv[1], "id") == 0) { output_type = CGROUPID; } else { usage(); exit(1); } } const char *input_search_name = (argc == 3) ? argv[2] : argv[1]; unsigned int input_search_len = strlen(input_search_name); if (input_search_len > FILENAME_MAX) { fprintf(stderr, "invalid container_id\n"); return ret; } // ".scope" 6 + null 1 = 7 char *cgroup_search_name = (char *)malloc(input_search_len + 7); if (!cgroup_search_name) { fprintf(stderr, "Cannot allocate memory.\n"); exit(1); } strcpy(cgroup_search_name, input_search_name); strcat(cgroup_search_name, ".scope"); ret = cgroup_init(); if (ret) { fprintf(stderr, "cgroup initialization failed: %s\n", cgroup_strerror(ret)); free(cgroup_search_name); return ret; } print_cgroup(cgroup_search_name, output_type); free(cgroup_search_name); return 0; }