github.com/dctrud/umoci@v0.4.3-0.20191016193643-05a1d37de015/third_party/user/lookup.go (about)

     1  /*
     2   * Imported from opencontainers/runc/libcontainer/user.
     3   * Copyright (C) 2014 Docker, Inc.
     4   * Copyright (C) The Linux Foundation
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *     http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package user
    20  
    21  import (
    22  	"errors"
    23  	"syscall"
    24  )
    25  
    26  var (
    27  	// The current operating system does not provide the required data for user lookups.
    28  	ErrUnsupported = errors.New("user lookup: operating system does not provide passwd-formatted data")
    29  	// No matching entries found in file.
    30  	ErrNoPasswdEntries = errors.New("no matching entries in passwd file")
    31  	ErrNoGroupEntries  = errors.New("no matching entries in group file")
    32  )
    33  
    34  func lookupUser(filter func(u User) bool) (User, error) {
    35  	// Get operating system-specific passwd reader-closer.
    36  	passwd, err := GetPasswd()
    37  	if err != nil {
    38  		return User{}, err
    39  	}
    40  	defer passwd.Close()
    41  
    42  	// Get the users.
    43  	users, err := ParsePasswdFilter(passwd, filter)
    44  	if err != nil {
    45  		return User{}, err
    46  	}
    47  
    48  	// No user entries found.
    49  	if len(users) == 0 {
    50  		return User{}, ErrNoPasswdEntries
    51  	}
    52  
    53  	// Assume the first entry is the "correct" one.
    54  	return users[0], nil
    55  }
    56  
    57  // CurrentUser looks up the current user by their user id in /etc/passwd. If the
    58  // user cannot be found (or there is no /etc/passwd file on the filesystem),
    59  // then CurrentUser returns an error.
    60  func CurrentUser() (User, error) {
    61  	return LookupUid(syscall.Getuid())
    62  }
    63  
    64  // LookupUser looks up a user by their username in /etc/passwd. If the user
    65  // cannot be found (or there is no /etc/passwd file on the filesystem), then
    66  // LookupUser returns an error.
    67  func LookupUser(username string) (User, error) {
    68  	return lookupUser(func(u User) bool {
    69  		return u.Name == username
    70  	})
    71  }
    72  
    73  // LookupUid looks up a user by their user id in /etc/passwd. If the user cannot
    74  // be found (or there is no /etc/passwd file on the filesystem), then LookupId
    75  // returns an error.
    76  func LookupUid(uid int) (User, error) {
    77  	return lookupUser(func(u User) bool {
    78  		return u.Uid == uid
    79  	})
    80  }
    81  
    82  func lookupGroup(filter func(g Group) bool) (Group, error) {
    83  	// Get operating system-specific group reader-closer.
    84  	group, err := GetGroup()
    85  	if err != nil {
    86  		return Group{}, err
    87  	}
    88  	defer group.Close()
    89  
    90  	// Get the users.
    91  	groups, err := ParseGroupFilter(group, filter)
    92  	if err != nil {
    93  		return Group{}, err
    94  	}
    95  
    96  	// No user entries found.
    97  	if len(groups) == 0 {
    98  		return Group{}, ErrNoGroupEntries
    99  	}
   100  
   101  	// Assume the first entry is the "correct" one.
   102  	return groups[0], nil
   103  }
   104  
   105  // CurrentGroup looks up the current user's group by their primary group id's
   106  // entry in /etc/passwd. If the group cannot be found (or there is no
   107  // /etc/group file on the filesystem), then CurrentGroup returns an error.
   108  func CurrentGroup() (Group, error) {
   109  	return LookupGid(syscall.Getgid())
   110  }
   111  
   112  // LookupGroup looks up a group by its name in /etc/group. If the group cannot
   113  // be found (or there is no /etc/group file on the filesystem), then LookupGroup
   114  // returns an error.
   115  func LookupGroup(groupname string) (Group, error) {
   116  	return lookupGroup(func(g Group) bool {
   117  		return g.Name == groupname
   118  	})
   119  }
   120  
   121  // LookupGid looks up a group by its group id in /etc/group. If the group cannot
   122  // be found (or there is no /etc/group file on the filesystem), then LookupGid
   123  // returns an error.
   124  func LookupGid(gid int) (Group, error) {
   125  	return lookupGroup(func(g Group) bool {
   126  		return g.Gid == gid
   127  	})
   128  }