github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/libsnap-confine-private/feature.c (about)

     1  /*
     2   * Copyright (C) 2018 Canonical Ltd
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License version 3 as
     6   * published by the Free Software Foundation.
     7   *
     8   * This program is distributed in the hope that it will be useful,
     9   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11   * GNU General Public License for more details.
    12   *
    13   * You should have received a copy of the GNU General Public License
    14   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15   *
    16   */
    17  
    18  #define _GNU_SOURCE
    19  
    20  #include "feature.h"
    21  
    22  #include <errno.h>
    23  #include <fcntl.h>
    24  #include <sys/stat.h>
    25  #include <sys/types.h>
    26  #include <unistd.h>
    27  
    28  #include "cleanup-funcs.h"
    29  #include "utils.h"
    30  
    31  static const char *feature_flag_dir = "/var/lib/snapd/features";
    32  
    33  bool sc_feature_enabled(sc_feature_flag flag)
    34  {
    35  	const char *file_name;
    36  	switch (flag) {
    37  	case SC_FEATURE_PER_USER_MOUNT_NAMESPACE:
    38  		file_name = "per-user-mount-namespace";
    39  		break;
    40  	case SC_FEATURE_REFRESH_APP_AWARENESS:
    41  		file_name = "refresh-app-awareness";
    42  		break;
    43  	case SC_FEATURE_PARALLEL_INSTANCES:
    44  		file_name = "parallel-instances";
    45  		break;
    46  	case SC_FEATURE_HIDDEN_SNAP_FOLDER:
    47  		file_name = "hidden-snap-folder";
    48  		break;
    49  	default:
    50  		die("unknown feature flag code %d", flag);
    51  	}
    52  
    53  	int dirfd SC_CLEANUP(sc_cleanup_close) = -1;
    54  	dirfd =
    55  	    open(feature_flag_dir,
    56  		 O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW | O_PATH);
    57  	if (dirfd < 0 && errno == ENOENT) {
    58  		return false;
    59  	}
    60  	if (dirfd < 0) {
    61  		die("cannot open path %s", feature_flag_dir);
    62  	}
    63  
    64  	struct stat file_info;
    65  	if (fstatat(dirfd, file_name, &file_info, AT_SYMLINK_NOFOLLOW) < 0) {
    66  		if (errno == ENOENT) {
    67  			return false;
    68  		}
    69  		die("cannot inspect file %s/%s", feature_flag_dir, file_name);
    70  	}
    71  
    72  	return S_ISREG(file_info.st_mode);
    73  }