1/*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 *
23 * db_commands.cpp -- commands to directly manipulate Db's using the DL API.
24 */
25
26#include "db_commands.h"
27
28#include "readline.h"
29#include "security.h"
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <security_cdsa_client/dlclient.h>
35
36using namespace CssmClient;
37
38static int
39do_db_create(const CSSM_GUID guid, const char *dbname, Boolean do_openparams, Boolean do_autocommit, Boolean do_mode, mode_t mode, Boolean do_version_0_params)
40{
41	int result = 0;
42
43	try
44	{
45		CSSM_APPLEDL_OPEN_PARAMETERS openParameters = { sizeof(CSSM_APPLEDL_OPEN_PARAMETERS),
46			(do_version_0_params ? 0 : CSSM_APPLEDL_OPEN_PARAMETERS_VERSION) };
47		Cssm cssm;
48		Module module(guid, cssm);
49		DL dl(module);
50		Db db(dl, dbname);
51
52		if (do_openparams)
53		{
54			openParameters.autoCommit = do_autocommit;
55			if (!do_version_0_params && do_mode)
56			{
57				openParameters.mask |= kCSSM_APPLEDL_MASK_MODE;
58				openParameters.mode = mode;
59			}
60
61			db->openParameters(&openParameters);
62		}
63
64		db->create();
65	}
66	catch (const CommonError &e)
67	{
68		OSStatus status = e.osStatus();
69		sec_error("CSSM_DbCreate %s: %s", dbname, sec_errstr(status));
70	}
71	catch (...)
72	{
73		result = 1;
74	}
75
76	return result;
77}
78
79static int
80parse_guid(const char *name, CSSM_GUID *guid)
81{
82	size_t len = strlen(name);
83
84	if (!strncmp("dl", name, len))
85		*guid = gGuidAppleFileDL;
86	else if (!strncmp("cspdl", name, len))
87		*guid = gGuidAppleCSPDL;
88	else
89	{
90		sec_error("Invalid guid: %s", name);
91		return 2;
92	}
93
94	return 0;
95}
96
97
98static int
99parse_mode(const char *name, mode_t *pmode)
100{
101	int result = 0;
102	mode_t mode = 0;
103	const char *p;
104
105	if (!name || !pmode || *name != '0')
106	{
107		result = 2;
108		goto loser;
109	}
110
111	for (p = name + 1; *p; ++p)
112	{
113		if (*p < '0' || *p > '7')
114		{
115			result = 2;
116			goto loser;
117		}
118
119		mode = (mode << 3) + *p - '0';
120	}
121
122	*pmode = mode;
123	return 0;
124
125loser:
126	sec_error("Invalid mode: %s", name);
127	return result;
128}
129
130int
131db_create(int argc, char * const *argv)
132{
133	int free_dbname = 0;
134	char *dbname = NULL;
135	int ch, result = 0;
136	bool do_autocommit = true, do_mode = false;
137	bool do_openparams = false, do_version_0_params = false;
138	mode_t mode = 0666;
139	CSSM_GUID guid = gGuidAppleFileDL;
140
141	while ((ch = getopt(argc, argv, "0ahg:m:o")) != -1)
142	{
143		switch  (ch)
144		{
145		case '0':
146			do_version_0_params = true;
147			do_openparams = true;
148			break;
149		case 'a':
150			do_autocommit = false;
151			do_openparams = true;
152			break;
153		case 'g':
154			result = parse_guid(optarg, &guid);
155			if (result)
156				goto loser;
157			break;
158		case 'm':
159			result = parse_mode(optarg, &mode);
160			if (result)
161				goto loser;
162			do_mode = true;
163			do_openparams = true;
164			break;
165		case 'o':
166			do_openparams = true;
167			break;
168		case '?':
169		default:
170			return 2; /* @@@ Return 2 triggers usage message. */
171		}
172	}
173
174	argc -= optind;
175	argv += optind;
176
177	if (argc > 0)
178		dbname = *argv;
179	else
180	{
181		fprintf(stderr, "db to create: ");
182		dbname = readline(NULL, 0);
183		if (!dbname)
184		{
185			result = -1;
186			goto loser;
187		}
188
189		free_dbname = 1;
190		if (*dbname == '\0')
191			goto loser;
192	}
193
194	do
195	{
196		result = do_db_create(guid, dbname, do_openparams, do_autocommit, do_mode, mode, do_version_0_params);
197		if (result)
198			goto loser;
199
200		argc--;
201		argv++;
202		dbname = *argv;
203	} while (argc > 0);
204
205loser:
206	if (free_dbname)
207		free(dbname);
208
209	return result;
210}
211