⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chmod.c

📁 Rsync 3.0.5 source code
💻 C
字号:
/* * Implement the core of the --chmod option. * * Copyright (C) 2002 Scott Howard * Copyright (C) 2005-2008 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, visit the http://fsf.org website. */#include "rsync.h"extern mode_t orig_umask;#define FLAG_X_KEEP (1<<0)#define FLAG_DIRS_ONLY (1<<1)#define FLAG_FILES_ONLY (1<<2)struct chmod_mode_struct {	struct chmod_mode_struct *next;	int ModeAND, ModeOR;	char flags;};#define CHMOD_ADD 1#define CHMOD_SUB 2#define CHMOD_EQ  3#define STATE_ERROR 0#define STATE_1ST_HALF 1#define STATE_2ND_HALF 2/* Parse a chmod-style argument, and break it down into one or more AND/OR * pairs in a linked list.  We return a pointer to new items on succcess * (appending the items to the specified list), or NULL on error. */struct chmod_mode_struct *parse_chmod(const char *modestr,				      struct chmod_mode_struct **root_mode_ptr){	int state = STATE_1ST_HALF;	int where = 0, what = 0, op = 0, topbits = 0, topoct = 0, flags = 0;	struct chmod_mode_struct *first_mode = NULL, *curr_mode = NULL,				 *prev_mode = NULL;	while (state != STATE_ERROR) {		if (!*modestr || *modestr == ',') {			int bits;			if (!op) {				state = STATE_ERROR;				break;			}			prev_mode = curr_mode;			curr_mode = new_array(struct chmod_mode_struct, 1);			if (prev_mode)				prev_mode->next = curr_mode;			else				first_mode = curr_mode;			curr_mode->next = NULL;			if (where)				bits = where * what;			else {				where = 0111;				bits = (where * what) & ~orig_umask;			}			switch (op) {			case CHMOD_ADD:				curr_mode->ModeAND = CHMOD_BITS;				curr_mode->ModeOR  = bits + topoct;				break;			case CHMOD_SUB:				curr_mode->ModeAND = CHMOD_BITS - bits - topoct;				curr_mode->ModeOR  = 0;				break;			case CHMOD_EQ:				curr_mode->ModeAND = CHMOD_BITS - (where * 7) - (topoct ? topbits : 0);				curr_mode->ModeOR  = bits + topoct;				break;			}			curr_mode->flags = flags;			if (!*modestr)				break;			modestr++;			state = STATE_1ST_HALF;			where = what = op = topoct = topbits = flags = 0;		}		if (state != STATE_2ND_HALF) {			switch (*modestr) {			case 'D':				if (flags & FLAG_FILES_ONLY)					state = STATE_ERROR;				flags |= FLAG_DIRS_ONLY;				break;			case 'F':				if (flags & FLAG_DIRS_ONLY)					state = STATE_ERROR;				flags |= FLAG_FILES_ONLY;				break;			case 'u':				where |= 0100;				topbits |= 04000;				break;			case 'g':				where |= 0010;				topbits |= 02000;				break;			case 'o':				where |= 0001;				break;			case 'a':				where |= 0111;				break;			case '+':				op = CHMOD_ADD;				state = STATE_2ND_HALF;				break;			case '-':				op = CHMOD_SUB;				state = STATE_2ND_HALF;				break;			case '=':				op = CHMOD_EQ;				state = STATE_2ND_HALF;				break;			default:				state = STATE_ERROR;				break;			}		} else {			switch (*modestr) {			case 'r':				what |= 4;				break;			case 'w':				what |= 2;				break;			case 'X':				flags |= FLAG_X_KEEP;				/* FALL THROUGH */			case 'x':				what |= 1;				break;			case 's':				if (topbits)					topoct |= topbits;				else					topoct = 04000;				break;			case 't':				topoct |= 01000;				break;			default:				state = STATE_ERROR;				break;			}		}		modestr++;	}	if (state == STATE_ERROR) {		free_chmod_mode(first_mode);		return NULL;	}	if (!(curr_mode = *root_mode_ptr))		*root_mode_ptr = first_mode;	else {		while (curr_mode->next)			curr_mode = curr_mode->next;		curr_mode->next = first_mode;	}	return first_mode;}/* Takes an existing file permission and a list of AND/OR changes, and * create a new permissions. */int tweak_mode(int mode, struct chmod_mode_struct *chmod_modes){	int IsX = mode & 0111;	int NonPerm = mode & ~CHMOD_BITS;	for ( ; chmod_modes; chmod_modes = chmod_modes->next) {		if ((chmod_modes->flags & FLAG_DIRS_ONLY) && !S_ISDIR(NonPerm))			continue;		if ((chmod_modes->flags & FLAG_FILES_ONLY) && S_ISDIR(NonPerm))			continue;		mode &= chmod_modes->ModeAND;		if ((chmod_modes->flags & FLAG_X_KEEP) && !IsX && !S_ISDIR(NonPerm))			mode |= chmod_modes->ModeOR & ~0111;		else			mode |= chmod_modes->ModeOR;	}	return mode | NonPerm;}/* Free the linked list created by parse_chmod. */int free_chmod_mode(struct chmod_mode_struct *chmod_modes){	struct chmod_mode_struct *next;	while (chmod_modes) {		next = chmod_modes->next;		free(chmod_modes);		chmod_modes = next;	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -