00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <dirent.h>
00033 #include <fcntl.h>
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <fcntl.h>
00037 #include <macros.h>
00038 #include <getopt.h>
00039 #include <stdarg.h>
00040 #include <str.h>
00041 #include <ctype.h>
00042
00043 #include "config.h"
00044 #include "errors.h"
00045 #include "util.h"
00046 #include "entry.h"
00047 #include "mkfile.h"
00048 #include "cmds.h"
00049
00051 #define BUFFER_SIZE 16384
00052
00053 static const char *cmdname = "mkfile";
00054
00055 static struct option const long_options[] = {
00056 {"size", required_argument, 0, 's'},
00057 {"help", no_argument, 0, 'h'},
00058 {0, 0, 0, 0}
00059 };
00060
00061 void help_cmd_mkfile(unsigned int level)
00062 {
00063 if (level == HELP_SHORT) {
00064 printf("`%s' creates a new zero-filled file\n", cmdname);
00065 } else {
00066 help_cmd_mkfile(HELP_SHORT);
00067 printf(
00068 "Usage: %s [options] <path>\n"
00069 "Options:\n"
00070 " -h, --help A short option summary\n"
00071 " -s, --size sz Size of the file\n"
00072 "\n"
00073 "Size is a number followed by 'k', 'm' or 'g' for kB, MB, GB.\n"
00074 "E.g. 100k, 2m, 1g.\n",
00075 cmdname);
00076 }
00077
00078 return;
00079 }
00080
00089 static ssize_t read_size(const char *str)
00090 {
00091 ssize_t number, unit;
00092 char *ep;
00093
00094 number = strtol(str, &ep, 10);
00095 if (ep[0] == '\0')
00096 return number;
00097
00098 if (ep[1] != '\0')
00099 return -1;
00100
00101 switch (tolower(ep[0])) {
00102 case 'k': unit = 1024; break;
00103 case 'm': unit = 1024*1024; break;
00104 case 'g': unit = 1024*1024*1024; break;
00105 default: return -1;
00106 }
00107
00108 return number * unit;
00109 }
00110
00111 int cmd_mkfile(char **argv)
00112 {
00113 unsigned int argc;
00114 int c, opt_ind;
00115 int fd;
00116 ssize_t file_size;
00117 ssize_t total_written;
00118 ssize_t to_write, rc;
00119 char *file_name;
00120 void *buffer;
00121
00122 file_size = 0;
00123
00124 argc = cli_count_args(argv);
00125
00126 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
00127 c = getopt_long(argc, argv, "s:h", long_options, &opt_ind);
00128 switch (c) {
00129 case 'h':
00130 help_cmd_mkfile(HELP_LONG);
00131 return CMD_SUCCESS;
00132 case 's':
00133 file_size = read_size(optarg);
00134 if (file_size < 0) {
00135 printf("%s: Invalid file size specification.\n",
00136 cmdname);
00137 return CMD_FAILURE;
00138 }
00139 break;
00140 }
00141 }
00142
00143 argc -= optind;
00144
00145 if (argc != 1) {
00146 printf("%s: incorrect number of arguments. Try `%s --help'\n",
00147 cmdname, cmdname);
00148 return CMD_FAILURE;
00149 }
00150
00151 file_name = argv[optind];
00152
00153 fd = open(file_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
00154 if (fd < 0) {
00155 printf("%s: failed to create file %s.\n", cmdname, file_name);
00156 return CMD_FAILURE;
00157 }
00158
00159 buffer = calloc(BUFFER_SIZE, 1);
00160 if (buffer == NULL) {
00161 printf("%s: Error, out of memory.\n", cmdname);
00162 return CMD_FAILURE;
00163 }
00164
00165 total_written = 0;
00166 while (total_written < file_size) {
00167 to_write = min(file_size - total_written, BUFFER_SIZE);
00168 rc = write(fd, buffer, to_write);
00169 if (rc <= 0) {
00170 printf("%s: Error writing file (%zd).\n", cmdname, rc);
00171 close(fd);
00172 return CMD_FAILURE;
00173 }
00174 total_written += rc;
00175 }
00176
00177 rc = close(fd);
00178 if (rc != 0) {
00179 printf("%s: Error writing file (%zd).\n", cmdname, rc);
00180 return CMD_FAILURE;
00181 }
00182
00183 free(buffer);
00184
00185 return CMD_SUCCESS;
00186 }