11b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes/* 21b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * Copyright (C) 2015 The Android Open Source Project 31b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * 41b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 51b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * you may not use this file except in compliance with the License. 61b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * You may obtain a copy of the License at 71b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * 81b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 91b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * 101b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * Unless required by applicable law or agreed to in writing, software 111b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 121b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * See the License for the specific language governing permissions and 141b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes * limitations under the License. 151b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes */ 161b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 171b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include "diagnose_usb.h" 181b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 191b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include <errno.h> 201b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include <unistd.h> 211b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 221b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include <string> 231b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 241b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include <android-base/stringprintf.h> 251b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 261b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#if defined(__linux__) 271b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include <grp.h> 281b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#endif 291b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 301b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughesstatic const char kPermissionsHelpUrl[] = "http://developer.android.com/tools/device.html"; 311b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 321b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes// Returns a message describing any potential problems we find with udev, or nullptr if we can't 331b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes// find plugdev information (i.e. udev is not installed). 341b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughesstatic const char* GetUdevProblem() { 351b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#if defined(__linux__) 361b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes errno = 0; 371b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes group* plugdev_group = getgrnam("plugdev"); 381b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 391b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes if (plugdev_group == nullptr) { 401b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes if (errno != 0) { 411b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes perror("failed to read plugdev group info"); 421b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes } 431b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes // We can't give any generally useful advice here, just let the caller print the help URL. 441b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes return nullptr; 451b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes } 461b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 471b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes // getgroups(2) indicates that the group_member() may not check the egid so we check it 481b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes // additionally just to be sure. 491b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes if (group_member(plugdev_group->gr_gid) || getegid() == plugdev_group->gr_gid) { 501b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes // The user is in plugdev so the problem is likely with the udev rules. 511b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes return "verify udev rules"; 521b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes } 531b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes return "udev requires plugdev group membership"; 541b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#else 551b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes return nullptr; 561b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#endif 571b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes} 581b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 591b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes// Short help text must be a single line, and will look something like: 601b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes// no permissions (reason); see <URL> 611b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughesstd::string UsbNoPermissionsShortHelpText() { 621b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes std::string help_text = "no permissions"; 631b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 641b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes const char* problem = GetUdevProblem(); 651b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes if (problem != nullptr) { 661b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes help_text += android::base::StringPrintf(" (%s)", problem); 671b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes } 681b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 691b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes return android::base::StringPrintf("%s; see [%s]", help_text.c_str(), kPermissionsHelpUrl); 701b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes} 711b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 721b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes// Long help text can span multiple lines and should provide more detailed information. 731b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughesstd::string UsbNoPermissionsLongHelpText() { 741b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes std::string header = "insufficient permissions for device"; 751b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 761b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes const char* problem = GetUdevProblem(); 771b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes if (problem != nullptr) { 781b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes header += android::base::StringPrintf(": %s", problem); 791b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes } 801b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes 811b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes return android::base::StringPrintf("%s.\nSee [%s] for more information.", 821b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes header.c_str(), kPermissionsHelpUrl); 831b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes} 84