summaryrefslogtreecommitdiff
path: root/minix/servers/vfs/gcov.c
blob: 82c62dcebf819eb24641b92bca09473c14242a93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

#include <string.h>

#include "fs.h"
#include "file.h"

/*===========================================================================*
 *				do_gcov_flush				     *
 *===========================================================================*/
int do_gcov_flush(void)
{
/* A userland tool has requested the gcov data from another
 * process (possibly vfs itself). Grant the target process
 * access to the supplied buffer, and perform the call that
 * makes the target copy its buffer to the caller (incl vfs
 * itself).
 */
  char label[LABEL_MAX];
  vir_bytes labeladdr, buf;
  size_t labellen, size;
  endpoint_t endpt;
  cp_grant_id_t grantid;
  int r;
  message m;

  /*
   * Something as sensitive as system service coverage information must be
   * call to the target service, and so it is not impossible to deadlock the
   * system with this call.
   */
  if (!super_user) return(EPERM);

  labeladdr = job_m_in.m_lc_vfs_gcov.label;
  labellen = job_m_in.m_lc_vfs_gcov.labellen;
  buf = job_m_in.m_lc_vfs_gcov.buf;
  size = job_m_in.m_lc_vfs_gcov.buflen;

  /* Retrieve and look up the target label. */
  if (labellen >= sizeof(label))
	return EINVAL;
  if ((r = sys_datacopy_wrapper(who_e, labeladdr, SELF, (vir_bytes)label,
    labellen)) != OK)
	return r;
  label[labellen - 1] = '\0';

  if ((r = ds_retrieve_label_endpt(label, &endpt)) != OK)
	return r;

  /* Hack: init is the only non-system process with a valid label. */
  if (endpt == INIT_PROC_NR)
	return ENOENT;

  /* Grant target process to requestor's buffer. */
  if ((grantid = cpf_grant_magic(endpt, who_e, buf, size, CPF_WRITE)) < 0) {
	printf("VFS: gcov_flush: grant failed\n");
	return(ENOMEM);
  }

  if (endpt == VFS_PROC_NR) {
	/* Request is for VFS itself. */
	r = gcov_flush(VFS_PROC_NR, grantid, size);
  } else {
	/* Perform generic GCOV request. */
	memset(&m, 0, sizeof(m));
	m.m_vfs_lsys_gcov.grant = grantid;
	m.m_vfs_lsys_gcov.size = size;
	r = _taskcall(endpt, COMMON_REQ_GCOV_DATA, &m);
  }

  cpf_revoke(grantid);

  return(r);
}