1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include "log_sys.h"
7 #include "fsutils.h"
8 #include "strutils.h"
9 #include "vmrecord.h"
10 #include <stdlib.h>
11 
vmrecord_last(struct vmrecord_t * vmrecord,const char * vm_name,size_t nlen,char * vmkey,size_t ksize)12 int vmrecord_last(struct vmrecord_t *vmrecord, const char *vm_name,
13 		size_t nlen, char *vmkey, size_t ksize)
14 {
15 	int res;
16 	char *p;
17 	char *key;
18 
19 	if (!vmrecord || !vm_name || !nlen || !vmkey || !ksize)
20 		return -1;
21 
22 	key = malloc(nlen + 2);
23 	if (!key)
24 		return -1;
25 
26 	memcpy(key, vm_name, nlen);
27 	key[nlen] = ' ';
28 	key[nlen + 1] = '\0';
29 
30 	pthread_mutex_lock(&vmrecord->mtx);
31 	res = file_read_key_value_r(vmkey, ksize, vmrecord->path, key,
32 				    nlen + 1);
33 	pthread_mutex_unlock(&vmrecord->mtx);
34 	free(key);
35 	if (res < 0) {
36 		LOGE("failed to search %s, %s\n", vmrecord->path,
37 		     strerror(errno));
38 		return -1;
39 	}
40 	p = strchr(vmkey, ' ');
41 	if (p)
42 		*p = 0;
43 
44 	return 0;
45 }
46 
47 /* This function must be called with holding vmrecord mutex */
vmrecord_mark(struct vmrecord_t * vmrecord,const char * vmkey,size_t klen,enum vmrecord_mark_t type)48 int vmrecord_mark(struct vmrecord_t *vmrecord, const char *vmkey,
49 			   size_t klen, enum vmrecord_mark_t type)
50 {
51 	size_t len;
52 	char *line;
53 	char *tag;
54 
55 	if (!vmrecord || !vmrecord->recos || !vmkey || !klen)
56 		return -1;
57 
58 	line = get_line(vmkey, klen, vmrecord->recos->begin,
59 			vmrecord->recos->size, vmrecord->recos->begin, &len);
60 	if (!line)
61 		return -1;
62 
63 	tag = line + len - VMRECORD_TAG_LEN;
64 
65 	if (type == SUCCESS)
66 		memcpy(tag, VMRECORD_TAG_SUCCESS, VMRECORD_TAG_LEN);
67 	else if (type == NOT_FOUND)
68 		memcpy(tag, VMRECORD_TAG_NOT_FOUND, VMRECORD_TAG_LEN);
69 	else if (type == MISS_LOG)
70 		memcpy(tag, VMRECORD_TAG_MISS_LOG, VMRECORD_TAG_LEN);
71 	else if (type == WAITING_SYNC)
72 		memcpy(tag, VMRECORD_TAG_WAITING_SYNC, VMRECORD_TAG_LEN);
73 	else if (type == ON_GOING)
74 		memcpy(tag, VMRECORD_TAG_ON_GOING, VMRECORD_TAG_LEN);
75 	else if (type == NO_RESRC)
76 		memcpy(tag, VMRECORD_TAG_NO_RESOURCE, VMRECORD_TAG_LEN);
77 	else
78 		return -1;
79 
80 	return 0;
81 
82 }
83 
vmrecord_open_mark(struct vmrecord_t * vmrecord,const char * vmkey,size_t klen,enum vmrecord_mark_t type)84 int vmrecord_open_mark(struct vmrecord_t *vmrecord, const char *vmkey,
85 			   size_t klen, enum vmrecord_mark_t type)
86 {
87 	int ret;
88 
89 	if (!vmrecord || !vmkey || !klen)
90 		return -1;
91 
92 	pthread_mutex_lock(&vmrecord->mtx);
93 	vmrecord->recos = mmap_file(vmrecord->path);
94 	if (!vmrecord->recos) {
95 		LOGE("failed to mmap %s, %s\n", vmrecord->path,
96 						strerror(errno));
97 		ret = -1;
98 		goto unlock;
99 	}
100 	if (!vmrecord->recos->size ||
101 	    mm_count_lines(vmrecord->recos) < VMRECORD_HEAD_LINES) {
102 		LOGE("(%s) invalid\n", vmrecord->path);
103 		ret = -1;
104 		goto out;
105 	}
106 
107 	ret = vmrecord_mark(vmrecord, vmkey, klen, type);
108 out:
109 	unmap_file(vmrecord->recos);
110 unlock:
111 	pthread_mutex_unlock(&vmrecord->mtx);
112 	return ret;
113 }
114 
vmrecord_gen_ifnot_exists(struct vmrecord_t * vmrecord)115 int vmrecord_gen_ifnot_exists(struct vmrecord_t *vmrecord)
116 {
117 	const char * const head =
118 		"/* DONT EDIT!\n"
119 		" * This file records VM id synced or about to be synched,\n"
120 		" * the tag:\n"
121 		" * \"<==\" indicates event waiting to sync.\n"
122 		" * \"NOT_FOUND\" indicates event not found in User VM.\n"
123 		" * \"MISS_LOGS\" indicates event miss logs in User VM.\n"
124 		" * \"ON_GOING\" indicates event is under syncing.\n"
125 		" * \"NO_RESORC\" indicates no enough resources in Service VM.\n"
126 		" */\n\n";
127 
128 	if (!vmrecord) {
129 		LOGE("vmrecord was not initialized\n");
130 		return -1;
131 	}
132 
133 	pthread_mutex_lock(&vmrecord->mtx);
134 	if (!file_exists(vmrecord->path)) {
135 		if (overwrite_file(vmrecord->path, head) < 0) {
136 			pthread_mutex_unlock(&vmrecord->mtx);
137 			LOGE("failed to create file (%s), %s\n",
138 			     vmrecord->path, strerror(errno));
139 			return -1;
140 		}
141 	}
142 	pthread_mutex_unlock(&vmrecord->mtx);
143 	return 0;
144 }
145 
vmrecord_new(struct vmrecord_t * vmrecord,const char * vm_name,const char * key)146 int vmrecord_new(struct vmrecord_t *vmrecord, const char *vm_name,
147 			  const char *key)
148 {
149 	char log_new[64];
150 	int nlen;
151 
152 	if (!vmrecord || !vm_name || !key)
153 		return -1;
154 
155 	nlen = snprintf(log_new, sizeof(log_new), "%s %s %s\n",
156 			vm_name, key, VMRECORD_TAG_WAITING_SYNC);
157 	if (s_not_expect(nlen, sizeof(log_new))) {
158 		LOGE("failed to construct record, key (%s)\n", key);
159 		return -1;
160 	}
161 
162 	pthread_mutex_lock(&vmrecord->mtx);
163 	if (append_file(vmrecord->path, log_new, strnlen(log_new, 64)) < 0) {
164 		pthread_mutex_unlock(&vmrecord->mtx);
165 		LOGE("failed to append file (%s), %s\n", vmrecord->path,
166 		     strerror(errno));
167 		return -1;
168 	}
169 	pthread_mutex_unlock(&vmrecord->mtx);
170 	return 0;
171 }
172