Annotation of pkgsrc/pkgtools/pkg_install/files/create/build.c, Revision 1.2
1.2 ! joerg 1: /* $NetBSD: build.c,v 1.1 2007/08/03 13:15:59 joerg Exp $ */
1.1 joerg 2:
3: #if HAVE_CONFIG_H
4: #include "config.h"
5: #endif
6: #include <nbcompat.h>
7: #if HAVE_SYS_CDEFS_H
8: #include <sys/cdefs.h>
9: #endif
10: #ifndef lint
11: #if 0
12: static const char *rcsid = "from FreeBSD Id: perform.c,v 1.38 1997/10/13 15:03:51 jkh Exp";
13: #else
1.2 ! joerg 14: __RCSID("$NetBSD: build.c,v 1.1 2007/08/03 13:15:59 joerg Exp $");
1.1 joerg 15: #endif
16: #endif
17:
18: /*
19: * FreeBSD install - a package for the installation and maintainance
20: * of non-core utilities.
21: *
22: * Redistribution and use in source and binary forms, with or without
23: * modification, are permitted provided that the following conditions
24: * are met:
25: * 1. Redistributions of source code must retain the above copyright
26: * notice, this list of conditions and the following disclaimer.
27: * 2. Redistributions in binary form must reproduce the above copyright
28: * notice, this list of conditions and the following disclaimer in the
29: * documentation and/or other materials provided with the distribution.
30: *
31: * Jordan K. Hubbard
32: * 18 July 1993
33: *
34: * This is the main body of the create module.
35: *
36: */
37:
38: #include "lib.h"
39: #include "create.h"
40:
41: #if HAVE_ERR_H
42: #include <err.h>
43: #endif
1.2 ! joerg 44: #if HAVE_GRP_H
! 45: #include <grp.h>
! 46: #endif
! 47: #if HAVE_PWD_H
! 48: #include <pwd.h>
1.1 joerg 49: #endif
50: #if HAVE_UNISTD_H
51: #include <unistd.h>
52: #endif
53:
54: #include <archive.h>
55: #include <archive_entry.h>
56:
57: static struct memory_file *contents_file;
58: static struct memory_file *comment_file;
59: static struct memory_file *desc_file;
60: static struct memory_file *install_file;
61: static struct memory_file *deinstall_file;
62: static struct memory_file *display_file;
63: static struct memory_file *build_version_file;
64: static struct memory_file *build_info_file;
65: static struct memory_file *size_pkg_file;
66: static struct memory_file *size_all_file;
67: static struct memory_file *preserve_file;
68: static struct memory_file *views_file;
69:
70: static void
71: write_meta_file(struct memory_file *file, struct archive *archive)
72: {
73: struct archive_entry *entry;
74:
75: entry = archive_entry_new();
76: archive_entry_set_pathname(entry, file->name);
77: archive_entry_copy_stat(entry, &file->st);
78:
79: archive_entry_set_uname(entry, file->owner);
80: archive_entry_set_gname(entry, file->group);
81:
82: if (archive_write_header(archive, entry))
83: errx(2, "cannot write to archive: %s", archive_error_string(archive));
84:
85: archive_write_data(archive, file->data, file->len);
86:
87: archive_entry_free(entry);
88: }
89:
90: LIST_HEAD(hardlink_list, hardlinked_entry);
91: struct hardlink_list written_hardlinks;
92:
93: struct hardlinked_entry {
94: LIST_ENTRY(hardlinked_entry) link;
95: const char *existing_name;
96: nlink_t remaining_links;
97: dev_t existing_device;
98: ino_t existing_ino;
99: };
100:
101: static void
102: write_normal_file(const char *name, struct archive *archive, const char *owner, const char *group)
103: {
104: char buf[16384];
105: off_t len;
106: ssize_t buf_len;
107: struct hardlinked_entry *older_link;
108: struct archive_entry *entry;
109: struct stat st;
110: int fd;
111:
112: if (lstat(name, &st) == -1)
113: err(2, "lstat failed for file %s", name);
114:
115: entry = archive_entry_new();
116: archive_entry_set_pathname(entry, name);
117:
118: if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) {
119: LIST_FOREACH(older_link, &written_hardlinks, link) {
120: if (st.st_dev == older_link->existing_device &&
121: st.st_ino == older_link->existing_ino) {
122: archive_entry_copy_hardlink(entry,
123: older_link->existing_name);
124: if (archive_write_header(archive, entry)) {
125: errx(2, "cannot write to archive: %s",
126: archive_error_string(archive));
127: }
128:
129: if (--older_link->remaining_links > 0)
130: return;
131: LIST_REMOVE(older_link, link);
132: free(older_link);
133: return;
134: }
135: }
136: /* Not yet linked */
137: if ((older_link = malloc(sizeof(*older_link))) == NULL)
138: err(2, "malloc failed");
139: older_link->existing_name = name;
140: older_link->remaining_links = st.st_nlink - 1;
141: older_link->existing_device = st.st_dev;
142: older_link->existing_ino = st.st_ino;
143: LIST_INSERT_HEAD(&written_hardlinks, older_link, link);
144: }
145:
146: archive_entry_copy_stat(entry, &st);
147:
148: if (owner != NULL) {
149: uid_t uid;
150:
151: archive_entry_set_uname(entry, owner);
152: if (uid_from_user(owner, &uid) == -1)
153: errx(2, "user %s unknown", owner);
154: archive_entry_set_uid(entry, uid);
155: } else {
156: archive_entry_set_uname(entry, user_from_uid(st.st_uid, 1));
157: }
158:
159: if (group != NULL) {
160: gid_t gid;
161:
162: archive_entry_set_gname(entry, group);
163: if (gid_from_group(group, &gid) == -1)
164: errx(2, "group %s unknown", group);
165: archive_entry_set_gid(entry, gid);
166: } else {
167: archive_entry_set_gname(entry, group_from_gid(st.st_gid, 1));
168: }
169:
170: switch (st.st_mode & S_IFMT) {
171: case S_IFLNK:
172: buf_len = readlink(name, buf, sizeof buf);
173: if (buf_len < 0)
174: err(2, "cannot read symlink %s", name);
175: buf[buf_len] = '\0';
176: archive_entry_set_symlink(entry, buf);
177:
178: if (archive_write_header(archive, entry))
179: errx(2, "cannot write to archive: %s", archive_error_string(archive));
180:
181: break;
182:
183: case S_IFREG:
184: fd = open(name, O_RDONLY);
185: if (fd == -1)
186: errx(2, "cannot open data file %s: %s", name, archive_error_string(archive));
187:
188: len = st.st_size;
189:
190: if (archive_write_header(archive, entry))
191: errx(2, "cannot write to archive: %s", archive_error_string(archive));
192:
193: while (len > 0) {
194: if (len > sizeof(buf))
195: buf_len = sizeof(buf);
196: else
197: buf_len = (ssize_t)len;
198: if ((buf_len = read(fd, buf, buf_len)) <= 0)
199: break;
200: archive_write_data(archive, buf, (size_t)buf_len);
201: len -= buf_len;
202: }
203:
204: close(fd);
205: break;
206:
207: default:
208: errx(2, "PLIST entry neither symlink nor directory: %s", name);
209: }
210:
211: archive_entry_free(entry);
212: }
213:
214: static void
215: make_dist(const char *pkg, const char *suffix, const package_t *plist)
216: {
217: char *archive_name;
218: const char *owner, *group;
219: const plist_t *p;
220: struct archive *archive;
221: char *initial_cwd;
222:
223: archive = archive_write_new();
224: archive_write_set_format_pax_restricted(archive);
225:
226: if (strcmp(suffix, "tbz") == 0 || strcmp(suffix, "tar.bz2") == 0)
227: archive_write_set_compression_bzip2(archive);
228: else if (strcmp(suffix, "tgz") == 0 || strcmp(suffix, "tar.gz") == 0)
229: archive_write_set_compression_gzip(archive);
230: else
231: archive_write_set_compression_none(archive);
232:
233: if (asprintf(&archive_name, "%s.%s", pkg, suffix) == -1)
234: err(2, "cannot compute output name");
235:
236: if (archive_write_open_file(archive, archive_name))
237: errx(2, "cannot create archive: %s", archive_error_string(archive));
238:
239: free(archive_name);
240:
241: owner = DefaultOwner;
242: group = DefaultGroup;
243:
244: write_meta_file(contents_file, archive);
245: write_meta_file(comment_file, archive);
246: write_meta_file(desc_file, archive);
247:
248: if (Install)
249: write_meta_file(install_file, archive);
250: if (DeInstall)
251: write_meta_file(deinstall_file, archive);
252: if (Display)
253: write_meta_file(display_file, archive);
254: if (BuildVersion)
255: write_meta_file(build_version_file, archive);
256: if (BuildInfo)
257: write_meta_file(build_info_file, archive);
258: if (SizePkg)
259: write_meta_file(size_pkg_file, archive);
260: if (SizeAll)
261: write_meta_file(size_all_file, archive);
262: if (Preserve)
263: write_meta_file(preserve_file, archive);
264: if (create_views)
265: write_meta_file(views_file, archive);
266:
267: initial_cwd = getcwd(NULL, 0);
268:
269: for (p = plist->head; p; p = p->next) {
270: if (p->type == PLIST_FILE) {
271: write_normal_file(p->name, archive, owner, group);
272: } else if (p->type == PLIST_CWD || p->type == PLIST_SRC) {
273:
274: /* XXX let PLIST_SRC override PLIST_CWD */
275: if (p->type == PLIST_CWD && p->next != NULL &&
276: p->next->type == PLIST_SRC) {
277: continue;
278: }
279: chdir(p->name);
280: } else if (p->type == PLIST_IGNORE) {
281: p = p->next;
282: } else if (p->type == PLIST_CHOWN) {
283: if (p->name != NULL)
284: owner = p->name;
285: else
286: owner = DefaultOwner;
287: } else if (p->type == PLIST_CHGRP) {
288: if (p->name != NULL)
289: group = p->name;
290: else
291: group = DefaultGroup;
292: }
293: }
294: chdir(initial_cwd);
295: free(initial_cwd);
296:
297: if (archive_write_close(archive))
298: errx(2, "cannot finish archive: %s", archive_error_string(archive));
299: archive_write_finish(archive);
300: }
301:
302: static struct memory_file *
303: load_and_add(package_t *plist, const char *input_name,
304: const char *target_name, mode_t perm)
305: {
306: struct memory_file *file;
307:
308: file = load_memory_file(input_name, target_name, DefaultOwner,
309: DefaultGroup, perm);
310: add_plist(plist, PLIST_IGNORE, NULL);
311: add_plist(plist, PLIST_FILE, target_name);
312:
313: return file;
314: }
315:
316: static struct memory_file *
317: make_and_add(package_t *plist, const char *target_name,
318: char *content, mode_t perm)
319: {
320: struct memory_file *file;
321:
322: file = make_memory_file(target_name, content, strlen(content),
323: DefaultOwner, DefaultGroup, perm);
324: add_plist(plist, PLIST_IGNORE, NULL);
325: add_plist(plist, PLIST_FILE, target_name);
326:
327: return file;
328: }
329:
330: int
331: pkg_build(const char *pkg, const char *full_pkg, const char *suffix,
332: package_t *plist)
333: {
334: char *plist_buf;
335: size_t plist_len;
336:
337: /* Now put the release specific items in */
338: add_plist(plist, PLIST_CWD, ".");
339: comment_file = make_and_add(plist, COMMENT_FNAME, Comment, 0444);
340: desc_file = make_and_add(plist, DESC_FNAME, Desc, 0444);
341:
342: if (Install) {
343: install_file = load_and_add(plist, Install, INSTALL_FNAME,
344: 0555);
345: }
346: if (DeInstall) {
347: deinstall_file = load_and_add(plist, DeInstall,
348: DEINSTALL_FNAME, 0555);
349: }
350: if (Display) {
351: display_file = load_and_add(plist, Display,
352: DISPLAY_FNAME, 0444);
353: add_plist(plist, PLIST_DISPLAY, DISPLAY_FNAME);
354: }
355: if (BuildVersion) {
356: build_version_file = load_and_add(plist, BuildVersion,
357: BUILD_VERSION_FNAME, 0444);
358: }
359: if (BuildInfo) {
360: build_info_file = load_and_add(plist, BuildInfo,
361: BUILD_INFO_FNAME, 0444);
362: }
363: if (SizePkg) {
364: size_pkg_file = load_and_add(plist, SizePkg,
365: SIZE_PKG_FNAME, 0444);
366: }
367: if (SizeAll) {
368: size_all_file = load_and_add(plist, SizeAll,
369: SIZE_ALL_FNAME, 0444);
370: }
371: if (Preserve) {
372: preserve_file = load_and_add(plist, Preserve,
373: PRESERVE_FNAME, 0444);
374: }
375: if (create_views)
376: views_file = make_and_add(plist, VIEWS_FNAME, "", 0444);
377:
378: /* Finally, write out the packing list */
379: stringify_plist(plist, &plist_buf, &plist_len, realprefix);
380: contents_file = make_memory_file(CONTENTS_FNAME, plist_buf, plist_len,
381: DefaultOwner, DefaultGroup, 0644);
382:
383: /* And stick it into a tar ball */
384: make_dist(pkg, suffix, plist);
385:
386: return TRUE; /* Success */
387: }
CVSweb <webmaster@jp.NetBSD.org>