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

     1  #include "config.h"
     2  #include "classic.h"
     3  #include "../libsnap-confine-private/cleanup-funcs.h"
     4  #include "../libsnap-confine-private/infofile.h"
     5  #include "../libsnap-confine-private/string-utils.h"
     6  
     7  #include <stdbool.h>
     8  #include <stdio.h>
     9  #include <string.h>
    10  #include <unistd.h>
    11  
    12  static const char *os_release = "/etc/os-release";
    13  static const char *meta_snap_yaml = "/meta/snap.yaml";
    14  
    15  sc_distro sc_classify_distro(void)
    16  {
    17  	FILE *f SC_CLEANUP(sc_cleanup_file) = fopen(os_release, "r");
    18  	if (f == NULL) {
    19  		return SC_DISTRO_CLASSIC;
    20  	}
    21  
    22  	bool is_core = false;
    23  	int core_version = 0;
    24  	char buf[255] = { 0 };
    25  
    26  	while (fgets(buf, sizeof buf, f) != NULL) {
    27  		size_t len = strlen(buf);
    28  		if (len > 0 && buf[len - 1] == '\n') {
    29  			buf[len - 1] = '\0';
    30  		}
    31  		if (sc_streq(buf, "ID=\"ubuntu-core\"")
    32  		    || sc_streq(buf, "ID=ubuntu-core")) {
    33  			is_core = true;
    34  		} else if (sc_streq(buf, "VERSION_ID=\"16\"")
    35  			   || sc_streq(buf, "VERSION_ID=16")) {
    36  			core_version = 16;
    37  		} else if (sc_streq(buf, "VARIANT_ID=\"snappy\"")
    38  			   || sc_streq(buf, "VARIANT_ID=snappy")) {
    39  			is_core = true;
    40  		}
    41  	}
    42  
    43  	if (!is_core) {
    44  		/* Since classic systems don't have a /meta/snap.yaml file the simple
    45  		   presence of that file qualifies as SC_DISTRO_CORE_OTHER. */
    46  		if (access(meta_snap_yaml, F_OK) == 0) {
    47  			is_core = true;
    48  		}
    49  	}
    50  
    51  	if (is_core) {
    52  		if (core_version == 16) {
    53  			return SC_DISTRO_CORE16;
    54  		}
    55  		return SC_DISTRO_CORE_OTHER;
    56  	} else {
    57  		return SC_DISTRO_CLASSIC;
    58  	}
    59  }
    60  
    61  bool sc_is_debian_like(void)
    62  {
    63  	FILE *f SC_CLEANUP(sc_cleanup_file) = fopen(os_release, "r");
    64  	if (f == NULL) {
    65  		return false;
    66  	}
    67  	const char *const id_keys_to_try[] = {
    68  		"ID",		/* actual debian only sets ID */
    69  		"ID_LIKE",	/* distros based on debian */
    70  	};
    71  	size_t id_keys_to_try_len =
    72  	    sizeof id_keys_to_try / sizeof *id_keys_to_try;
    73  	for (size_t i = 0; i < id_keys_to_try_len; i++) {
    74  		if (fseek(f, 0L, SEEK_SET) == -1) {
    75  			return false;
    76  		}
    77  		char *id_val SC_CLEANUP(sc_cleanup_string) = NULL;
    78  		struct sc_error *err SC_CLEANUP(sc_cleanup_error) = NULL;
    79  		int rc =
    80  		    sc_infofile_get_key(f, id_keys_to_try[i], &id_val, &err);
    81  		if (rc != 0) {
    82  			/* only if sc_infofile_get_key failed */
    83  			return false;
    84  		}
    85  		if (sc_streq(id_val, "\"debian\"")
    86  		    || sc_streq(id_val, "debian")) {
    87  			return true;
    88  		}
    89  	}
    90  	return false;
    91  }