summaryrefslogblamecommitdiffstats
path: root/sys-utils/fsfreeze.c
blob: 401ab5c980c3f9078fdb56b8fff78db7381d7665 (plain) (tree)





















                                                                 
 
              

                   
                        
                     
 





                   
                                                     
 

                                 
                    
                                                                                

                                    
                                                           
 


                                                                      
                                    

                                              
 
                           




                               
                                             


                       
                                                 




                                                    

          
                                                                                  




                                                                      


                                           
                             
 
                                                                             


                                                                  

                           
                                

                              
                                        

                              
                                          
                              


                                                   
                        
                                                 


                 

                                                                                  





                                                               
                                         



                                  
                                                             

                                   
                                                   







                                                         

                         
                                             


                                                           

                      
                                           


                                                             


                        








                          
/*
 * fsfreeze.c -- Filesystem freeze/unfreeze IO for Linux
 *
 * Copyright (C) 2010 Hajime Taira <htaira@redhat.com>
 *                    Masatake Yamato <yamato@redhat.com>
 *
 * 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 1 or
 * (at your option) any later version.
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>

#include "c.h"
#include "blkdev.h"
#include "nls.h"
#include "closestream.h"
#include "optutils.h"

enum fs_operation {
	NOOP,
	FREEZE,
	UNFREEZE
};

static void __attribute__((__noreturn__)) usage(void)
{
	FILE *out = stdout;
	fputs(USAGE_HEADER, out);
	fprintf(out,
	      _(" %s [options] <mountpoint>\n"), program_invocation_short_name);

	fputs(USAGE_SEPARATOR, out);
	fputs(_("Suspend access to a filesystem.\n"), out);

	fputs(USAGE_OPTIONS, out);
	fputs(_(" -f, --freeze      freeze the filesystem\n"), out);
	fputs(_(" -u, --unfreeze    unfreeze the filesystem\n"), out);
	fputs(USAGE_SEPARATOR, out);
	printf(USAGE_HELP_OPTIONS(19));
	printf(USAGE_MAN_TAIL("fsfreeze(8)"));

	exit(EXIT_SUCCESS);
}

int main(int argc, char **argv)
{
	int fd = -1, c;
	int action = NOOP, rc = EXIT_FAILURE;
	char *path;
	struct stat sb;

	static const struct option longopts[] = {
	    { "help",      no_argument, NULL, 'h' },
	    { "freeze",    no_argument, NULL, 'f' },
	    { "unfreeze",  no_argument, NULL, 'u' },
	    { "version",   no_argument, NULL, 'V' },
	    { NULL, 0, NULL, 0 }
	};

	static const ul_excl_t excl[] = {       /* rows and cols in ASCII order */
		{ 'f','u' },			/* freeze, unfreeze */
		{ 0 }
	};
	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	atexit(close_stdout);

	while ((c = getopt_long(argc, argv, "hfuV", longopts, NULL)) != -1) {

		err_exclusive_options(c, longopts, excl, excl_st);

		switch(c) {
		case 'h':
			usage();
			break;
		case 'f':
			action = FREEZE;
			break;
		case 'u':
			action = UNFREEZE;
			break;
		case 'V':
			printf(UTIL_LINUX_VERSION);
			exit(EXIT_SUCCESS);
		default:
			errtryhelp(EXIT_FAILURE);
		}
	}

	if (action == NOOP)
		errx(EXIT_FAILURE, _("neither --freeze or --unfreeze specified"));
	if (optind == argc)
		errx(EXIT_FAILURE, _("no filename specified"));
	path = argv[optind++];

	if (optind != argc) {
		warnx(_("unexpected number of arguments"));
		errtryhelp(EXIT_FAILURE);
	}

	fd = open(path, O_RDONLY);
	if (fd < 0)
		err(EXIT_FAILURE, _("cannot open %s"), path);

	if (fstat(fd, &sb) == -1) {
		warn(_("stat of %s failed"), path);
		goto done;
	}

	if (!S_ISDIR(sb.st_mode)) {
		warnx(_("%s: is not a directory"), path);
		goto done;
	}

	switch (action) {
	case FREEZE:
		if (ioctl(fd, FIFREEZE, 0)) {
			warn(_("%s: freeze failed"), path);
			goto done;
		}
		break;
	case UNFREEZE:
		if (ioctl(fd, FITHAW, 0)) {
			warn(_("%s: unfreeze failed"), path);
			goto done;
		}
		break;
	default:
		abort();
	}

	rc = EXIT_SUCCESS;
done:
	if (fd >= 0)
		close(fd);
	return rc;
}