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 }