more stuff

This commit is contained in:
Eric Andersen 1999-10-07 08:30:23 +00:00
parent 5c3199e0a5
commit 596e5469d0
15 changed files with 1033 additions and 1142 deletions

View File

@ -23,7 +23,7 @@ BINDIR=$(prefix)
LDFLAGS= -s LDFLAGS= -s
LIBRARIES=-lc LIBRARIES=-lc
OBJECTS=$(shell ./busybox.sh) utility.o OBJECTS=$(shell ./busybox.sh)
CFLAGS+= -DBB_VER='"$(VERSION)"' CFLAGS+= -DBB_VER='"$(VERSION)"'
CFLAGS+= -DBB_BT='"$(BUILDTIME)"' CFLAGS+= -DBB_BT='"$(BUILDTIME)"'

View File

@ -111,7 +111,7 @@ static const struct Applet applets[] = {
{"mt", mt_main}, {"mt", mt_main},
#endif #endif
#ifdef BB_MV //bin #ifdef BB_MV //bin
{"mv", dyadic_main}, {"mv", mv_main},
#endif #endif
#ifdef BB_PRINTF //usr/bin #ifdef BB_PRINTF //usr/bin
{"printf", printf_main}, {"printf", printf_main},
@ -144,7 +144,7 @@ static const struct Applet applets[] = {
{"sync", sync_main}, {"sync", sync_main},
#endif #endif
#ifdef BB_TOUCH //usr/bin #ifdef BB_TOUCH //usr/bin
{"touch", monadic_main}, {"touch", touch_main},
#endif #endif
#ifdef BB_TRUE //bin #ifdef BB_TRUE //bin
{"true", true_main}, {"true", true_main},
@ -208,8 +208,8 @@ int busybox_main(int argc, char **argv)
const struct Applet *a = applets; const struct Applet *a = applets;
fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n", fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n",
BB_VER, BB_BT); BB_VER, BB_BT);
fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, "\nUsage:\t[function] [arguments]...\n");
fprintf(stderr, "or\nUsage: [function] [arguments]...\n"); fprintf(stderr, "\tbusybox [function] [arguments]...\n");
fprintf(stderr, fprintf(stderr,
"\n\tMost people will create a symlink to busybox for each\n" "\n\tMost people will create a symlink to busybox for each\n"
"\tfunction name, and busybox will act like whatever you invoke it as.\n"); "\tfunction name, and busybox will act like whatever you invoke it as.\n");

View File

@ -111,7 +111,7 @@ static const struct Applet applets[] = {
{"mt", mt_main}, {"mt", mt_main},
#endif #endif
#ifdef BB_MV //bin #ifdef BB_MV //bin
{"mv", dyadic_main}, {"mv", mv_main},
#endif #endif
#ifdef BB_PRINTF //usr/bin #ifdef BB_PRINTF //usr/bin
{"printf", printf_main}, {"printf", printf_main},
@ -144,7 +144,7 @@ static const struct Applet applets[] = {
{"sync", sync_main}, {"sync", sync_main},
#endif #endif
#ifdef BB_TOUCH //usr/bin #ifdef BB_TOUCH //usr/bin
{"touch", monadic_main}, {"touch", touch_main},
#endif #endif
#ifdef BB_TRUE //bin #ifdef BB_TRUE //bin
{"true", true_main}, {"true", true_main},
@ -208,8 +208,8 @@ int busybox_main(int argc, char **argv)
const struct Applet *a = applets; const struct Applet *a = applets;
fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n", fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n",
BB_VER, BB_BT); BB_VER, BB_BT);
fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, "\nUsage:\t[function] [arguments]...\n");
fprintf(stderr, "or\nUsage: [function] [arguments]...\n"); fprintf(stderr, "\tbusybox [function] [arguments]...\n");
fprintf(stderr, fprintf(stderr,
"\n\tMost people will create a symlink to busybox for each\n" "\n\tMost people will create a symlink to busybox for each\n"
"\tfunction name, and busybox will act like whatever you invoke it as.\n"); "\tfunction name, and busybox will act like whatever you invoke it as.\n");

View File

@ -30,7 +30,6 @@
//#define BB_LOADKMAP //#define BB_LOADKMAP
////#define BB_LOSETUP ////#define BB_LOSETUP
#define BB_LS #define BB_LS
//#define BB_MAIN
//#define BB_MAKEDEVS //#define BB_MAKEDEVS
////#define BB_MATH ////#define BB_MATH
//#define BB_MKDIR //#define BB_MKDIR
@ -39,9 +38,9 @@
//#define BB_MNC //#define BB_MNC
//#define BB_MONADIC //#define BB_MONADIC
#define BB_MORE #define BB_MORE
//#define BB_MOUNT #define BB_MOUNT
////#define BB_MT ////#define BB_MT
//#define BB_MV #define BB_MV
//#define BB_POSTPROCESS //#define BB_POSTPROCESS
//#define BB_PRINTF //#define BB_PRINTF
//#define BB_PWD //#define BB_PWD
@ -53,10 +52,10 @@
//#define BB_SWAPON //#define BB_SWAPON
//#define BB_SYNC //#define BB_SYNC
#define BB_TAR #define BB_TAR
//#define BB_TOUCH #define BB_TOUCH
#define BB_TRUE #define BB_TRUE
//#define BB_UMOUNT //#define BB_UMOUNT
//#define BB_UPDATE //#define BB_UPDATE
//#define BB_UTILITY #define BB_UTILITY
#define BB_ZCAT #define BB_ZCAT
#define BB_GZIP #define BB_GZIP

View File

@ -3,6 +3,7 @@
#include <mntent.h> #include <mntent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include <fstab.h>
const char df_usage[] = "df [filesystem ...]\n" const char df_usage[] = "df [filesystem ...]\n"
"\n" "\n"
@ -10,7 +11,7 @@ const char df_usage[] = "df [filesystem ...]\n"
static int static int
df(const char * device, const char * mountPoint) df(char* device, const char * mountPoint)
{ {
struct statfs s; struct statfs s;
long blocks_used; long blocks_used;
@ -25,6 +26,8 @@ df(const char * device, const char * mountPoint)
blocks_used = s.f_blocks - s.f_bfree; blocks_used = s.f_blocks - s.f_bfree;
blocks_percent_used = (long) blocks_percent_used = (long)
(blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5); (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
if ( strcmp(device, "/dev/root")==0)
device=(getfsfile ("/"))->fs_spec;
printf( printf(
"%-20s %9ld %9ld %9ld %3ld%% %s\n", "%-20s %9ld %9ld %9ld %3ld%% %s\n",
@ -75,7 +78,7 @@ df_main(int argc, char * * argv)
} }
while ( (mountEntry = getmntent (mountTable))) { while ( (mountEntry = getmntent (mountTable))) {
int status=df(mountEntry->mnt_fsname ,mountEntry->mnt_dir); int status=df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
if (status) if (status)
return status; return status;
} }
@ -129,3 +132,5 @@ findMountPoint(const char* name, const char* table)
endmntent(mountTable); endmntent(mountTable);
return mountEntry; return mountEntry;
} }

View File

@ -1,38 +1,84 @@
/*
* Mini mv implementation for busybox
*
* Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "internal.h" #include "internal.h"
#include <stdio.h> #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utime.h>
#include <errno.h> #include <errno.h>
const char mv_usage[] = "mv source-file destination-file\n" const char mv_usage[] = "source-file [source-file ...] destination-file\n"
"\t\tmv source-file [source-file ...] destination-directory\n" "\n" "\tMove the source files to the destination.\n" "\n";
"\n"
"\tMove the source files to the destination.\n"
"\n";
extern int
mv_fn(const struct FileInfo * i)
extern int mv_main (int argc, char **argv)
{ {
struct stat destination_stat; const char *srcName;
char d[1024]; const char *destName;
struct FileInfo n; const char *lastArg;
BOOL dirFlag;
if ( stat(i->destination, &destination_stat) == 0 ) { if (argc < 3) {
if ( i->stat.st_ino == destination_stat.st_ino fprintf (stderr, "Usage: %s %s", *argv, mv_usage);
&& i->stat.st_dev == destination_stat.st_dev ) return (FALSE);
return 0; /* Move file to itself. */ }
lastArg = argv[argc - 1];
dirFlag = isDirectory (lastArg);
if ((argc > 3) && !dirFlag) {
fprintf (stderr, "%s: not a directory\n", lastArg);
return (FALSE);
}
while (argc-- > 2) {
srcName = *(++argv);
if (access (srcName, 0) < 0) {
perror (srcName);
continue;
} }
if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) {
n = *i; destName = lastArg;
n.destination = join_paths(d, i->destination, basename(i->source));
i = &n; if (dirFlag)
destName = buildName (destName, srcName);
if (rename (srcName, destName) >= 0)
continue;
if (errno != EXDEV) {
perror (destName);
continue;
} }
if ( rename(i->source, i->destination) == 0 )
return 0; if (!copyFile (srcName, destName, TRUE))
else if ( errno == EXDEV && is_a_directory(i->source) ) { continue;
fprintf(stderr
,"%s: Can't move directory across filesystems.\n" if (unlink (srcName) < 0)
,i->source); perror (srcName);
return 1; }
} return (TRUE);
else
return cp_fn(i);
} }

View File

@ -1,20 +1,85 @@
#include "internal.h" /*
#include <sys/types.h> * Mini touch implementation for busybox
#include <stdio.h> *
#include <utime.h> * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
const char touch_usage[] = "touch [-c] file [file ...]\n" #include "internal.h"
"\n" #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utime.h>
#include <errno.h>
const char touch_usage[] = "touch [-c] file [file ...]\n\n"
"\tUpdate the last-modified date on the given file[s].\n"; "\tUpdate the last-modified date on the given file[s].\n";
extern int
touch_fn(const struct FileInfo * i)
extern int
touch_main(int argc, char **argv)
{ {
if ( (utime(i->source, 0) != 0) && (i->create != 1) ) { int fd;
if ( fopen(i->source, "w") == NULL ) { int create=TRUE;
name_and_error(i->source);
return 1; if (argc < 2) {
} fprintf(stderr, "Usage: %s %s", *argv, touch_usage);
exit( FALSE);
}
argc--;
argv++;
/* Parse options */
while (**argv == '-') {
while (*++(*argv)) switch (**argv) {
case 'c':
create = FALSE;
break;
default:
fprintf(stderr, "Unknown option: %c\n", **argv);
exit( FALSE);
} }
return 0; argc--;
argv++;
}
fd = open (*argv, (create==FALSE)? O_RDWR : O_RDWR | O_CREAT, 0644);
if (fd < 0 ) {
if (create==FALSE && errno == ENOENT)
exit( TRUE);
else {
perror("touch");
exit( FALSE);
}
}
close( fd);
if (utime (*argv, NULL)) {
perror("touch");
exit( FALSE);
}
else
exit( TRUE);
} }

9
df.c
View File

@ -3,6 +3,7 @@
#include <mntent.h> #include <mntent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include <fstab.h>
const char df_usage[] = "df [filesystem ...]\n" const char df_usage[] = "df [filesystem ...]\n"
"\n" "\n"
@ -10,7 +11,7 @@ const char df_usage[] = "df [filesystem ...]\n"
static int static int
df(const char * device, const char * mountPoint) df(char* device, const char * mountPoint)
{ {
struct statfs s; struct statfs s;
long blocks_used; long blocks_used;
@ -25,6 +26,8 @@ df(const char * device, const char * mountPoint)
blocks_used = s.f_blocks - s.f_bfree; blocks_used = s.f_blocks - s.f_bfree;
blocks_percent_used = (long) blocks_percent_used = (long)
(blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5); (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
if ( strcmp(device, "/dev/root")==0)
device=(getfsfile ("/"))->fs_spec;
printf( printf(
"%-20s %9ld %9ld %9ld %3ld%% %s\n", "%-20s %9ld %9ld %9ld %3ld%% %s\n",
@ -75,7 +78,7 @@ df_main(int argc, char * * argv)
} }
while ( (mountEntry = getmntent (mountTable))) { while ( (mountEntry = getmntent (mountTable))) {
int status=df(mountEntry->mnt_fsname ,mountEntry->mnt_dir); int status=df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
if (status) if (status)
return status; return status;
} }
@ -129,3 +132,5 @@ findMountPoint(const char* name, const char* table)
endmntent(mountTable); endmntent(mountTable);
return mountEntry; return mountEntry;
} }

View File

@ -23,187 +23,174 @@
const char grep_usage[] = const char grep_usage[] =
"Search the input file(s) for lines matching the given pattern.\n" "Search the input file(s) for lines matching the given pattern.\n"
"\tI search stdin if no files are given.\n" "\tI search stdin if no files are given.\n"
"\tI can't grok full regular expressions.\n" "\tI can't grok full regular expressions.\n"
"usage: grep [in] PATTERN [FILES]...\n" "usage: grep [in] PATTERN [FILES]...\n"
"\ti=ignore case, n=list line numbers\n"; "\ti=ignore case, n=list line numbers\n";
static BOOL search static BOOL search (const char *string, const char *word, BOOL ignoreCase);
(const char * string, const char * word, BOOL ignoreCase);
extern int extern int grep_main (int argc, char **argv)
grep_main(int argc, char ** argv)
{ {
FILE * fp; FILE *fp;
const char * word; const char *word;
const char * name; const char *name;
const char * cp; const char *cp;
BOOL tellName; BOOL tellName;
BOOL ignoreCase; BOOL ignoreCase;
BOOL tellLine; BOOL tellLine;
long line; long line;
char buf[BUF_SIZE]; char buf[BUF_SIZE];
ignoreCase = FALSE; ignoreCase = FALSE;
tellLine = FALSE; tellLine = FALSE;
argc--;
argv++;
if (argc < 1) {
fprintf (stderr, "%s", grep_usage);
return 1;
}
if (**argv == '-') {
argc--; argc--;
argv++; cp = *argv++;
if (argc < 1)
{ while (*++cp)
fprintf(stderr, "%s", grep_usage); switch (*cp) {
case 'i':
ignoreCase = TRUE;
break;
case 'n':
tellLine = TRUE;
break;
default:
fprintf (stderr, "Unknown option\n");
return 1; return 1;
}
}
word = *argv++;
argc--;
tellName = (argc > 1);
while (argc-- > 0) {
name = *argv++;
fp = fopen (name, "r");
if (fp == NULL) {
perror (name);
continue;
} }
if (**argv == '-') line = 0;
{
argc--;
cp = *argv++;
while (*++cp) switch (*cp) while (fgets (buf, sizeof (buf), fp)) {
{ line++;
case 'i':
ignoreCase = TRUE;
break;
case 'n': cp = &buf[strlen (buf) - 1];
tellLine = TRUE;
break;
default: if (*cp != '\n')
fprintf(stderr, "Unknown option\n"); fprintf (stderr, "%s: Line too long\n", name);
return 1;
} if (search (buf, word, ignoreCase)) {
if (tellName)
printf ("%s: ", name);
if (tellLine)
printf ("%ld: ", line);
fputs (buf, stdout);
}
} }
word = *argv++; if (ferror (fp))
argc--; perror (name);
tellName = (argc > 1); fclose (fp);
}
while (argc-- > 0) return 0;
{
name = *argv++;
fp = fopen(name, "r");
if (fp == NULL)
{
perror(name);
continue;
}
line = 0;
while (fgets(buf, sizeof(buf), fp))
{
line++;
cp = &buf[strlen(buf) - 1];
if (*cp != '\n')
fprintf(stderr, "%s: Line too long\n", name);
if (search(buf, word, ignoreCase))
{
if (tellName)
printf("%s: ", name);
if (tellLine)
printf("%ld: ", line);
fputs(buf, stdout);
}
}
if (ferror(fp))
perror(name);
fclose(fp);
}
return 0;
} }
/* /*
* See if the specified word is found in the specified string. * See if the specified word is found in the specified string.
*/ */
static BOOL static BOOL search (const char *string, const char *word, BOOL ignoreCase)
search(const char * string, const char * word, BOOL ignoreCase)
{ {
const char * cp1; const char *cp1;
const char * cp2; const char *cp2;
int len; int len;
int lowFirst; int lowFirst;
int ch1; int ch1;
int ch2; int ch2;
len = strlen(word); len = strlen (word);
if (!ignoreCase) if (!ignoreCase) {
{ while (TRUE) {
while (TRUE) string = strchr (string, word[0]);
{
string = strchr(string, word[0]);
if (string == NULL) if (string == NULL)
return FALSE; return FALSE;
if (memcmp(string, word, len) == 0) if (memcmp (string, word, len) == 0)
return TRUE; return TRUE;
string++; string++;
} }
}
/*
* Here if we need to check case independence.
* Do the search by lower casing both strings.
*/
lowFirst = *word;
if (isupper (lowFirst))
lowFirst = tolower (lowFirst);
while (TRUE) {
while (*string && (*string != lowFirst) &&
(!isupper (*string) || (tolower (*string) != lowFirst))) {
string++;
} }
/* if (*string == '\0')
* Here if we need to check case independence. return FALSE;
* Do the search by lower casing both strings.
*/
lowFirst = *word;
if (isupper(lowFirst)) cp1 = string;
lowFirst = tolower(lowFirst); cp2 = word;
while (TRUE) do {
{ if (*cp2 == '\0')
while (*string && (*string != lowFirst) && return TRUE;
(!isupper(*string) || (tolower(*string) != lowFirst)))
{
string++;
}
if (*string == '\0') ch1 = *cp1++;
return FALSE;
cp1 = string; if (isupper (ch1))
cp2 = word; ch1 = tolower (ch1);
do ch2 = *cp2++;
{
if (*cp2 == '\0')
return TRUE;
ch1 = *cp1++; if (isupper (ch2))
ch2 = tolower (ch2);
if (isupper(ch1))
ch1 = tolower(ch1);
ch2 = *cp2++;
if (isupper(ch2))
ch2 = tolower(ch2);
}
while (ch1 == ch2);
string++;
} }
while (ch1 == ch2);
string++;
}
return (TRUE);
} }
#endif #endif

269
grep.c
View File

@ -23,187 +23,174 @@
const char grep_usage[] = const char grep_usage[] =
"Search the input file(s) for lines matching the given pattern.\n" "Search the input file(s) for lines matching the given pattern.\n"
"\tI search stdin if no files are given.\n" "\tI search stdin if no files are given.\n"
"\tI can't grok full regular expressions.\n" "\tI can't grok full regular expressions.\n"
"usage: grep [in] PATTERN [FILES]...\n" "usage: grep [in] PATTERN [FILES]...\n"
"\ti=ignore case, n=list line numbers\n"; "\ti=ignore case, n=list line numbers\n";
static BOOL search static BOOL search (const char *string, const char *word, BOOL ignoreCase);
(const char * string, const char * word, BOOL ignoreCase);
extern int extern int grep_main (int argc, char **argv)
grep_main(int argc, char ** argv)
{ {
FILE * fp; FILE *fp;
const char * word; const char *word;
const char * name; const char *name;
const char * cp; const char *cp;
BOOL tellName; BOOL tellName;
BOOL ignoreCase; BOOL ignoreCase;
BOOL tellLine; BOOL tellLine;
long line; long line;
char buf[BUF_SIZE]; char buf[BUF_SIZE];
ignoreCase = FALSE; ignoreCase = FALSE;
tellLine = FALSE; tellLine = FALSE;
argc--;
argv++;
if (argc < 1) {
fprintf (stderr, "%s", grep_usage);
return 1;
}
if (**argv == '-') {
argc--; argc--;
argv++; cp = *argv++;
if (argc < 1)
{ while (*++cp)
fprintf(stderr, "%s", grep_usage); switch (*cp) {
case 'i':
ignoreCase = TRUE;
break;
case 'n':
tellLine = TRUE;
break;
default:
fprintf (stderr, "Unknown option\n");
return 1; return 1;
}
}
word = *argv++;
argc--;
tellName = (argc > 1);
while (argc-- > 0) {
name = *argv++;
fp = fopen (name, "r");
if (fp == NULL) {
perror (name);
continue;
} }
if (**argv == '-') line = 0;
{
argc--;
cp = *argv++;
while (*++cp) switch (*cp) while (fgets (buf, sizeof (buf), fp)) {
{ line++;
case 'i':
ignoreCase = TRUE;
break;
case 'n': cp = &buf[strlen (buf) - 1];
tellLine = TRUE;
break;
default: if (*cp != '\n')
fprintf(stderr, "Unknown option\n"); fprintf (stderr, "%s: Line too long\n", name);
return 1;
} if (search (buf, word, ignoreCase)) {
if (tellName)
printf ("%s: ", name);
if (tellLine)
printf ("%ld: ", line);
fputs (buf, stdout);
}
} }
word = *argv++; if (ferror (fp))
argc--; perror (name);
tellName = (argc > 1); fclose (fp);
}
while (argc-- > 0) return 0;
{
name = *argv++;
fp = fopen(name, "r");
if (fp == NULL)
{
perror(name);
continue;
}
line = 0;
while (fgets(buf, sizeof(buf), fp))
{
line++;
cp = &buf[strlen(buf) - 1];
if (*cp != '\n')
fprintf(stderr, "%s: Line too long\n", name);
if (search(buf, word, ignoreCase))
{
if (tellName)
printf("%s: ", name);
if (tellLine)
printf("%ld: ", line);
fputs(buf, stdout);
}
}
if (ferror(fp))
perror(name);
fclose(fp);
}
return 0;
} }
/* /*
* See if the specified word is found in the specified string. * See if the specified word is found in the specified string.
*/ */
static BOOL static BOOL search (const char *string, const char *word, BOOL ignoreCase)
search(const char * string, const char * word, BOOL ignoreCase)
{ {
const char * cp1; const char *cp1;
const char * cp2; const char *cp2;
int len; int len;
int lowFirst; int lowFirst;
int ch1; int ch1;
int ch2; int ch2;
len = strlen(word); len = strlen (word);
if (!ignoreCase) if (!ignoreCase) {
{ while (TRUE) {
while (TRUE) string = strchr (string, word[0]);
{
string = strchr(string, word[0]);
if (string == NULL) if (string == NULL)
return FALSE; return FALSE;
if (memcmp(string, word, len) == 0) if (memcmp (string, word, len) == 0)
return TRUE; return TRUE;
string++; string++;
} }
}
/*
* Here if we need to check case independence.
* Do the search by lower casing both strings.
*/
lowFirst = *word;
if (isupper (lowFirst))
lowFirst = tolower (lowFirst);
while (TRUE) {
while (*string && (*string != lowFirst) &&
(!isupper (*string) || (tolower (*string) != lowFirst))) {
string++;
} }
/* if (*string == '\0')
* Here if we need to check case independence. return FALSE;
* Do the search by lower casing both strings.
*/
lowFirst = *word;
if (isupper(lowFirst)) cp1 = string;
lowFirst = tolower(lowFirst); cp2 = word;
while (TRUE) do {
{ if (*cp2 == '\0')
while (*string && (*string != lowFirst) && return TRUE;
(!isupper(*string) || (tolower(*string) != lowFirst)))
{
string++;
}
if (*string == '\0') ch1 = *cp1++;
return FALSE;
cp1 = string; if (isupper (ch1))
cp2 = word; ch1 = tolower (ch1);
do ch2 = *cp2++;
{
if (*cp2 == '\0')
return TRUE;
ch1 = *cp1++; if (isupper (ch2))
ch2 = tolower (ch2);
if (isupper(ch1))
ch1 = tolower(ch1);
ch2 = *cp2++;
if (isupper(ch2))
ch2 = tolower(ch2);
}
while (ch1 == ch2);
string++;
} }
while (ch1 == ch2);
string++;
}
return (TRUE);
} }
#endif #endif

View File

@ -127,6 +127,7 @@ extern int mnc_main(int argc, char** argv);
extern int monadic_main(int argc, char** argv); extern int monadic_main(int argc, char** argv);
extern int mount_main(int argc, char** argv); extern int mount_main(int argc, char** argv);
extern int mt_main(int argc, char** argv); extern int mt_main(int argc, char** argv);
extern int mv_main(int argc, char** argv);
extern int printf_main(int argc, char** argv); extern int printf_main(int argc, char** argv);
extern int pwd_main(int argc, char** argv); extern int pwd_main(int argc, char** argv);
extern int reboot_main(int argc, char** argv); extern int reboot_main(int argc, char** argv);
@ -135,6 +136,7 @@ extern int scan_partitions_main(int argc, char** argv);
extern int sh_main(int argc, char** argv); extern int sh_main(int argc, char** argv);
extern int sleep_main(int argc, char** argv); extern int sleep_main(int argc, char** argv);
extern int tar_main(int argc, char** argv); extern int tar_main(int argc, char** argv);
extern int touch_main(int argc, char** argv);
extern int sync_main(int argc, char** argv); extern int sync_main(int argc, char** argv);
extern int tput_main(int argc, char** argv); extern int tput_main(int argc, char** argv);
extern int true_main(int argc, char** argv); extern int true_main(int argc, char** argv);

600
mount.c
View File

@ -1,9 +1,29 @@
/* /*
3/21/1999 Charles P. Wright <cpwright@cpwright.com> * Mini mount implementation for busybox
searches through fstab when -a is passed *
will try mounting stuff with all fses when passed -t auto * Copyright (C) 1999 by Erik Andersen <andersee@debian.org>
*
1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab. * 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 3/21/1999 Charles P. Wright <cpwright@cpwright.com>
* searches through fstab when -a is passed
* will try mounting stuff with all fses when passed -t auto
*
* 1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab.
* 1999-10-07 Erik Andersen. Removed mtab usage, major adjustments,
* and some serious dieting all around.
*/ */
#include "internal.h" #include "internal.h"
@ -15,416 +35,238 @@
#include <mntent.h> #include <mntent.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <ctype.h> #include <ctype.h>
#include <fstab.h>
const char mount_usage[] = "mount\n" const char mount_usage[] = "Usage:\tmount [flags]\n"
"\t\tmount [flags] special-device directory\n" "\tmount [flags] device directory [-o options,more-options]\n"
"\n" "\n"
"Flags:\n" "Flags:\n"
"\t-a:\tMount all file systems in fstab.\n" "\t-a:\tMount all file systems in fstab.\n"
"\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n" "\t-o option:\tOne of many filesystem options, listed below.\n"
"\t-n:\tDon't write a mount table entry.\n" "\t-r:\tMount the filesystem read-only.\n"
"\t-o option:\tOne of many filesystem options, listed below.\n" "\t-t filesystem-type:\tSpecify the filesystem type.\n"
"\t-r:\tMount the filesystem read-only.\n" "\t-w:\tMount for reading and writing (default).\n"
"\t-t filesystem-type:\tSpecify the filesystem type.\n" "\n"
"\t-w:\tMount for reading and writing (default).\n" "Options for use with the \"-o\" flag:\n"
"\n" "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
"Options for use with the \"-o\" flag:\n" "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
"\tasync / sync:\tWrites are asynchronous / synchronous.\n" "\texec / noexec:\tAllow use of executable files / disallow them.\n"
"\tdev / nodev:\tAllow use of special device files / disallow them.\n" "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
"\texec / noexec:\tAllow use of executable files / disallow them.\n" "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
"\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" "\tro / rw: Mount for read-only / read-write.\n"
"\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" "\t"
"\tro / rw: Mount for read-only / read-write.\n" "There are EVEN MORE flags that are specific to each filesystem.\n"
"\t" "You'll have to see the written documentation for those.\n";
"There are EVEN MORE flags that are specific to each filesystem.\n"
"You'll have to see the written documentation for those.\n";
struct mount_options { struct mount_options {
const char * name; const char *name;
unsigned long and; unsigned long and;
unsigned long or; unsigned long or;
}; };
static const struct mount_options mount_options[] = { static const struct mount_options mount_options[] = {
{ "async", ~MS_SYNCHRONOUS,0 }, {"async", ~MS_SYNCHRONOUS, 0},
{ "defaults", ~0, 0 }, {"defaults", ~0, 0},
{ "dev", ~MS_NODEV, 0 }, {"dev", ~MS_NODEV, 0},
{ "exec", ~MS_NOEXEC, 0 }, {"exec", ~MS_NOEXEC, 0},
{ "nodev", ~0, MS_NODEV }, {"nodev", ~0, MS_NODEV},
{ "noexec", ~0, MS_NOEXEC }, {"noexec", ~0, MS_NOEXEC},
{ "nosuid", ~0, MS_NOSUID }, {"nosuid", ~0, MS_NOSUID},
{ "remount", ~0, MS_REMOUNT }, {"remount", ~0, MS_REMOUNT},
{ "ro", ~0, MS_RDONLY }, {"ro", ~0, MS_RDONLY},
{ "rw", ~MS_RDONLY, 0 }, {"rw", ~MS_RDONLY, 0},
{ "suid", ~MS_NOSUID, 0 }, {"suid", ~MS_NOSUID, 0},
{ "sync", ~0, MS_SYNCHRONOUS }, {"sync", ~0, MS_SYNCHRONOUS},
{ 0, 0, 0 } {0, 0, 0}
}; };
static void
show_flags(unsigned long flags, char * buffer)
{
const struct mount_options * f = mount_options;
while ( f->name ) {
if ( flags & f->and ) {
int length = strlen(f->name);
memcpy(buffer, f->name, length);
buffer += length;
*buffer++ = ',';
*buffer = '\0';
}
f++;
}
}
static void static void
one_option( parse_mount_options ( char *options, unsigned long *flags, char *data)
char * option
,unsigned long * flags
,char * data)
{ {
const struct mount_options * f = mount_options; printf("option=%s\n", options);
while (*options) {
char *comma = strchr (options, ',');
const struct mount_options* f = mount_options;
if (comma)
*comma = '\0';
while ( f->name != 0 ) { printf("checking option=%s vs %s\n", options, f->name);
if ( strcasecmp(f->name, option) == 0 ) { while (f->name != 0) {
*flags &= f->and; printf("checking option=%s vs %s\n", options, f->name);
*flags |= f->or; if (strcasecmp (f->name, options) == 0) {
return; *flags &= f->and;
} *flags |= f->or;
f++; return;
}
f++;
} }
if ( *data ) { if (*data) {
data += strlen(data); data += strlen (data);
*data++ = ','; *data++ = ',';
}
strcpy(data, option);
}
static void
parse_mount_options(
char * options
,unsigned long * flags
,char * data)
{
while ( *options ) {
char * comma = strchr(options, ',');
if ( comma )
*comma = '\0';
one_option(options, flags, data);
if ( comma ) {
*comma = ',';
options = ++comma;
}
else
break;
} }
strcpy (data, options);
if (comma) {
*comma = ',';
options = ++comma;
} else
break;
}
} }
int int
mount_one( mount_one (
char * blockDevice char *blockDevice, char *directory, char *filesystemType,
,char * directory unsigned long flags, char *string_flags)
,char * filesystemType
,unsigned long flags
,char * string_flags
,int noMtab
,int fake)
{ {
int error = 0; int status = 0;
int status = 0;
char buf[255]; char buf[255];
if (!fake) {
if (*filesystemType == 'a') { //Will fail on real FS starting with 'a'
FILE *f = fopen("/proc/filesystems", "r"); if (strcmp(filesystemType, "auto") == 0) {
FILE *f = fopen ("/proc/filesystems", "r");
if (f == NULL) return 1; if (f == NULL)
return( FALSE);
while (fgets(buf, sizeof(buf), f) != NULL) { while (fgets (buf, sizeof (buf), f) != NULL) {
filesystemType = buf; filesystemType = buf;
if (*filesystemType == '\t') { // Not a nodev filesystem if (*filesystemType == '\t') { // Not a nodev filesystem
while (*filesystemType && *filesystemType != '\n') filesystemType++;
*filesystemType = '\0';
filesystemType = buf;
filesystemType++; //hop past tab
status = mount(blockDevice, directory, filesystemType,
flags|MS_MGC_VAL ,string_flags);
error = errno;
if (status == 0) break; // Add NULL termination to each line
} while (*filesystemType && *filesystemType != '\n')
} filesystemType++;
fclose(f); *filesystemType = '\0';
} else {
status = mount( blockDevice, directory, filesystemType, filesystemType = buf;
flags|MS_MGC_VAL ,string_flags); filesystemType++; // hop past tab
error = errno;
} status = mount (blockDevice, directory, filesystemType,
flags | MS_MGC_VAL, string_flags);
if (status == 0)
break;
}
} }
fclose (f);
} else {
status = mount (blockDevice, directory, filesystemType,
flags | MS_MGC_VAL, string_flags);
}
if ( status == 0 ) { if (status) {
char * s = &string_flags[strlen(string_flags)]; fprintf (stderr, "Mounting %s on %s failed: %s\n",
FILE * mountTable; blockDevice, directory, strerror(errno));
if ( s != string_flags ) { return (FALSE);
*s++ = ','; }
show_flags(flags, s); return (TRUE);
}
if ( !noMtab && (mountTable = setmntent("/etc/mtab", "a+")) ) {
int length = strlen(directory);
struct mntent m;
if ( length > 1 && directory[length - 1] == '/' )
directory[length - 1] = '\0';
if ( filesystemType == 0 ) {
struct mntent * p
= findMountPoint(blockDevice, "/proc/mounts");
if ( p && p->mnt_type )
filesystemType = p->mnt_type;
}
m.mnt_fsname = blockDevice;
m.mnt_dir = directory;
m.mnt_type = filesystemType ? filesystemType : "default";
if (*string_flags) {
m.mnt_opts = string_flags;
} else {
if ( (flags | MS_RDONLY) == flags )
m.mnt_opts = "ro";
else
m.mnt_opts = "rw";
}
m.mnt_freq = 0;
m.mnt_passno = 0;
addmntent(mountTable, &m);
endmntent(mountTable);
}
return 0;
} else {
fprintf(stderr, "Mount %s", blockDevice);
if ( filesystemType && *filesystemType )
fprintf(stderr, " (type %s)", filesystemType);
fprintf(
stderr
," on %s: "
,directory);
switch ( error ) {
case EPERM:
if (geteuid() == 0)
fprintf(
stderr
,"mount point %s is not a directory"
,blockDevice);
else
fprintf(
stderr
,"must be superuser to use mount");
break;
case EBUSY:
fprintf(
stderr
,"%s already mounted or %s busy"
,blockDevice
,directory);
break;
case ENOENT:
{
struct stat statbuf;
if ( stat(directory, &statbuf) != 0 )
fprintf(
stderr
,"directory %s does not exist"
,directory);
else if ( stat(blockDevice, &statbuf) != 0 )
fprintf(
stderr
,"block device %s does not exist"
,blockDevice);
else
fprintf(
stderr
,"%s is not mounted on %s, but the mount table says it is."
,blockDevice
,directory);
break;
}
case ENOTDIR:
fprintf(
stderr
,"%s is not a directory"
,directory);
break;
case EINVAL:
fprintf(
stderr
,"wrong filesystem type, or bad superblock on %s"
,blockDevice);
break;
case EMFILE:
fprintf(stderr, "mount table full");
break;
case EIO:
fprintf(
stderr
,"I/O error reading %s"
,blockDevice);
break;
case ENODEV:
{
FILE * f = fopen("/proc/filesystems", "r");
fprintf(
stderr
,"filesystem type %s not in kernel.\n"
,filesystemType);
fprintf(stderr, "Do you need to load a module?\n");
if ( f ) {
char buf[100];
fprintf(
stderr
,"Here are the filesystem types the kernel"
" can mount:\n");
while ( fgets(buf, sizeof(buf), f) != 0 )
fprintf(stderr, "\t%s", buf);
fclose(f);
}
break;
}
case ENOTBLK:
fprintf(
stderr
,"%s is not a block device"
,blockDevice);
break;
case ENXIO:
fprintf(
stderr
,"%s is not a valid block device"
,blockDevice);
break;
default:
fputs(strerror(errno), stderr);
}
putc('\n', stderr);
return -1;
}
} }
extern int extern int mount_main (int argc, char **argv)
mount_main(struct FileInfo * i, int argc, char * * argv)
{ {
char string_flags[1024]; char string_flags[1024]="\0";
unsigned long flags = 0; unsigned long flags = 0;
char * filesystemType = "auto"; char *filesystemType = "auto";
int fake = 0; int all = 0;
int noMtab = 0; int i = argc;
int all = 0;
*string_flags = '\0';
if ( argc == 1 ) { if (argc == 1) {
FILE * mountTable; FILE *mountTable;
if ( (mountTable = setmntent("/etc/mtab", "r")) ) { if ((mountTable = setmntent ("/proc/mounts", "r"))) {
struct mntent * m; struct mntent *m;
while ( (m = getmntent(mountTable)) != 0 ) { while ((m = getmntent (mountTable)) != 0) {
printf( char *blockDevice = m->mnt_fsname;
"%s on %s type %s (%s)\n" if (strcmp (blockDevice, "/dev/root") == 0)
,m->mnt_fsname blockDevice = (getfsfile ("/"))->fs_spec;
,m->mnt_dir printf ("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
,m->mnt_type m->mnt_type, m->mnt_opts);
,m->mnt_opts); }
} endmntent (mountTable);
endmntent(mountTable);
}
return 0;
} }
return( TRUE);
}
while ( argc >= 2 && argv[1][0] == '-' ) {
switch ( argv[1][1] ) { /* Parse options */
case 'f': while (**argv) {
fake = 1; if (**argv == '-') {
break; switch (**argv) {
case 'n': case 'o':
noMtab = 1; if (++argv == 0) {
break; fprintf (stderr, "%s\n", mount_usage);
case 'o': return( FALSE);
if ( argc < 3 ) {
usage(mount_usage);
return 1;
}
parse_mount_options(argv[2], &flags, string_flags);
argc--;
argv++;
break;
case 'r':
flags |= MS_RDONLY;
break;
case 't':
if ( argc < 3 ) {
usage(mount_usage);
return 1;
}
filesystemType = argv[2];
argc--;
argv++;
break;
case 'v':
break;
case 'w':
flags &= ~MS_RDONLY;
break;
case 'a':
all = 1;
break;
default:
usage(mount_usage);
return 1;
} }
parse_mount_options (*argv, &flags, string_flags);
argc--; argc--;
argv++; argv++;
break;
case 'r':
flags |= MS_RDONLY;
break;
case 't':
if (++argv == 0) {
fprintf (stderr, "%s\n", mount_usage);
return( FALSE);
}
filesystemType = *argv;
argc--;
argv++;
break;
case 'w':
flags &= ~MS_RDONLY;
break;
case 'a':
all = 1;
break;
case 'v':
case 'h':
case '-':
fprintf (stderr, "%s\n", mount_usage);
return( TRUE);
}
}
i--;
argv++;
}
if (all == 1) {
struct mntent *m;
FILE *f = setmntent ("/etc/fstab", "r");
if (f == NULL) {
perror("/etc/fstab");
return( FALSE);
}
// FIXME: Combine read routine (make new function) with unmount_all
// to save space.
while ((m = getmntent (f)) != NULL) {
// If the file system isn't noauto, and isn't mounted on /, mount
// it
if ((!strstr (m->mnt_opts, "noauto"))
&& (m->mnt_dir[1] != '\0') && !((m->mnt_type[0] == 's')
&& (m->mnt_type[1] == 'w'))
&& !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) {
mount_one (m->mnt_fsname, m->mnt_dir, m->mnt_type, flags,
m->mnt_opts);
}
} }
if (all == 1) { endmntent (f);
struct mntent *m; } else {
FILE *f = setmntent("/etc/fstab", "r"); if (argc >= 3) {
while (i < argc)
if (f == NULL) { argv--;
return 1; while (**argv == '-')
} argv++;
if (mount_one
// FIXME: Combine read routine (make new function) with unmount_all to save space. (*argv, *(argv+1), filesystemType, flags,
string_flags) == 0) return 0;
while ((m = getmntent(f)) != NULL) { else
// If the file system isn't noauto, and isn't mounted on /, mount it return( FALSE);
if ((!strstr(m->mnt_opts, "noauto")) && (m->mnt_dir[1] != '\0')
&& !((m->mnt_type[0] == 's') && (m->mnt_type[1] == 'w'))
&& !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) {
mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, flags, m->mnt_opts, noMtab, fake);
}
}
endmntent(f);
} else { } else {
if ( argc >= 3 ) { fprintf (stderr, "%s\n", mount_usage);
if ( mount_one( argv[1], argv[2], filesystemType, flags, string_flags, noMtab, fake) == 0 ) return( FALSE);
return 0;
else
return 1;
} else {
usage(mount_usage);
return 1;
}
} }
return 0; }
return( TRUE);
} }

102
mv.c
View File

@ -1,38 +1,84 @@
/*
* Mini mv implementation for busybox
*
* Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "internal.h" #include "internal.h"
#include <stdio.h> #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utime.h>
#include <errno.h> #include <errno.h>
const char mv_usage[] = "mv source-file destination-file\n" const char mv_usage[] = "source-file [source-file ...] destination-file\n"
"\t\tmv source-file [source-file ...] destination-directory\n" "\n" "\tMove the source files to the destination.\n" "\n";
"\n"
"\tMove the source files to the destination.\n"
"\n";
extern int
mv_fn(const struct FileInfo * i)
extern int mv_main (int argc, char **argv)
{ {
struct stat destination_stat; const char *srcName;
char d[1024]; const char *destName;
struct FileInfo n; const char *lastArg;
BOOL dirFlag;
if ( stat(i->destination, &destination_stat) == 0 ) { if (argc < 3) {
if ( i->stat.st_ino == destination_stat.st_ino fprintf (stderr, "Usage: %s %s", *argv, mv_usage);
&& i->stat.st_dev == destination_stat.st_dev ) return (FALSE);
return 0; /* Move file to itself. */ }
lastArg = argv[argc - 1];
dirFlag = isDirectory (lastArg);
if ((argc > 3) && !dirFlag) {
fprintf (stderr, "%s: not a directory\n", lastArg);
return (FALSE);
}
while (argc-- > 2) {
srcName = *(++argv);
if (access (srcName, 0) < 0) {
perror (srcName);
continue;
} }
if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) {
n = *i; destName = lastArg;
n.destination = join_paths(d, i->destination, basename(i->source));
i = &n; if (dirFlag)
destName = buildName (destName, srcName);
if (rename (srcName, destName) >= 0)
continue;
if (errno != EXDEV) {
perror (destName);
continue;
} }
if ( rename(i->source, i->destination) == 0 )
return 0; if (!copyFile (srcName, destName, TRUE))
else if ( errno == EXDEV && is_a_directory(i->source) ) { continue;
fprintf(stderr
,"%s: Can't move directory across filesystems.\n" if (unlink (srcName) < 0)
,i->source); perror (srcName);
return 1; }
} return (TRUE);
else
return cp_fn(i);
} }

93
touch.c
View File

@ -1,20 +1,85 @@
#include "internal.h" /*
#include <sys/types.h> * Mini touch implementation for busybox
#include <stdio.h> *
#include <utime.h> * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
const char touch_usage[] = "touch [-c] file [file ...]\n" #include "internal.h"
"\n" #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utime.h>
#include <errno.h>
const char touch_usage[] = "touch [-c] file [file ...]\n\n"
"\tUpdate the last-modified date on the given file[s].\n"; "\tUpdate the last-modified date on the given file[s].\n";
extern int
touch_fn(const struct FileInfo * i)
extern int
touch_main(int argc, char **argv)
{ {
if ( (utime(i->source, 0) != 0) && (i->create != 1) ) { int fd;
if ( fopen(i->source, "w") == NULL ) { int create=TRUE;
name_and_error(i->source);
return 1; if (argc < 2) {
} fprintf(stderr, "Usage: %s %s", *argv, touch_usage);
exit( FALSE);
}
argc--;
argv++;
/* Parse options */
while (**argv == '-') {
while (*++(*argv)) switch (**argv) {
case 'c':
create = FALSE;
break;
default:
fprintf(stderr, "Unknown option: %c\n", **argv);
exit( FALSE);
} }
return 0; argc--;
argv++;
}
fd = open (*argv, (create==FALSE)? O_RDWR : O_RDWR | O_CREAT, 0644);
if (fd < 0 ) {
if (create==FALSE && errno == ENOENT)
exit( TRUE);
else {
perror("touch");
exit( FALSE);
}
}
close( fd);
if (utime (*argv, NULL)) {
perror("touch");
exit( FALSE);
}
else
exit( TRUE);
} }

View File

@ -1,9 +1,29 @@
/* /*
3/21/1999 Charles P. Wright <cpwright@cpwright.com> * Mini mount implementation for busybox
searches through fstab when -a is passed *
will try mounting stuff with all fses when passed -t auto * Copyright (C) 1999 by Erik Andersen <andersee@debian.org>
*
1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab. * 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 3/21/1999 Charles P. Wright <cpwright@cpwright.com>
* searches through fstab when -a is passed
* will try mounting stuff with all fses when passed -t auto
*
* 1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab.
* 1999-10-07 Erik Andersen. Removed mtab usage, major adjustments,
* and some serious dieting all around.
*/ */
#include "internal.h" #include "internal.h"
@ -15,416 +35,238 @@
#include <mntent.h> #include <mntent.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <ctype.h> #include <ctype.h>
#include <fstab.h>
const char mount_usage[] = "mount\n" const char mount_usage[] = "Usage:\tmount [flags]\n"
"\t\tmount [flags] special-device directory\n" "\tmount [flags] device directory [-o options,more-options]\n"
"\n" "\n"
"Flags:\n" "Flags:\n"
"\t-a:\tMount all file systems in fstab.\n" "\t-a:\tMount all file systems in fstab.\n"
"\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n" "\t-o option:\tOne of many filesystem options, listed below.\n"
"\t-n:\tDon't write a mount table entry.\n" "\t-r:\tMount the filesystem read-only.\n"
"\t-o option:\tOne of many filesystem options, listed below.\n" "\t-t filesystem-type:\tSpecify the filesystem type.\n"
"\t-r:\tMount the filesystem read-only.\n" "\t-w:\tMount for reading and writing (default).\n"
"\t-t filesystem-type:\tSpecify the filesystem type.\n" "\n"
"\t-w:\tMount for reading and writing (default).\n" "Options for use with the \"-o\" flag:\n"
"\n" "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
"Options for use with the \"-o\" flag:\n" "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
"\tasync / sync:\tWrites are asynchronous / synchronous.\n" "\texec / noexec:\tAllow use of executable files / disallow them.\n"
"\tdev / nodev:\tAllow use of special device files / disallow them.\n" "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
"\texec / noexec:\tAllow use of executable files / disallow them.\n" "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
"\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" "\tro / rw: Mount for read-only / read-write.\n"
"\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" "\t"
"\tro / rw: Mount for read-only / read-write.\n" "There are EVEN MORE flags that are specific to each filesystem.\n"
"\t" "You'll have to see the written documentation for those.\n";
"There are EVEN MORE flags that are specific to each filesystem.\n"
"You'll have to see the written documentation for those.\n";
struct mount_options { struct mount_options {
const char * name; const char *name;
unsigned long and; unsigned long and;
unsigned long or; unsigned long or;
}; };
static const struct mount_options mount_options[] = { static const struct mount_options mount_options[] = {
{ "async", ~MS_SYNCHRONOUS,0 }, {"async", ~MS_SYNCHRONOUS, 0},
{ "defaults", ~0, 0 }, {"defaults", ~0, 0},
{ "dev", ~MS_NODEV, 0 }, {"dev", ~MS_NODEV, 0},
{ "exec", ~MS_NOEXEC, 0 }, {"exec", ~MS_NOEXEC, 0},
{ "nodev", ~0, MS_NODEV }, {"nodev", ~0, MS_NODEV},
{ "noexec", ~0, MS_NOEXEC }, {"noexec", ~0, MS_NOEXEC},
{ "nosuid", ~0, MS_NOSUID }, {"nosuid", ~0, MS_NOSUID},
{ "remount", ~0, MS_REMOUNT }, {"remount", ~0, MS_REMOUNT},
{ "ro", ~0, MS_RDONLY }, {"ro", ~0, MS_RDONLY},
{ "rw", ~MS_RDONLY, 0 }, {"rw", ~MS_RDONLY, 0},
{ "suid", ~MS_NOSUID, 0 }, {"suid", ~MS_NOSUID, 0},
{ "sync", ~0, MS_SYNCHRONOUS }, {"sync", ~0, MS_SYNCHRONOUS},
{ 0, 0, 0 } {0, 0, 0}
}; };
static void
show_flags(unsigned long flags, char * buffer)
{
const struct mount_options * f = mount_options;
while ( f->name ) {
if ( flags & f->and ) {
int length = strlen(f->name);
memcpy(buffer, f->name, length);
buffer += length;
*buffer++ = ',';
*buffer = '\0';
}
f++;
}
}
static void static void
one_option( parse_mount_options ( char *options, unsigned long *flags, char *data)
char * option
,unsigned long * flags
,char * data)
{ {
const struct mount_options * f = mount_options; printf("option=%s\n", options);
while (*options) {
char *comma = strchr (options, ',');
const struct mount_options* f = mount_options;
if (comma)
*comma = '\0';
while ( f->name != 0 ) { printf("checking option=%s vs %s\n", options, f->name);
if ( strcasecmp(f->name, option) == 0 ) { while (f->name != 0) {
*flags &= f->and; printf("checking option=%s vs %s\n", options, f->name);
*flags |= f->or; if (strcasecmp (f->name, options) == 0) {
return; *flags &= f->and;
} *flags |= f->or;
f++; return;
}
f++;
} }
if ( *data ) { if (*data) {
data += strlen(data); data += strlen (data);
*data++ = ','; *data++ = ',';
}
strcpy(data, option);
}
static void
parse_mount_options(
char * options
,unsigned long * flags
,char * data)
{
while ( *options ) {
char * comma = strchr(options, ',');
if ( comma )
*comma = '\0';
one_option(options, flags, data);
if ( comma ) {
*comma = ',';
options = ++comma;
}
else
break;
} }
strcpy (data, options);
if (comma) {
*comma = ',';
options = ++comma;
} else
break;
}
} }
int int
mount_one( mount_one (
char * blockDevice char *blockDevice, char *directory, char *filesystemType,
,char * directory unsigned long flags, char *string_flags)
,char * filesystemType
,unsigned long flags
,char * string_flags
,int noMtab
,int fake)
{ {
int error = 0; int status = 0;
int status = 0;
char buf[255]; char buf[255];
if (!fake) {
if (*filesystemType == 'a') { //Will fail on real FS starting with 'a'
FILE *f = fopen("/proc/filesystems", "r"); if (strcmp(filesystemType, "auto") == 0) {
FILE *f = fopen ("/proc/filesystems", "r");
if (f == NULL) return 1; if (f == NULL)
return( FALSE);
while (fgets(buf, sizeof(buf), f) != NULL) { while (fgets (buf, sizeof (buf), f) != NULL) {
filesystemType = buf; filesystemType = buf;
if (*filesystemType == '\t') { // Not a nodev filesystem if (*filesystemType == '\t') { // Not a nodev filesystem
while (*filesystemType && *filesystemType != '\n') filesystemType++;
*filesystemType = '\0';
filesystemType = buf;
filesystemType++; //hop past tab
status = mount(blockDevice, directory, filesystemType,
flags|MS_MGC_VAL ,string_flags);
error = errno;
if (status == 0) break; // Add NULL termination to each line
} while (*filesystemType && *filesystemType != '\n')
} filesystemType++;
fclose(f); *filesystemType = '\0';
} else {
status = mount( blockDevice, directory, filesystemType, filesystemType = buf;
flags|MS_MGC_VAL ,string_flags); filesystemType++; // hop past tab
error = errno;
} status = mount (blockDevice, directory, filesystemType,
flags | MS_MGC_VAL, string_flags);
if (status == 0)
break;
}
} }
fclose (f);
} else {
status = mount (blockDevice, directory, filesystemType,
flags | MS_MGC_VAL, string_flags);
}
if ( status == 0 ) { if (status) {
char * s = &string_flags[strlen(string_flags)]; fprintf (stderr, "Mounting %s on %s failed: %s\n",
FILE * mountTable; blockDevice, directory, strerror(errno));
if ( s != string_flags ) { return (FALSE);
*s++ = ','; }
show_flags(flags, s); return (TRUE);
}
if ( !noMtab && (mountTable = setmntent("/etc/mtab", "a+")) ) {
int length = strlen(directory);
struct mntent m;
if ( length > 1 && directory[length - 1] == '/' )
directory[length - 1] = '\0';
if ( filesystemType == 0 ) {
struct mntent * p
= findMountPoint(blockDevice, "/proc/mounts");
if ( p && p->mnt_type )
filesystemType = p->mnt_type;
}
m.mnt_fsname = blockDevice;
m.mnt_dir = directory;
m.mnt_type = filesystemType ? filesystemType : "default";
if (*string_flags) {
m.mnt_opts = string_flags;
} else {
if ( (flags | MS_RDONLY) == flags )
m.mnt_opts = "ro";
else
m.mnt_opts = "rw";
}
m.mnt_freq = 0;
m.mnt_passno = 0;
addmntent(mountTable, &m);
endmntent(mountTable);
}
return 0;
} else {
fprintf(stderr, "Mount %s", blockDevice);
if ( filesystemType && *filesystemType )
fprintf(stderr, " (type %s)", filesystemType);
fprintf(
stderr
," on %s: "
,directory);
switch ( error ) {
case EPERM:
if (geteuid() == 0)
fprintf(
stderr
,"mount point %s is not a directory"
,blockDevice);
else
fprintf(
stderr
,"must be superuser to use mount");
break;
case EBUSY:
fprintf(
stderr
,"%s already mounted or %s busy"
,blockDevice
,directory);
break;
case ENOENT:
{
struct stat statbuf;
if ( stat(directory, &statbuf) != 0 )
fprintf(
stderr
,"directory %s does not exist"
,directory);
else if ( stat(blockDevice, &statbuf) != 0 )
fprintf(
stderr
,"block device %s does not exist"
,blockDevice);
else
fprintf(
stderr
,"%s is not mounted on %s, but the mount table says it is."
,blockDevice
,directory);
break;
}
case ENOTDIR:
fprintf(
stderr
,"%s is not a directory"
,directory);
break;
case EINVAL:
fprintf(
stderr
,"wrong filesystem type, or bad superblock on %s"
,blockDevice);
break;
case EMFILE:
fprintf(stderr, "mount table full");
break;
case EIO:
fprintf(
stderr
,"I/O error reading %s"
,blockDevice);
break;
case ENODEV:
{
FILE * f = fopen("/proc/filesystems", "r");
fprintf(
stderr
,"filesystem type %s not in kernel.\n"
,filesystemType);
fprintf(stderr, "Do you need to load a module?\n");
if ( f ) {
char buf[100];
fprintf(
stderr
,"Here are the filesystem types the kernel"
" can mount:\n");
while ( fgets(buf, sizeof(buf), f) != 0 )
fprintf(stderr, "\t%s", buf);
fclose(f);
}
break;
}
case ENOTBLK:
fprintf(
stderr
,"%s is not a block device"
,blockDevice);
break;
case ENXIO:
fprintf(
stderr
,"%s is not a valid block device"
,blockDevice);
break;
default:
fputs(strerror(errno), stderr);
}
putc('\n', stderr);
return -1;
}
} }
extern int extern int mount_main (int argc, char **argv)
mount_main(struct FileInfo * i, int argc, char * * argv)
{ {
char string_flags[1024]; char string_flags[1024]="\0";
unsigned long flags = 0; unsigned long flags = 0;
char * filesystemType = "auto"; char *filesystemType = "auto";
int fake = 0; int all = 0;
int noMtab = 0; int i = argc;
int all = 0;
*string_flags = '\0';
if ( argc == 1 ) { if (argc == 1) {
FILE * mountTable; FILE *mountTable;
if ( (mountTable = setmntent("/etc/mtab", "r")) ) { if ((mountTable = setmntent ("/proc/mounts", "r"))) {
struct mntent * m; struct mntent *m;
while ( (m = getmntent(mountTable)) != 0 ) { while ((m = getmntent (mountTable)) != 0) {
printf( char *blockDevice = m->mnt_fsname;
"%s on %s type %s (%s)\n" if (strcmp (blockDevice, "/dev/root") == 0)
,m->mnt_fsname blockDevice = (getfsfile ("/"))->fs_spec;
,m->mnt_dir printf ("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
,m->mnt_type m->mnt_type, m->mnt_opts);
,m->mnt_opts); }
} endmntent (mountTable);
endmntent(mountTable);
}
return 0;
} }
return( TRUE);
}
while ( argc >= 2 && argv[1][0] == '-' ) {
switch ( argv[1][1] ) { /* Parse options */
case 'f': while (**argv) {
fake = 1; if (**argv == '-') {
break; switch (**argv) {
case 'n': case 'o':
noMtab = 1; if (++argv == 0) {
break; fprintf (stderr, "%s\n", mount_usage);
case 'o': return( FALSE);
if ( argc < 3 ) {
usage(mount_usage);
return 1;
}
parse_mount_options(argv[2], &flags, string_flags);
argc--;
argv++;
break;
case 'r':
flags |= MS_RDONLY;
break;
case 't':
if ( argc < 3 ) {
usage(mount_usage);
return 1;
}
filesystemType = argv[2];
argc--;
argv++;
break;
case 'v':
break;
case 'w':
flags &= ~MS_RDONLY;
break;
case 'a':
all = 1;
break;
default:
usage(mount_usage);
return 1;
} }
parse_mount_options (*argv, &flags, string_flags);
argc--; argc--;
argv++; argv++;
break;
case 'r':
flags |= MS_RDONLY;
break;
case 't':
if (++argv == 0) {
fprintf (stderr, "%s\n", mount_usage);
return( FALSE);
}
filesystemType = *argv;
argc--;
argv++;
break;
case 'w':
flags &= ~MS_RDONLY;
break;
case 'a':
all = 1;
break;
case 'v':
case 'h':
case '-':
fprintf (stderr, "%s\n", mount_usage);
return( TRUE);
}
}
i--;
argv++;
}
if (all == 1) {
struct mntent *m;
FILE *f = setmntent ("/etc/fstab", "r");
if (f == NULL) {
perror("/etc/fstab");
return( FALSE);
}
// FIXME: Combine read routine (make new function) with unmount_all
// to save space.
while ((m = getmntent (f)) != NULL) {
// If the file system isn't noauto, and isn't mounted on /, mount
// it
if ((!strstr (m->mnt_opts, "noauto"))
&& (m->mnt_dir[1] != '\0') && !((m->mnt_type[0] == 's')
&& (m->mnt_type[1] == 'w'))
&& !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) {
mount_one (m->mnt_fsname, m->mnt_dir, m->mnt_type, flags,
m->mnt_opts);
}
} }
if (all == 1) { endmntent (f);
struct mntent *m; } else {
FILE *f = setmntent("/etc/fstab", "r"); if (argc >= 3) {
while (i < argc)
if (f == NULL) { argv--;
return 1; while (**argv == '-')
} argv++;
if (mount_one
// FIXME: Combine read routine (make new function) with unmount_all to save space. (*argv, *(argv+1), filesystemType, flags,
string_flags) == 0) return 0;
while ((m = getmntent(f)) != NULL) { else
// If the file system isn't noauto, and isn't mounted on /, mount it return( FALSE);
if ((!strstr(m->mnt_opts, "noauto")) && (m->mnt_dir[1] != '\0')
&& !((m->mnt_type[0] == 's') && (m->mnt_type[1] == 'w'))
&& !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) {
mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, flags, m->mnt_opts, noMtab, fake);
}
}
endmntent(f);
} else { } else {
if ( argc >= 3 ) { fprintf (stderr, "%s\n", mount_usage);
if ( mount_one( argv[1], argv[2], filesystemType, flags, string_flags, noMtab, fake) == 0 ) return( FALSE);
return 0;
else
return 1;
} else {
usage(mount_usage);
return 1;
}
} }
return 0; }
return( TRUE);
} }