getvserverctx.c (5129B)
1 // $Id$ --*- c -*-- 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; version 2 of the License. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 18 19 #ifdef HAVE_CONFIG_H 20 # include <config.h> 21 #endif 22 23 #include "vserver.h" 24 #include "pathconfig.h" 25 #include "compat-c99.h" 26 #include "lib_internal/util.h" 27 #include "internal.h" 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <fcntl.h> 32 #include <errno.h> 33 #include <string.h> 34 #include <unistd.h> 35 36 #ifdef VC_ENABLE_API_COMPAT 37 #include <fcntl.h> 38 39 static xid_t 40 extractLegacyXID(char const *dir, char const *basename) 41 { 42 size_t l1 = strlen(dir); 43 size_t l2 = strlen(basename); 44 char path[l1 + l2 + sizeof("/.ctx")]; 45 char * ptr = path; 46 int fd; 47 ssize_t len; 48 xid_t result = VC_NOXID; 49 50 ptr = Xmemcpy(ptr, dir, l1); 51 *ptr++ = '/'; 52 ptr = Xmemcpy(ptr, basename, l2); 53 ptr = Xmemcpy(ptr, ".ctx", 5); 54 55 fd = open(path, O_RDONLY); 56 if (fd==-1) return VC_NOXID; 57 58 len = lseek(fd, 0, SEEK_END); 59 60 if (len!=-1 && lseek(fd, 0, SEEK_SET)!=-1) { 61 char buf[len+2]; 62 char const *pos = 0; 63 64 buf[0] = '\n'; 65 66 if (read(fd, buf+1, len+1)==len) { 67 buf[len+1] = '\0'; 68 pos = strstr(buf, "\nS_CONTEXT="); 69 } 70 71 if (pos) pos += 11; 72 if (*pos>='1' && *pos<='9') 73 result = atoi(pos); 74 } 75 76 close(fd); 77 return result; 78 } 79 #else 80 static xid_t 81 extractLegacyXID(char const UNUSED *dir, char const UNUSED *basename) 82 { 83 return VC_NOXID; 84 } 85 #endif 86 87 88 static xid_t 89 getCtxFromFile(char const *pathname) 90 { 91 int fd; 92 off_t len; 93 94 fd = open(pathname, O_RDONLY); 95 96 if (fd==-1) return VC_NOCTX; 97 if ((len=lseek(fd, 0, SEEK_END))==-1 || 98 (len>50) || 99 (lseek(fd, 0, SEEK_SET)==-1)) { 100 close(fd); 101 return VC_NOCTX; 102 } 103 104 { 105 char buf[len+1]; 106 char *errptr; 107 xid_t res; 108 109 if (TEMP_FAILURE_RETRY(read(fd, buf, len+1))!=len) res = VC_NOCTX; 110 else { 111 buf[len] = '\0'; 112 113 res = strtol(buf, &errptr, 10); 114 if (*errptr!='\0' && *errptr!='\n') res = VC_NOCTX; 115 } 116 117 close(fd); 118 return res; 119 } 120 } 121 122 xid_t 123 vc_getVserverCtx(char const *id, vcCfgStyle style, bool honor_static, bool *is_running, 124 vcCtxType type) 125 { 126 size_t l1 = strlen(id); 127 char buf[sizeof(CONFDIR "//") + l1 + sizeof("/ncontext")]; 128 129 if (style==vcCFG_NONE || style==vcCFG_AUTO) 130 style = vc_getVserverCfgStyle(id); 131 132 if (is_running) *is_running = false; 133 134 switch (style) { 135 case vcCFG_NONE : return VC_NOCTX; 136 case vcCFG_LEGACY : 137 return extractLegacyXID(DEFAULT_PKGSTATEDIR, id); 138 case vcCFG_RECENT_SHORT : 139 case vcCFG_RECENT_FULL : { 140 size_t idx = 0; 141 xid_t res = 0; 142 143 if (style==vcCFG_RECENT_SHORT) { 144 memcpy(buf, CONFDIR "/", sizeof(CONFDIR "/")-1); 145 idx = sizeof(CONFDIR "/") - 1; 146 } 147 memcpy(buf+idx, id, l1); idx += l1; 148 memcpy(buf+idx, "/run", 5); // appends '\0' too 149 150 res = getCtxFromFile(buf); 151 152 // when context information could be read, we have to verify that 153 // it belongs to a running vserver and the both vservers are 154 // identically 155 if (res!=VC_NOCTX && type == vcCTX_XID) { 156 char *cur_name; 157 struct vc_vx_info info; 158 159 // determine the vserver which is associated with the xid resp. skip 160 // this step when the context does not exist. When checking whether 161 // the context exists, do not rely on the success of 162 // vc_get_vx_info() alone but check 'errno' for ESRCH also. Else, 163 // wrong results will be caused e.g. for xid 1 which will fail with 164 // ENOSYS. 165 cur_name = (vc_get_vx_info(res, &info)!=-1 || errno!=ESRCH ? 166 vc_getVserverByCtx_Internal(res, &style, 0, false) : 167 0); 168 169 buf[idx] = '\0'; // cut off the '/run' from the vserver name 170 171 res = ((cur_name!=0 && 172 vc_compareVserverById(buf, vcCFG_RECENT_FULL, 173 cur_name, vcCFG_RECENT_FULL)==0) 174 ? res 175 : VC_NOCTX); // correct the value of 'res' 176 177 free(cur_name); 178 179 if (is_running) // fill 'is_running' information... 180 *is_running = res!=VC_NOCTX; 181 } 182 else if (is_running) 183 *is_running = false; 184 185 if (res==VC_NOCTX && honor_static) { 186 check_static: 187 switch (type) { 188 case vcCTX_XID: 189 memcpy(buf+idx, "/context", 9); // appends '\0' too 190 break; 191 case vcCTX_NID: 192 memcpy(buf+idx, "/ncontext", 10); 193 break; 194 case vcCTX_TAG: 195 memcpy(buf+idx, "/tag", 5); 196 break; 197 } 198 199 res = getCtxFromFile(buf); 200 if (res==VC_NOCTX && type!=vcCTX_XID) { 201 type = vcCTX_XID; 202 goto check_static; 203 } 204 } 205 206 return res; 207 } 208 default : return VC_NOCTX; 209 } 210 }