1139804Simp/*-
2139013Sdavidxu * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
3112904Sjeff * All rights reserved.
4112904Sjeff *
5112904Sjeff * Redistribution and use in source and binary forms, with or without
6112904Sjeff * modification, are permitted provided that the following conditions
7112904Sjeff * are met:
8112904Sjeff *
9112904Sjeff * 1. Redistributions of source code must retain the above copyright
10112904Sjeff *    notice, this list of conditions and the following disclaimer.
11112904Sjeff * 2. Redistributions in binary form must reproduce the above copyright
12112904Sjeff *    notice, this list of conditions and the following disclaimer in
13112904Sjeff *    the documentation and/or other materials provided with the
14112904Sjeff *    distribution.
15112904Sjeff *
16112904Sjeff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17112904Sjeff * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18112904Sjeff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19112904Sjeff * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
20112904Sjeff * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21112904Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22112904Sjeff * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23112904Sjeff * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24112904Sjeff * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25112904Sjeff * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26112904Sjeff * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27112904Sjeff * SUCH DAMAGE.
28116182Sobrien */
29116182Sobrien
30116182Sobrien#if HAVE_CONFIG_H
31162536Sdavidxu#include "config.h"
32112904Sjeff#endif
33112904Sjeff
34131431Smarcel#include <nbcompat.h>
35112904Sjeff
36115765Sjeff#if HAVE_SYS_STAT_H
37112904Sjeff#include <sys/stat.h>
38164033Srwatson#endif
39112904Sjeff#if HAVE_ERR_H
40161678Sdavidxu#include <err.h>
41165369Sdavidxu#endif
42161678Sdavidxu#include <fcntl.h>
43112904Sjeff#if HAVE_PWD_H
44112904Sjeff#include <grp.h>
45112904Sjeff#endif
46216641Sdavidxu#include <limits.h>
47139013Sdavidxu#if HAVE_PWD_H
48112904Sjeff#include <pwd.h>
49112904Sjeff#endif
50139013Sdavidxu#include <stdlib.h>
51139013Sdavidxu#include <string.h>
52139013Sdavidxu#include <time.h>
53139013Sdavidxu#include <unistd.h>
54139013Sdavidxu
55139013Sdavidxu#include "lib.h"
56165369Sdavidxu#include "create.h"
57165369Sdavidxu
58205014Snwhitehornstatic void
59162536Sdavidxuupdate_ids(struct memory_file *file)
60162536Sdavidxu{
61162536Sdavidxu	const char *s;
62179970Sdavidxu
63179970Sdavidxu	if (file->owner != NULL) {
64179970Sdavidxu		uid_t uid;
65161678Sdavidxu
66161678Sdavidxu		if (uid_from_user(file->owner, &uid) == -1)
67161678Sdavidxu			errx(2, "user %s unknown", file->owner);
68161678Sdavidxu		file->st.st_uid = uid;
69161678Sdavidxu	} else {
70161678Sdavidxu		if ((s = user_from_uid(file->st.st_uid, 1)) == NULL)
71161678Sdavidxu			errx(2, "unknown user name for uid %u",
72161678Sdavidxu			    (unsigned) file->st.st_uid);
73161678Sdavidxu		file->owner = xstrdup(s);
74161678Sdavidxu	}
75161678Sdavidxu
76161678Sdavidxu	if (file->group != NULL) {
77161678Sdavidxu		gid_t gid;
78161678Sdavidxu
79161678Sdavidxu		if (gid_from_group(file->group, &gid) == -1)
80161678Sdavidxu			errx(2, "group %s unknown", file->group);
81161678Sdavidxu		file->st.st_gid = gid;
82161678Sdavidxu	} else {
83161678Sdavidxu		if ((s = group_from_gid(file->st.st_gid, 1)) == NULL)
84161678Sdavidxu			errx(2, "unknown group name for gid %u",
85161678Sdavidxu			    (unsigned) file->st.st_gid);
86161678Sdavidxu		file->group = xstrdup(s);
87115765Sjeff	}
88161678Sdavidxu}
89161678Sdavidxu
90161678Sdavidxustruct memory_file *
91161678Sdavidxumake_memory_file(const char *archive_name, void *data, size_t len,
92161678Sdavidxu    const char *owner, const char *group, mode_t mode)
93161678Sdavidxu{
94161678Sdavidxu	struct memory_file *file;
95161678Sdavidxu
96161678Sdavidxu	file = xmalloc(sizeof(*file));
97161678Sdavidxu	file->name = archive_name;
98161678Sdavidxu	file->owner = (owner != NULL) ? xstrdup(owner) : NULL;
99161678Sdavidxu	file->group = (group != NULL) ? xstrdup(group) : NULL;
100161678Sdavidxu	file->data = data;
101161678Sdavidxu	file->len = len;
102161678Sdavidxu
103170300Sjeff	memset(&file->st, 0, sizeof(file->st));
104170300Sjeff
105161678Sdavidxu	file->st.st_atime = file->st.st_ctime = file->st.st_mtime = time(NULL);
106161678Sdavidxu
107161678Sdavidxu	file->st.st_nlink = 1;
108161678Sdavidxu	file->st.st_size = len;
109161678Sdavidxu	file->st.st_mode = mode | S_IFREG;
110161678Sdavidxu
111161678Sdavidxu	update_ids(file);
112161678Sdavidxu
113161678Sdavidxu	return file;
114161742Sdavidxu}
115161678Sdavidxu
116201991Sdavidxustruct memory_file *
117201991Sdavidxuload_memory_file(const char *disk_name,
118201991Sdavidxu    const char *archive_name, const char *owner, const char *group,
119201991Sdavidxu    mode_t mode)
120201991Sdavidxu{
121201991Sdavidxu	struct memory_file *file;
122115765Sjeff	int fd;
123115765Sjeff
124161678Sdavidxu	file = xmalloc(sizeof(*file));
125161678Sdavidxu	file->name = archive_name;
126201991Sdavidxu	file->owner = (owner != NULL) ? xstrdup(owner) : NULL;
127201991Sdavidxu	file->group = (group != NULL) ? xstrdup(group) : NULL;
128201991Sdavidxu	file->mode = mode;
129201991Sdavidxu
130201991Sdavidxu	fd = open(disk_name, O_RDONLY);
131201991Sdavidxu	if (fd == -1)
132201991Sdavidxu		err(2, "cannot open file %s", disk_name);
133201991Sdavidxu	if (fstat(fd, &file->st) == -1)
134201991Sdavidxu		err(2, "cannot stat file %s", disk_name);
135201991Sdavidxu
136161678Sdavidxu	update_ids(file);
137138224Sdavidxu
138161678Sdavidxu	if ((file->st.st_mode & S_IFMT) != S_IFREG)
139161678Sdavidxu		errx(1, "meta data file %s is not regular file", disk_name);
140161678Sdavidxu	if (file->st.st_size > SSIZE_MAX)
141161678Sdavidxu		errx(2, "meta data file too large: %s", disk_name);
142201991Sdavidxu	file->data = xmalloc(file->st.st_size);
143177848Sdavidxu
144177848Sdavidxu	if (read(fd, file->data, file->st.st_size) != file->st.st_size)
145161678Sdavidxu		err(2, "cannot read file into memory %s", disk_name);
146201991Sdavidxu
147201991Sdavidxu	file->len = file->st.st_size;
148161678Sdavidxu
149161678Sdavidxu	close(fd);
150161678Sdavidxu
151161678Sdavidxu	return file;
152158377Sdavidxu}
153161678Sdavidxu
154161678Sdavidxuvoid
155161678Sdavidxufree_memory_file(struct memory_file *file)
156201991Sdavidxu{
157138224Sdavidxu	if (file != NULL) {
158115765Sjeff		free(__UNCONST(file->owner));
159161678Sdavidxu		free(__UNCONST(file->group));
160189756Sdavidxu		free(file->data);
161161678Sdavidxu		free(file);
162161678Sdavidxu	}
163161678Sdavidxu}
164161678Sdavidxu