1/*
2 * Copyright (c) 2001-2007 Apple 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/*
24 *  BLCreateFile.c
25 *  bless
26 *
27 *  Created by Shantonu Sen <ssen@apple.com> on Tue Apr 17 2001.
28 *  Copyright (c) 2001-2007 Apple Inc. All Rights Reserved.
29 *
30 *  $Id: BLCreateFile.c,v 1.26 2006/02/20 22:49:56 ssen Exp $
31 *
32 */
33
34#include <CoreFoundation/CoreFoundation.h>
35
36#include <stdlib.h>
37#include <unistd.h>
38#include <stdio.h>
39#include <sys/param.h>
40#include <sys/stat.h>
41#include <sys/fcntl.h>
42#include <sys/paths.h>
43#include <errno.h>
44
45#include "bless.h"
46#include "bless_private.h"
47#include "bless_private.h"
48
49
50int BLCreateFile(BLContextPtr context, const CFDataRef data,
51                 const char * file, int setImmutable,
52				 uint32_t type, uint32_t creator) {
53
54
55    int err;
56    int mainfd;
57	struct stat sb;
58    const char *rsrcpath = file;
59
60
61	err = lstat(rsrcpath, &sb);
62	if(err == 0) {
63		if(!S_ISREG(sb.st_mode)) {
64			contextprintf(context, kBLLogLevelError, "%s is not a regular file\n",
65						  rsrcpath);
66			return 1;
67		}
68
69		if(sb.st_flags & UF_IMMUTABLE) {
70			uint32_t newflags = sb.st_flags & ~UF_IMMUTABLE;
71
72			contextprintf(context, kBLLogLevelVerbose, "Removing UF_IMMUTABLE from %s\n",
73						  rsrcpath);
74			err = chflags(rsrcpath, newflags);
75			if(err) {
76				contextprintf(context, kBLLogLevelError,
77							  "Can't remove UF_IMMUTABLE from %s: %s\n", rsrcpath,
78							  strerror(errno));
79				return 1;
80			}
81
82		}
83
84
85		contextprintf(context, kBLLogLevelVerbose, "Deleting old %s\n",
86					  rsrcpath);
87		err = unlink(rsrcpath);
88		if(err) {
89			contextprintf(context, kBLLogLevelError,
90						  "Can't delete %s: %s\n", rsrcpath,
91						  strerror(errno));
92			return 1;
93		}
94
95	} else if(errno != ENOENT) {
96		contextprintf(context, kBLLogLevelError,  "Can't access %s: %s\n", rsrcpath,
97					  strerror(errno));
98		return 1;
99	} else {
100		// ENOENT is OK, we'll create the file now
101	}
102
103    mainfd = open(rsrcpath, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
104    if(mainfd < 0) {
105      contextprintf(context, kBLLogLevelError,  "Could not touch %s\n", rsrcpath );
106      return 2;
107    }
108    close(mainfd);
109
110    if(data != NULL) {
111        err = BLCopyFileFromCFData(context, data, rsrcpath, 1);
112        if(err) return 3;
113    }
114
115	if (type || creator) {
116		err = BLSetTypeAndCreator(context, rsrcpath, type, creator);
117		if(err) {
118			contextprintf(context, kBLLogLevelError,
119						  "Error while setting type/creator for %s\n", rsrcpath );
120			return 4;
121		} else {
122			char printType[5], printCreator[5];
123
124			contextprintf(context, kBLLogLevelVerbose, "Type/creator set to %4.4s/%4.4s for %s\n",
125						  blostype2string(type, printType),
126						  blostype2string(creator, printCreator), rsrcpath );
127		}
128	}
129
130	if(setImmutable) {
131		contextprintf(context, kBLLogLevelVerbose, "Setting UF_IMMUTABLE on %s\n",
132					  rsrcpath);
133		err = chflags(rsrcpath, UF_IMMUTABLE);
134		if(err && errno != ENOTSUP) {
135			contextprintf(context, kBLLogLevelError,
136						  "Can't set UF_IMMUTABLE on %s: %s\n", rsrcpath,
137						  strerror(errno));
138			return 5;
139		}
140	}
141
142    return 0;
143}
144