libutil

C Utility Library
git clone http://git.omkov.net/libutil
Log | Tree | Refs | README | LICENCE | Download

libutil/src/mode.c (84 lines, 2.3 KiB) -rw-r--r-- file download

8a5f06f Jamozed 2022-02-09 20:04:50
0
// util/mode.c, version 1.0.3
98e5939 Jamozed 2021-11-27 17:53:46
1
// Mode source file from libutil
5d4006f Jamozed 2020-10-26 13:02:06
2
// Copyright (C) 2020, Jakob Wakeling
7f427d9 Jamozed 2022-03-06 12:55:13
3
// MIT Licence
5d4006f Jamozed 2020-10-26 13:02:06
4
5d4006f Jamozed 2020-10-26 13:02:06
5
/*
5d4006f Jamozed 2020-10-26 13:02:06
6
	TODO Handle copying permissions
5d4006f Jamozed 2020-10-26 13:02:06
7
*/
5d4006f Jamozed 2020-10-26 13:02:06
8
5d4006f Jamozed 2020-10-26 13:02:06
9
#include "mode.h"
5d4006f Jamozed 2020-10-26 13:02:06
10
5d4006f Jamozed 2020-10-26 13:02:06
11
#include <sys/types.h>
5d4006f Jamozed 2020-10-26 13:02:06
12
5d4006f Jamozed 2020-10-26 13:02:06
13
#include <stdio.h>
5d4006f Jamozed 2020-10-26 13:02:06
14
#include <stdlib.h>
5d4006f Jamozed 2020-10-26 13:02:06
15
5d4006f Jamozed 2020-10-26 13:02:06
16
static inline int getop(char **s);
5d4006f Jamozed 2020-10-26 13:02:06
17
static inline mode_t getref(char **s);
5d4006f Jamozed 2020-10-26 13:02:06
18
5d4006f Jamozed 2020-10-26 13:02:06
19
/* Parse an octal or symbolic mode string */
5d4006f Jamozed 2020-10-26 13:02:06
20
chmod_t *strmode(char *str) {
5d4006f Jamozed 2020-10-26 13:02:06
21
	char *s = str; chmod_t *m; mode_t mode = 0; size_t i;
5d4006f Jamozed 2020-10-26 13:02:06
22
	
5d4006f Jamozed 2020-10-26 13:02:06
23
	// Try and parse an octal mode
5d4006f Jamozed 2020-10-26 13:02:06
24
	for (register mode_t d; *s >= '0' && *s <= '7'; ++s) {
5d4006f Jamozed 2020-10-26 13:02:06
25
		d = *s - '0'; if (mode > (07777 - d) / 8) { break; }
5d4006f Jamozed 2020-10-26 13:02:06
26
		mode = mode * 8 + d;
5d4006f Jamozed 2020-10-26 13:02:06
27
	}
5d4006f Jamozed 2020-10-26 13:02:06
28
	
5d4006f Jamozed 2020-10-26 13:02:06
29
	if (!*s) {
5d4006f Jamozed 2020-10-26 13:02:06
30
		m = (chmod_t *)malloc(2 * sizeof (*m));
5d4006f Jamozed 2020-10-26 13:02:06
31
		
5d4006f Jamozed 2020-10-26 13:02:06
32
		// Construct a chmod_t from the octal mode and return it
5d4006f Jamozed 2020-10-26 13:02:06
33
		m[0].flag = MF_NORM; m[1].flag = MF_NULL;
5d4006f Jamozed 2020-10-26 13:02:06
34
		m[0].op = '='; m[0].ref = M_ALL; m[0].mod = mode;
5d4006f Jamozed 2020-10-26 13:02:06
35
		
5d4006f Jamozed 2020-10-26 13:02:06
36
		return m;
5d4006f Jamozed 2020-10-26 13:02:06
37
	}
5d4006f Jamozed 2020-10-26 13:02:06
38
	
5d4006f Jamozed 2020-10-26 13:02:06
39
	// If the octal mode is invalid return NULL
5d4006f Jamozed 2020-10-26 13:02:06
40
	else if (s != str) { return NULL; }
5d4006f Jamozed 2020-10-26 13:02:06
41
	
5d4006f Jamozed 2020-10-26 13:02:06
42
	// Allocate necesary memory for chmod_t array
5d4006f Jamozed 2020-10-26 13:02:06
43
	for (i = 1; *s; ++s) { i += (*s == '+' || *s == '-' || *s == '='); }
8b7b0e1 Jamozed 2020-11-13 00:03:34
44
	m = (chmod_t *)malloc((i + 1) * sizeof (*m)); s = str; m[i].flag = MF_NULL;
5d4006f Jamozed 2020-10-26 13:02:06
45
	
5d4006f Jamozed 2020-10-26 13:02:06
46
	i = 0; do { // Parse each part of the symbolic mode string
5d4006f Jamozed 2020-10-26 13:02:06
47
		for (mode_t ref = getref(&s); ((m[i].op = getop(&s))); ++i) {
5d4006f Jamozed 2020-10-26 13:02:06
48
			m[i].flag = MF_NORM; m[i].ref = ref;
5d4006f Jamozed 2020-10-26 13:02:06
49
			
5d4006f Jamozed 2020-10-26 13:02:06
50
			// Process the next mode
5d4006f Jamozed 2020-10-26 13:02:06
51
			for (m[i].mod = 0;;) switch (*s) {
5d4006f Jamozed 2020-10-26 13:02:06
52
				case 'r': { m[i].mod |= M_RD; ++s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
53
				case 'w': { m[i].mod |= M_WR; ++s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
54
				case 'x': { m[i].mod |= M_EX; ++s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
55
				case 'X': { m[i].flag = MF_XIFX; ++s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
56
				case 's': { m[i].mod |= M_ID; ++s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
57
				case 't': { m[i].mod |= M_ST; ++s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
58
				default: { goto end; }
5d4006f Jamozed 2020-10-26 13:02:06
59
			} end:;
5d4006f Jamozed 2020-10-26 13:02:06
60
		}
5d4006f Jamozed 2020-10-26 13:02:06
61
	} while (*s++ == ',' && *s);
5d4006f Jamozed 2020-10-26 13:02:06
62
	
5d4006f Jamozed 2020-10-26 13:02:06
63
	// If the symbolic mode is invalid return NULL
5d4006f Jamozed 2020-10-26 13:02:06
64
	if (*--s) { free(m); return NULL; } return m;
5d4006f Jamozed 2020-10-26 13:02:06
65
}
5d4006f Jamozed 2020-10-26 13:02:06
66
5d4006f Jamozed 2020-10-26 13:02:06
67
/* Process and return next operator */
5d4006f Jamozed 2020-10-26 13:02:06
68
static inline int getop(char **s) {
5d4006f Jamozed 2020-10-26 13:02:06
69
	switch (**s) { case '+': case '-': case '=': { return *(*s)++; }}
5d4006f Jamozed 2020-10-26 13:02:06
70
	return 0;
5d4006f Jamozed 2020-10-26 13:02:06
71
}
5d4006f Jamozed 2020-10-26 13:02:06
72
5d4006f Jamozed 2020-10-26 13:02:06
73
/* Process and return next reference */
5d4006f Jamozed 2020-10-26 13:02:06
74
static inline mode_t getref(char **s) {
5d4006f Jamozed 2020-10-26 13:02:06
75
	for (mode_t ref = 0;;) switch (**s) {
5d4006f Jamozed 2020-10-26 13:02:06
76
	case 'u': { ref |= M_USR; ++*s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
77
	case 'g': { ref |= M_GRP; ++*s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
78
	case 'o': { ref |= M_OTH; ++*s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
79
	case 'a': { ref |= M_ALL; ++*s; continue; }
5d4006f Jamozed 2020-10-26 13:02:06
80
	default: { return ref; }
5d4006f Jamozed 2020-10-26 13:02:06
81
	}
5d4006f Jamozed 2020-10-26 13:02:06
82
}
83