librazor/atomic-ktm.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Aug 23 11:13:48 2014 +0100 (2014-08-23)
changeset 440 48204dea0b9f
parent 423 6112bcc5d1cf
child 441 cf499fd51df7
permissions -rw-r--r--
Remove INTLLIBS from librazor_la_LIBADD.

This partially reverts 611c84a3f4b4538a65d186050608c17adbf17770.
It's not clear what motivated the initial inclusion of INTLLIBS
here since the net effect is only seen in librazor.la and not
in razor.pc and librazor.la is not normally packaged. Certainly
neither the static nor the dynamic versions of librazor currently
use libintl. At best this would cause the linker to search a
static libintl for undefined symbols without finding any; at worse
it causes a static build of plover using librazor.la to fail if
no static version of libintl is installed.
ali@416
     1
/*
ali@416
     2
 * Copyright (C) 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
ali@416
     3
 *
ali@416
     4
 * This program is free software; you can redistribute it and/or modify
ali@416
     5
 * it under the terms of the GNU General Public License as published by
ali@416
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@416
     7
 * (at your option) any later version.
ali@416
     8
 *
ali@416
     9
 * This program is distributed in the hope that it will be useful,
ali@416
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@416
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@416
    12
 * GNU General Public License for more details.
ali@416
    13
 *
ali@416
    14
 * You should have received a copy of the GNU General Public License along
ali@416
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@416
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@416
    17
 */
ali@416
    18
ali@416
    19
#include "config.h"
ali@416
    20
ali@416
    21
#if HAVE_WINDOWS_KTM
ali@416
    22
ali@416
    23
#include <stdlib.h>
ali@416
    24
#include <windows.h>
ali@416
    25
#include <stdio.h>
ali@416
    26
#include <limits.h>
ali@416
    27
#include <errno.h>
ali@416
    28
#include <unistd.h>
ali@416
    29
#include <fcntl.h>
ali@416
    30
#include <sys/stat.h>
ali@416
    31
#include <string.h>
ali@416
    32
#include <assert.h>
ali@416
    33
#include <wchar.h>
ali@416
    34
#include <ktmw32.h>
ali@416
    35
ali@416
    36
#include "razor.h"
ali@416
    37
#include "razor-internal.h"
ali@416
    38
ali@416
    39
#define RAZOR_ASCII_ISALPHA(c)	\
ali@416
    40
			((c) >= 'A' && (c) <= 'Z' || (c) >= 'a' && (c) <= 'z')
ali@416
    41
ali@416
    42
static int
ali@416
    43
razor_valid_root_name2(const wchar_t *name)
ali@416
    44
{
ali@416
    45
	if (razor_allow_all_root_names())
ali@416
    46
		return !wcschr(name, '/');
ali@416
    47
ali@416
    48
	return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' &&
ali@416
    49
	       name[2] == '\0';
ali@416
    50
}
ali@416
    51
ali@416
    52
struct razor_wstr {
ali@416
    53
	wchar_t *str;
ali@416
    54
	int len, allocated;
ali@416
    55
};
ali@416
    56
ali@416
    57
static struct razor_wstr *
ali@416
    58
razor_wstr_create(const char *init, int len)
ali@416
    59
{
ali@416
    60
	int n;
ali@416
    61
	struct razor_wstr *wstr;
ali@416
    62
ali@416
    63
	wstr = malloc(sizeof(struct razor_wstr));
ali@416
    64
ali@416
    65
	n = MultiByteToWideChar(CP_UTF8, 0, init, len, NULL, 0);
ali@416
    66
	if (len >= 0 && init[len])
ali@416
    67
		wstr->len = n++;
ali@416
    68
	else
ali@416
    69
		wstr->len = n - 1;
ali@416
    70
ali@416
    71
	wstr->allocated = n * 2;
ali@416
    72
	wstr->str = malloc(wstr->allocated * sizeof(wchar_t));
ali@416
    73
	if (!wstr->str) {
ali@416
    74
		free(wstr);
ali@416
    75
		return NULL;
ali@416
    76
	}
ali@416
    77
ali@416
    78
	(void)MultiByteToWideChar(CP_UTF8, 0, init, len, wstr->str, n);
ali@416
    79
	if (len >= 0 && init[len])
ali@416
    80
		wstr->str[wstr->len] = 0;
ali@416
    81
ali@416
    82
	return wstr;
ali@416
    83
}
ali@416
    84
ali@416
    85
static int
ali@416
    86
razor_wstr_append(struct razor_wstr *wstr, const char *s, int len)
ali@416
    87
{
ali@416
    88
	int n, allocated;
ali@416
    89
	wchar_t *str;
ali@416
    90
ali@416
    91
	n = MultiByteToWideChar(CP_UTF8, 0, s, len, NULL, 0);
ali@416
    92
	if (len < 0 || !s[len])
ali@416
    93
		n--;
ali@416
    94
ali@416
    95
	if (wstr->allocated <= wstr->len + n) {
ali@416
    96
		allocated = (wstr->len + n + 1) * 2;
ali@416
    97
		str = realloc(wstr->str, allocated * sizeof(wchar_t));
ali@416
    98
		if (!str)
ali@416
    99
			return -1;
ali@416
   100
		wstr->allocated = allocated;
ali@416
   101
		wstr->str = str;
ali@416
   102
	}
ali@416
   103
ali@416
   104
	(void)MultiByteToWideChar(CP_UTF8, 0, s, len, wstr->str + wstr->len, n);
ali@416
   105
	wstr->len += n;
ali@416
   106
	wstr->str[wstr->len] = 0;
ali@416
   107
ali@416
   108
	return 0;
ali@416
   109
}
ali@416
   110
ali@416
   111
static void
ali@416
   112
razor_wstr_destroy(struct razor_wstr *wstr)
ali@416
   113
{
ali@416
   114
	free(wstr->str);
ali@416
   115
	free(wstr);
ali@416
   116
}
ali@416
   117
ali@416
   118
RAZOR_EXPORT struct razor_atomic *
ali@416
   119
razor_atomic_open(const char *description)
ali@416
   120
{
ali@416
   121
	wchar_t *buf;
ali@416
   122
	struct razor_atomic *atomic;
ali@416
   123
ali@416
   124
	atomic = zalloc(sizeof *atomic);
ali@416
   125
	buf = razor_utf8_to_utf16(description, -1);
ali@416
   126
	atomic->transaction = CreateTransaction(NULL, 0,
ali@416
   127
						TRANSACTION_DO_NOT_PROMOTE,
ali@416
   128
						0, 0, 0, buf);
ali@416
   129
	free(buf);
ali@416
   130
ali@416
   131
	return atomic;
ali@416
   132
}
ali@416
   133
ali@416
   134
RAZOR_EXPORT int
ali@416
   135
razor_atomic_commit(struct razor_atomic *atomic)
ali@416
   136
{
ali@416
   137
	int retval;
ali@416
   138
ali@416
   139
	if (razor_atomic_in_error_state(atomic))
ali@416
   140
		return -1;
ali@416
   141
ali@416
   142
	retval = !CommitTransaction(atomic->transaction);
ali@416
   143
ali@416
   144
	if (retval) {
ali@424
   145
		razor_set_error_mswin(&atomic->error, NULL, GetLastError());
ali@416
   146
		RollbackTransaction(atomic->transaction);
ali@416
   147
	}
ali@416
   148
ali@416
   149
	CloseHandle(atomic->transaction);
ali@416
   150
	atomic->transaction = INVALID_HANDLE_VALUE;
ali@416
   151
ali@416
   152
	return retval;
ali@416
   153
}
ali@416
   154
ali@416
   155
RAZOR_EXPORT void
ali@416
   156
razor_atomic_destroy(struct razor_atomic *atomic)
ali@416
   157
{
ali@416
   158
	int i;
ali@416
   159
ali@416
   160
	for(i = 0; i < atomic->n_files; i++) {
ali@416
   161
		if (atomic->files[i].h != INVALID_HANDLE_VALUE) {
ali@416
   162
			CloseHandle(atomic->files[i].h);
ali@416
   163
			free(atomic->files[i].path);
ali@416
   164
		}
ali@416
   165
	}
ali@416
   166
	free(atomic->files);
ali@416
   167
	if (atomic->transaction != INVALID_HANDLE_VALUE) {
ali@416
   168
		RollbackTransaction(atomic->transaction);
ali@416
   169
		CloseHandle(atomic->transaction);
ali@416
   170
	}
ali@423
   171
	if (atomic->error)
ali@423
   172
		razor_error_free(atomic->error);
ali@416
   173
	free(atomic);
ali@416
   174
}
ali@416
   175
ali@416
   176
RAZOR_EXPORT int
ali@416
   177
razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
ali@416
   178
		       const char *path)
ali@416
   179
{
ali@416
   180
	struct razor_wstr *buffer;
ali@416
   181
	const char *slash, *next;
ali@416
   182
	WIN32_FILE_ATTRIBUTE_DATA fa;
ali@416
   183
	DWORD err;
ali@416
   184
	int r, creating = 0;
ali@416
   185
ali@416
   186
	if (razor_atomic_in_error_state(atomic))
ali@416
   187
		return -1;
ali@416
   188
ali@416
   189
	buffer = razor_wstr_create(root, -1);
ali@416
   190
	slash = path;
ali@416
   191
ali@416
   192
	for (; *slash != '\0'; slash = next) {
ali@416
   193
		next = strpbrk(slash + 1, "/\\");
ali@416
   194
		if (next == NULL)
ali@416
   195
			break;
ali@416
   196
ali@416
   197
		razor_wstr_append(buffer, slash, next - slash);
ali@416
   198
ali@416
   199
		if (!creating) {
ali@416
   200
			if (razor_valid_root_name2(buffer->str))
ali@416
   201
				continue;
ali@416
   202
ali@416
   203
			r = GetFileAttributesTransactedW(buffer->str,
ali@416
   204
							 GetFileExInfoStandard,
ali@416
   205
							 &fa,
ali@416
   206
							 atomic->transaction);
ali@416
   207
ali@416
   208
			if (!r) {
ali@416
   209
				err = GetLastError();
ali@416
   210
				if (err == ERROR_FILE_NOT_FOUND) {
ali@416
   211
					creating = 1;
ali@416
   212
				} else {
ali@424
   213
					razor_set_error_mswin(&atomic->error,
ali@424
   214
							      buffer->str, err);
ali@416
   215
					razor_wstr_destroy(buffer);
ali@416
   216
					return -1;
ali@416
   217
				}
ali@416
   218
			} else if (!(fa.dwFileAttributes&
ali@416
   219
				     FILE_ATTRIBUTE_DIRECTORY)) {
ali@424
   220
				razor_set_error2(&atomic->error, buffer->str,
ali@424
   221
						 "Not a directory");
ali@416
   222
				razor_wstr_destroy(buffer);
ali@416
   223
				return -1;
ali@416
   224
			}
ali@416
   225
		}
ali@416
   226
		if (creating) {
ali@416
   227
			if (!CreateDirectoryTransactedW(NULL, buffer->str, NULL,
ali@416
   228
							atomic->transaction)) {
ali@424
   229
				razor_set_error_mswin(&atomic->error,
ali@424
   230
						      buffer->str,
ali@424
   231
						      GetLastError());
ali@416
   232
				razor_wstr_destroy(buffer);
ali@416
   233
				return -1;
ali@416
   234
			}
ali@416
   235
ali@416
   236
			/* FIXME: What to do about permissions for dirs we
ali@416
   237
			 * have to create but are not in the cpio archive? */
ali@416
   238
		}
ali@416
   239
	}
ali@416
   240
ali@416
   241
	razor_wstr_destroy(buffer);
ali@416
   242
ali@416
   243
	return 0;
ali@416
   244
}
ali@416
   245
ali@416
   246
RAZOR_EXPORT int
ali@416
   247
razor_atomic_remove(struct razor_atomic *atomic, const char *path)
ali@416
   248
{
ali@416
   249
	wchar_t *buf;
ali@416
   250
	DWORD err;
ali@416
   251
ali@416
   252
	if (razor_atomic_in_error_state(atomic))
ali@416
   253
		return -1;
ali@416
   254
ali@416
   255
	buf = razor_utf8_to_utf16(path, -1);
ali@416
   256
ali@416
   257
	if (DeleteFileTransactedW(buf, atomic->transaction)) {
ali@416
   258
		free(buf);
ali@416
   259
		return 0;
ali@416
   260
	}
ali@416
   261
ali@416
   262
	err = GetLastError();
ali@416
   263
	if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
ali@416
   264
		free(buf);
ali@416
   265
		return 0;
ali@416
   266
	}
ali@416
   267
ali@416
   268
	if (SetFileAttributesTransactedW(buf, FILE_ATTRIBUTE_NORMAL,
ali@416
   269
					 atomic->transaction)) {
ali@416
   270
		if (DeleteFileTransactedW(buf, atomic->transaction)) {
ali@416
   271
			free(buf);
ali@416
   272
			return 0;
ali@416
   273
		}
ali@416
   274
		err = GetLastError();
ali@416
   275
	}
ali@416
   276
ali@416
   277
	if (RemoveDirectoryTransactedW(buf, atomic->transaction) ||
ali@416
   278
	    GetLastError() == ERROR_DIR_NOT_EMPTY) {
ali@416
   279
		free(buf);
ali@416
   280
		return 0;
ali@416
   281
	}
ali@416
   282
ali@416
   283
	/*
ali@416
   284
	 * It would be tempting to use:
ali@416
   285
	 * 	MoveFileEx(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)
ali@416
   286
	 * but unless we can guarantee that the system will be rebooted
ali@416
   287
	 * before we (or some other application) write another file with the
ali@416
   288
	 * same path, this is likely to cause more problems than it solves.
ali@416
   289
	 */
ali@416
   290
ali@424
   291
	razor_set_error_mswin(&atomic->error, buf, err);
ali@416
   292
	free(buf);
ali@416
   293
	return -1;
ali@416
   294
}
ali@416
   295
ali@416
   296
RAZOR_EXPORT int
ali@416
   297
razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
ali@416
   298
			 const char *newpath)
ali@416
   299
{
ali@416
   300
	wchar_t *oldbuf, *newbuf;
ali@416
   301
	const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
ali@416
   302
ali@416
   303
	if (razor_atomic_in_error_state(atomic))
ali@416
   304
		return -1;
ali@416
   305
ali@416
   306
	newbuf = razor_utf8_to_utf16(newpath, -1);
ali@416
   307
	oldbuf = razor_utf8_to_utf16(oldpath, -1);
ali@416
   308
ali@416
   309
	/*
ali@416
   310
	 * Passing MOVEFILE_REPLACE_EXISTING to MoveFileTransaction() will
ali@416
   311
	 * cover every case we care about _except_ replacing an empty
ali@416
   312
	 * directory with a file. Calling RemoveDirectoryTransacted() will deal
ali@416
   313
	 * with this case while having no effect in all other cases.
ali@416
   314
	 */
ali@416
   315
	(void)RemoveDirectoryTransactedW(newbuf, atomic->transaction);
ali@416
   316
ali@416
   317
	if (!MoveFileTransactedW(oldbuf, newbuf, NULL, NULL, flags,
ali@416
   318
			         atomic->transaction))
ali@424
   319
		razor_set_error_mswin(&atomic->error, newbuf, GetLastError());
ali@416
   320
ali@416
   321
	free(newbuf);
ali@416
   322
	free(oldbuf);
ali@416
   323
ali@423
   324
	return razor_atomic_in_error_state(atomic);
ali@416
   325
}
ali@416
   326
ali@416
   327
RAZOR_EXPORT int
ali@416
   328
razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
ali@416
   329
			mode_t mode)
ali@416
   330
{
ali@416
   331
	wchar_t *buf;
ali@416
   332
	DWORD err;
ali@416
   333
	WIN32_FILE_ATTRIBUTE_DATA fa;
ali@416
   334
ali@416
   335
	if (razor_atomic_in_error_state(atomic))
ali@416
   336
		return -1;
ali@416
   337
ali@416
   338
	buf = razor_utf8_to_utf16(dirname, -1);
ali@416
   339
ali@416
   340
	if (!CreateDirectoryTransactedW(NULL, buf, NULL, atomic->transaction)) {
ali@416
   341
		err = GetLastError();
ali@416
   342
		if (err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS) {
ali@416
   343
abort:
ali@424
   344
			razor_set_error_mswin(&atomic->error, buf, err);
ali@416
   345
			free(buf);
ali@416
   346
			return -1;
ali@416
   347
		}
ali@416
   348
ali@416
   349
		if (!GetFileAttributesTransactedW(buf, GetFileExInfoStandard,
ali@416
   350
						  &fa, atomic->transaction))
ali@416
   351
			goto abort;
ali@416
   352
ali@416
   353
		if (!(fa.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) {
ali@416
   354
			if (razor_atomic_remove(atomic, dirname)) {
ali@416
   355
				free(buf);
ali@416
   356
				return -1;
ali@416
   357
			}
ali@416
   358
			if (!CreateDirectoryTransactedW(NULL, buf, NULL,
ali@416
   359
							atomic->transaction)) {
ali@416
   360
				err = GetLastError();
ali@416
   361
				goto abort;
ali@416
   362
			}
ali@416
   363
		}
ali@416
   364
	}
ali@416
   365
ali@416
   366
	free(buf);
ali@416
   367
ali@416
   368
	return 0;
ali@416
   369
}
ali@416
   370
ali@416
   371
RAZOR_EXPORT int
ali@416
   372
razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
ali@416
   373
			    const char *path)
ali@416
   374
{
ali@416
   375
	if (razor_atomic_in_error_state(atomic))
ali@416
   376
		return -1;
ali@416
   377
ali@416
   378
	/*
ali@416
   379
	 * This isn't true, but symbolic links under Windows 7
ali@416
   380
	 * need to know whether the target is a directory or not
ali@416
   381
	 * and we don't always know that at the time when the
ali@416
   382
	 * link is created, so it's a convienent lie for now.
ali@416
   383
	 */
ali@424
   384
	razor_set_error(&atomic->error, NULL,
ali@424
   385
			"Symbolic links not supported on this platform");
ali@416
   386
ali@416
   387
	return -1;
ali@416
   388
}
ali@416
   389
ali@416
   390
RAZOR_EXPORT int
ali@416
   391
razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
ali@416
   392
			 mode_t mode)
ali@416
   393
{
ali@416
   394
	DWORD attribs;
ali@416
   395
	struct razor_atomic_file *files;
ali@416
   396
	int i = atomic->n_files;
ali@416
   397
ali@416
   398
	if (razor_atomic_in_error_state(atomic))
ali@416
   399
		return -1;
ali@416
   400
ali@416
   401
	files = realloc(atomic->files,
ali@416
   402
			(atomic->n_files+1) * sizeof(struct razor_atomic_file));
ali@416
   403
	if (!files) {
ali@424
   404
		razor_set_error(&atomic->error, NULL, "Not enough memory");
ali@416
   405
		return -1;
ali@416
   406
	}
ali@416
   407
	atomic->n_files++;
ali@416
   408
	atomic->files = files;
ali@416
   409
ali@416
   410
	files[i].path = razor_utf8_to_utf16(filename, -1);
ali@416
   411
ali@416
   412
	/*
ali@416
   413
	 * Passing CREATE_ALWAYS to CreateFileTransacted() will cover
ali@416
   414
	 * every case we care about _except_ replacing an empty directory
ali@416
   415
	 * with a file. Calling RemoveDirectoryTransacted() will deal
ali@416
   416
	 * with this case while having no effect in all other cases.
ali@416
   417
	 */
ali@416
   418
	(void)RemoveDirectoryTransactedW(files[i].path, atomic->transaction);
ali@416
   419
ali@416
   420
	if (mode & S_IWUSR)
ali@416
   421
		attribs = FILE_ATTRIBUTE_NORMAL;
ali@416
   422
	else
ali@416
   423
		attribs = FILE_ATTRIBUTE_READONLY;
ali@416
   424
ali@416
   425
	files[i].h = CreateFileTransactedW(files[i].path, GENERIC_WRITE,
ali@416
   426
					   0, NULL, CREATE_ALWAYS, attribs,
ali@416
   427
					   NULL, atomic->transaction, NULL,
ali@416
   428
					   NULL);
ali@416
   429
ali@416
   430
	if (files[i].h == INVALID_HANDLE_VALUE) {
ali@424
   431
		razor_set_error_mswin(&atomic->error, files[i].path,
ali@424
   432
				      GetLastError());
ali@416
   433
		free(files[i].path);
ali@416
   434
		atomic->n_files--;
ali@416
   435
		return -1;
ali@416
   436
	}
ali@416
   437
ali@416
   438
	return i;
ali@416
   439
}
ali@416
   440
ali@416
   441
RAZOR_EXPORT int
ali@416
   442
razor_atomic_write(struct razor_atomic *atomic, int handle, const void *data,
ali@416
   443
		   size_t size)
ali@416
   444
{
ali@416
   445
	DWORD written;
ali@416
   446
ali@416
   447
	if (razor_atomic_in_error_state(atomic))
ali@416
   448
		return -1;
ali@416
   449
ali@416
   450
	assert(handle < atomic->n_files);
ali@416
   451
	assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
ali@416
   452
ali@416
   453
	while(size) {
ali@416
   454
		if (!WriteFile(atomic->files[handle].h, data, size, &written,
ali@416
   455
			       NULL)) {
ali@424
   456
			razor_set_error_mswin(&atomic->error,
ali@424
   457
					      atomic->files[handle].path,
ali@424
   458
					      GetLastError());
ali@416
   459
ali@416
   460
			(void)CloseHandle(atomic->files[handle].h);
ali@416
   461
			free(atomic->files[handle].path);
ali@416
   462
			atomic->files[handle].path = NULL;
ali@416
   463
			atomic->files[handle].h = INVALID_HANDLE_VALUE;
ali@416
   464
ali@416
   465
			return -1;
ali@416
   466
		}
ali@416
   467
ali@416
   468
		data += written;
ali@416
   469
		size -= written;
ali@416
   470
	}
ali@416
   471
ali@416
   472
	return 0;
ali@416
   473
}
ali@416
   474
ali@416
   475
RAZOR_EXPORT int
ali@416
   476
razor_atomic_sync(struct razor_atomic *atomic, int handle)
ali@416
   477
{
ali@416
   478
	HANDLE h;
ali@416
   479
ali@416
   480
	if (razor_atomic_in_error_state(atomic))
ali@416
   481
		return -1;
ali@416
   482
ali@416
   483
	assert(handle < atomic->n_files);
ali@416
   484
	assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
ali@416
   485
ali@416
   486
	if (!CloseHandle(atomic->files[handle].h)) {
ali@424
   487
		razor_set_error_mswin(&atomic->error,
ali@424
   488
				      atomic->files[handle].path,
ali@424
   489
				      GetLastError());
ali@416
   490
		free(atomic->files[handle].path);
ali@416
   491
		atomic->files[handle].path = NULL;
ali@416
   492
		atomic->files[handle].h = INVALID_HANDLE_VALUE;
ali@416
   493
		return -1;
ali@416
   494
	}
ali@416
   495
ali@416
   496
	h = CreateFileTransactedW(atomic->files[handle].path, GENERIC_WRITE, 0,
ali@416
   497
				  NULL, OPEN_EXISTING, 0, NULL,
ali@416
   498
				  atomic->transaction, NULL, NULL);
ali@416
   499
	atomic->files[handle].h = h;
ali@416
   500
ali@416
   501
	if (atomic->files[handle].h == INVALID_HANDLE_VALUE) {
ali@424
   502
		razor_set_error_mswin(&atomic->error,
ali@424
   503
				      atomic->files[handle].path,
ali@424
   504
				      GetLastError());
ali@416
   505
		free(atomic->files[handle].path);
ali@416
   506
		atomic->files[handle].path = NULL;
ali@416
   507
		return -1;
ali@416
   508
	}
ali@416
   509
ali@423
   510
	return razor_atomic_in_error_state(atomic);
ali@416
   511
}
ali@416
   512
ali@416
   513
RAZOR_EXPORT int
ali@416
   514
razor_atomic_close(struct razor_atomic *atomic, int handle)
ali@416
   515
{
ali@416
   516
	if (razor_atomic_in_error_state(atomic))
ali@416
   517
		return -1;
ali@416
   518
ali@416
   519
	assert(handle < atomic->n_files);
ali@416
   520
	assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
ali@416
   521
ali@416
   522
	if (!CloseHandle(atomic->files[handle].h))
ali@424
   523
		razor_set_error_mswin(&atomic->error,
ali@424
   524
				      atomic->files[handle].path,
ali@424
   525
				      GetLastError());
ali@416
   526
ali@416
   527
	free(atomic->files[handle].path);
ali@416
   528
	atomic->files[handle].path = NULL;
ali@416
   529
	atomic->files[handle].h = INVALID_HANDLE_VALUE;
ali@416
   530
ali@416
   531
	while(atomic->n_files > 0 &&
ali@416
   532
	      atomic->files[atomic->n_files-1].h == INVALID_HANDLE_VALUE)
ali@416
   533
		atomic->n_files--;
ali@416
   534
ali@423
   535
	return razor_atomic_in_error_state(atomic);
ali@416
   536
}
ali@416
   537
ali@416
   538
#endif		/* HAVE_WINDOWS_KTM */