gitee.com/mysnapcore/mysnapd@v0.1.0/snap/helpers.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019-2020 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package snap 21 22 import ( 23 "os/user" 24 "path/filepath" 25 "strconv" 26 "syscall" 27 28 "gitee.com/mysnapcore/mysnapd/dirs" 29 "gitee.com/mysnapcore/mysnapd/snap/naming" 30 ) 31 32 var ( 33 userLookupId = user.LookupId 34 ) 35 36 func IsSnapd(snapID string) bool { 37 return snapID == naming.WellKnownSnapID("snapd") 38 } 39 40 // AllUsers returns a list of users, including the root user and all users that 41 // can be found under /home with a snap directory. 42 func AllUsers(opts *dirs.SnapDirOptions) ([]*user.User, error) { 43 ds, err := filepath.Glob(DataHomeGlob(opts)) 44 if err != nil { 45 // can't happen? 46 return nil, err 47 } 48 49 users := make([]*user.User, 1, len(ds)+1) 50 root, err := user.LookupId("0") 51 if err != nil { 52 return nil, err 53 } 54 users[0] = root 55 seen := make(map[uint32]bool, len(ds)+1) 56 seen[0] = true 57 var st syscall.Stat_t 58 for _, d := range ds { 59 err := syscall.Stat(d, &st) 60 if err != nil { 61 continue 62 } 63 if seen[st.Uid] { 64 continue 65 } 66 seen[st.Uid] = true 67 usr, err := userLookupId(strconv.FormatUint(uint64(st.Uid), 10)) 68 if err != nil { 69 // Treat all non-nil errors as user.Unknown{User,Group}Error's, as 70 // currently Go's handling of returned errno from get{pw,gr}nam_r 71 // in the cgo implementation of user.Lookup is lacking, and thus 72 // user.Unknown{User,Group}Error is returned only when errno is 0 73 // and the list of users/groups is empty, but as per the man page 74 // for get{pw,gr}nam_r, there are many other errno's that typical 75 // systems could return to indicate that the user/group wasn't 76 // found, however unfortunately the POSIX standard does not actually 77 // dictate what errno should be used to indicate "user/group not 78 // found", and so even if Go is more robust, it may not ever be 79 // fully robust. See from the man page: 80 // 81 // > It [POSIX.1-2001] does not call "not found" an error, hence 82 // > does not specify what value errno might have in this situation. 83 // > But that makes it impossible to recognize errors. 84 // 85 // See upstream Go issue: https://github.com/golang/go/issues/40334 86 continue 87 } else { 88 users = append(users, usr) 89 } 90 } 91 92 return users, nil 93 }