summaryrefslogtreecommitdiff
path: root/minix/lib/libhgfs/attr.c
blob: 61e1c1e966c20f468be708fb5250151c7f1179b8 (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */

#include "inc.h"

#include <sys/stat.h>

/*===========================================================================*
 *				attr_get				     *
 *===========================================================================*/
void attr_get(struct sffs_attr *attr)
{
/* Get attribute information from the RPC buffer, storing the requested parts
 * in the given attr structure.
 */
  mode_t mode;
  u32_t size_lo, size_hi;

  mode = (RPC_NEXT32) ? S_IFDIR : S_IFREG;

  size_lo = RPC_NEXT32;
  size_hi = RPC_NEXT32;
  if (attr->a_mask & SFFS_ATTR_SIZE)
	attr->a_size = make64(size_lo, size_hi);

  time_get((attr->a_mask & SFFS_ATTR_CRTIME) ? &attr->a_crtime : NULL);
  time_get((attr->a_mask & SFFS_ATTR_ATIME) ? &attr->a_atime : NULL);
  time_get((attr->a_mask & SFFS_ATTR_MTIME) ? &attr->a_mtime : NULL);
  time_get((attr->a_mask & SFFS_ATTR_CTIME) ? &attr->a_ctime : NULL);

  mode |= HGFS_PERM_TO_MODE(RPC_NEXT8);
  if (attr->a_mask & SFFS_ATTR_MODE) attr->a_mode = mode;
}

/*===========================================================================*
 *				hgfs_getattr				     *
 *===========================================================================*/
int hgfs_getattr(const char *path, struct sffs_attr *attr)
{
/* Get selected attributes of a file by path name.
 */
  int r;

  RPC_REQUEST(HGFS_REQ_GETATTR);

  path_put(path);

  if ((r = rpc_query()) != OK)
	return r;

  attr_get(attr);

  return OK;
}

/*===========================================================================*
 *				hgfs_setattr				     *
 *===========================================================================*/
int hgfs_setattr(const char *path, struct sffs_attr *attr)
{
/* Set selected attributes of a file by path name.
 */
  u8_t mask;

  RPC_REQUEST(HGFS_REQ_SETATTR);

  /* This library implements the HGFS v1 protocol, which is largely
   * path-oriented. This is the only method to set the file size, and thus,
   * truncating a deleted file is not possible. This has been fixed in later
   * HGFS protocol version (v2/v3).
   */
  mask = 0;
  if (attr->a_mask & SFFS_ATTR_MODE) mask |= HGFS_ATTR_MODE;
  if (attr->a_mask & SFFS_ATTR_SIZE) mask |= HGFS_ATTR_SIZE;
  if (attr->a_mask & SFFS_ATTR_CRTIME) mask |= HGFS_ATTR_CRTIME;
  if (attr->a_mask & SFFS_ATTR_ATIME)
	mask |= HGFS_ATTR_ATIME | HGFS_ATTR_ATIME_SET;
  if (attr->a_mask & SFFS_ATTR_MTIME)
	mask |= HGFS_ATTR_MTIME | HGFS_ATTR_MTIME_SET;
  if (attr->a_mask & SFFS_ATTR_CTIME) mask |= HGFS_ATTR_CTIME;

  RPC_NEXT8 = mask;

  RPC_NEXT32 = !!(S_ISDIR(attr->a_mode));
  RPC_NEXT32 = ex64lo(attr->a_size);
  RPC_NEXT32 = ex64hi(attr->a_size);

  time_put((attr->a_mask & HGFS_ATTR_CRTIME) ? &attr->a_crtime : NULL);
  time_put((attr->a_mask & HGFS_ATTR_ATIME) ? &attr->a_atime : NULL);
  time_put((attr->a_mask & HGFS_ATTR_MTIME) ? &attr->a_mtime : NULL);
  time_put((attr->a_mask & HGFS_ATTR_CTIME) ? &attr->a_ctime : NULL);

  RPC_NEXT8 = HGFS_MODE_TO_PERM(attr->a_mode);

  path_put(path);

  return rpc_query();
}