1 /*
2 Copyright Ⓒ 2009 Regis Duchesne
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
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
15 #include <sys/attr.h>
16 #include <sys/mount.h>
17
18 #ifndef ATTR_CMN_FILEID
19 #define ATTR_CMN_FILEID 0x02000000
20 #endif
21 #ifndef ATTR_CMN_PARENTID
22 #define ATTR_CMN_PARENTID 0x04000000
23 #endif
24 #ifndef ATTR_CMN_FULLPATH
25 #define ATTR_CMN_FULLPATH 0x08000000
26 #endif
27 #ifndef ATTR_CMN_RETURNED_ATTRS
28 #define ATTR_CMN_RETURNED_ATTRS 0x80000000
29 #endif
30
31 #ifdef LIBFAKEROOT_DEBUGGING
32 extern int fakeroot_debug;
33
34 #endif /* LIBFAKEROOT_DEBUGGING */
35 static void
patchattr(void * attrList,void * attrBuf,uid_t uid,gid_t gid,mode_t mode)36 patchattr(void *attrList, void *attrBuf, uid_t uid, gid_t gid, mode_t mode)
37 {
38 /* Attributes, in the order in which they are returned (which is the same as
39 the order they are described in the man page).
40 */
41 static const struct {
42 const char *name;
43 u_int32_t value;
44 size_t size;
45 int isRef;
46 } attrs[] = {
47 #define PATCHATTR(a,b,c) { #a, a, b, c, }
48 PATCHATTR(ATTR_CMN_RETURNED_ATTRS, sizeof (attribute_set_t), 0),
49 PATCHATTR(ATTR_CMN_NAME, sizeof (attrreference_t), 1),
50 PATCHATTR(ATTR_CMN_DEVID, sizeof (dev_t), 0),
51 PATCHATTR(ATTR_CMN_FSID, sizeof (fsid_t), 0),
52 PATCHATTR(ATTR_CMN_OBJTYPE, sizeof (fsobj_type_t), 0),
53 PATCHATTR(ATTR_CMN_OBJTAG, sizeof (fsobj_tag_t), 0),
54 PATCHATTR(ATTR_CMN_OBJID, sizeof (fsobj_id_t), 0),
55 PATCHATTR(ATTR_CMN_OBJPERMANENTID, sizeof (fsobj_id_t), 0),
56 PATCHATTR(ATTR_CMN_PAROBJID, sizeof (fsobj_id_t), 0),
57 PATCHATTR(ATTR_CMN_SCRIPT, sizeof (text_encoding_t), 0),
58 PATCHATTR(ATTR_CMN_CRTIME, sizeof (struct timespec), 0),
59 PATCHATTR(ATTR_CMN_MODTIME, sizeof (struct timespec), 0),
60 PATCHATTR(ATTR_CMN_CHGTIME, sizeof (struct timespec), 0),
61 PATCHATTR(ATTR_CMN_ACCTIME, sizeof (struct timespec), 0),
62 PATCHATTR(ATTR_CMN_BKUPTIME, sizeof (struct timespec), 0),
63 PATCHATTR(ATTR_CMN_FNDRINFO, 32, 0),
64 PATCHATTR(ATTR_CMN_OWNERID, sizeof (uid_t), 0),
65 PATCHATTR(ATTR_CMN_GRPID, sizeof (gid_t), 0),
66 PATCHATTR(ATTR_CMN_ACCESSMASK, sizeof (u_int32_t), 0),
67 PATCHATTR(ATTR_CMN_NAMEDATTRCOUNT, sizeof (u_int32_t), 0),
68 PATCHATTR(ATTR_CMN_NAMEDATTRLIST, sizeof (attrreference_t), 1),
69 PATCHATTR(ATTR_CMN_FLAGS, sizeof (u_int32_t), 0),
70 PATCHATTR(ATTR_CMN_USERACCESS, sizeof (u_int32_t), 0),
71 PATCHATTR(ATTR_CMN_EXTENDED_SECURITY, sizeof (attrreference_t), 1),
72 PATCHATTR(ATTR_CMN_UUID, sizeof (guid_t), 0),
73 PATCHATTR(ATTR_CMN_GRPUUID, sizeof (guid_t), 0),
74 PATCHATTR(ATTR_CMN_FILEID, sizeof (u_int64_t), 0),
75 PATCHATTR(ATTR_CMN_PARENTID, sizeof (u_int64_t), 0),
76 PATCHATTR(ATTR_CMN_FULLPATH, sizeof (attrreference_t), 1),
77 #undef PATCHATTR
78 };
79 struct attrlist *l = attrList;
80 unsigned char *b = attrBuf;
81 unsigned i;
82
83 #ifdef LIBFAKEROOT_DEBUGGING
84 if (fakeroot_debug) {
85 fprintf(stderr, "patchattr actual attrBuf size %u\n", *(u_int32_t *)b);
86 }
87 #endif /* LIBFAKEROOT_DEBUGGING */
88 b += sizeof (u_int32_t);
89 for (i = 0; i < sizeof attrs / sizeof attrs[0]; i++) {
90 if (l->commonattr & attrs[i].value) {
91 #ifdef LIBFAKEROOT_DEBUGGING
92 if (fakeroot_debug) {
93 fprintf(stderr, "patchattr attr %s: yes\n", attrs[i].name);
94 if (attrs[i].isRef) {
95 size_t here = b - (unsigned char *)attrBuf;
96 size_t begin = here + ((attrreference_t *)b)->attr_dataoffset;
97 size_t size = ((attrreference_t *)b)->attr_length;
98 size_t alignedEnd = (begin + size + 3) & ~3;
99 fprintf(stderr, "patchattr reference begin %zu size %zu aligned end %zu\n", begin, size, alignedEnd);
100 }
101 }
102 #endif /* LIBFAKEROOT_DEBUGGING */
103 if (attrs[i].value == ATTR_CMN_OWNERID) {
104 #ifdef LIBFAKEROOT_DEBUGGING
105 if (fakeroot_debug) {
106 fprintf(stderr, "patchattr owner %d\n", *(uid_t *)b);
107 }
108 #endif /* LIBFAKEROOT_DEBUGGING */
109 *(uid_t *)b = uid;
110 }
111 if (attrs[i].value == ATTR_CMN_GRPID) {
112 #ifdef LIBFAKEROOT_DEBUGGING
113 if (fakeroot_debug) {
114 fprintf(stderr, "patchattr group %d\n", *(gid_t *)b);
115 }
116 #endif /* LIBFAKEROOT_DEBUGGING */
117 *(gid_t *)b = gid;
118 }
119 if (attrs[i].value == ATTR_CMN_ACCESSMASK) {
120 #ifdef LIBFAKEROOT_DEBUGGING
121 if (fakeroot_debug) {
122 fprintf(stderr, "patchattr mode 0%o\n", *(mode_t *)b);
123 }
124 #endif /* LIBFAKEROOT_DEBUGGING */
125 *(mode_t *)b = mode;
126 }
127 b += (attrs[i].size + 3) & ~3;
128 }
129 }
130 #ifdef LIBFAKEROOT_DEBUGGING
131 if (fakeroot_debug) {
132 size_t here = b - (unsigned char *)attrBuf;
133 fprintf(stderr, "patchattr attrBuf fixed size %zu\n", here);
134 }
135 #endif /* LIBFAKEROOT_DEBUGGING */
136 }
137