Apply patches from osm0sis/android-busybox-ndk

Auto generated by ndk-busybox-kitchen
This commit is contained in:
topjohnwu 2017-09-05 11:54:52 +08:00
parent 81e26c4b8e
commit 12da53078d
63 changed files with 4748 additions and 38 deletions

View File

@ -476,6 +476,7 @@ libs-y := \
init/ \
libbb/ \
libpwdgrp/ \
libres/ \
loginutils/ \
mailutils/ \
miscutils/ \

View File

@ -1982,12 +1982,12 @@ extern struct globals *const ptr_to_globals;
* use bb_default_login_shell and following defines.
* If you change LIBBB_DEFAULT_LOGIN_SHELL,
* don't forget to change increment constant. */
#define LIBBB_DEFAULT_LOGIN_SHELL "-/bin/sh"
#define LIBBB_DEFAULT_LOGIN_SHELL "-/sbin/sh"
extern const char bb_default_login_shell[] ALIGN1;
/* "/bin/sh" */
#define DEFAULT_SHELL (bb_default_login_shell+1)
/* "sh" */
#define DEFAULT_SHELL_SHORT_NAME (bb_default_login_shell+6)
#define DEFAULT_SHELL_SHORT_NAME (bb_default_login_shell+7)
/* The following devices are the same on all systems. */
#define CURRENT_TTY "/dev/tty"

View File

@ -0,0 +1,58 @@
/*
* Linux INET6 implementation
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
* 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.
*/
#ifndef _LINUX_IPV6_ROUTE_H
#define _LINUX_IPV6_ROUTE_H
#include <linux/types.h>
#define RTF_DEFAULT 0x00010000 /* default - learned via ND */
#define RTF_ALLONLINK 0x00020000 /* (deprecated and will be removed)
fallback, no routers on link */
#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */
#define RTF_PREFIX_RT 0x00080000 /* A prefix only route - RA */
#define RTF_ANYCAST 0x00100000 /* Anycast */
#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */
#define RTF_EXPIRES 0x00400000
#define RTF_ROUTEINFO 0x00800000 /* route information - RA */
#define RTF_CACHE 0x01000000 /* cache entry */
#define RTF_FLOW 0x02000000 /* flow significant route */
#define RTF_POLICY 0x04000000 /* policy route */
#define RTF_PREF(pref) ((pref) << 27)
#define RTF_PREF_MASK 0x18000000
#define RTF_LOCAL 0x80000000
struct in6_rtmsg {
struct in6_addr rtmsg_dst;
struct in6_addr rtmsg_src;
struct in6_addr rtmsg_gateway;
__u32 rtmsg_type;
__u16 rtmsg_dst_len;
__u16 rtmsg_src_len;
__u32 rtmsg_metric;
unsigned long rtmsg_info;
__u32 rtmsg_flags;
int rtmsg_ifindex;
};
#define RTMSG_NEWDEVICE 0x11
#define RTMSG_DELDEVICE 0x12
#define RTMSG_NEWROUTE 0x21
#define RTMSG_DELROUTE 0x22
#endif

277
include/mtd/mtd-abi.h Normal file
View File

@ -0,0 +1,277 @@
/*
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __MTD_ABI_H__
#define __MTD_ABI_H__
#include <linux/types.h>
struct erase_info_user {
__u32 start;
__u32 length;
};
struct erase_info_user64 {
__u64 start;
__u64 length;
};
struct mtd_oob_buf {
__u32 start;
__u32 length;
unsigned char *ptr;
};
struct mtd_oob_buf64 {
__u64 start;
__u32 pad;
__u32 length;
__u64 usr_ptr;
};
/**
* MTD operation modes
*
* @MTD_OPS_PLACE_OOB: OOB data are placed at the given offset (default)
* @MTD_OPS_AUTO_OOB: OOB data are automatically placed at the free areas
* which are defined by the internal ecclayout
* @MTD_OPS_RAW: data are transferred as-is, with no error correction;
* this mode implies %MTD_OPS_PLACE_OOB
*
* These modes can be passed to ioctl(MEMWRITE) and are also used internally.
* See notes on "MTD file modes" for discussion on %MTD_OPS_RAW vs.
* %MTD_FILE_MODE_RAW.
*/
enum {
MTD_OPS_PLACE_OOB = 0,
MTD_OPS_AUTO_OOB = 1,
MTD_OPS_RAW = 2,
};
/**
* struct mtd_write_req - data structure for requesting a write operation
*
* @start: start address
* @len: length of data buffer
* @ooblen: length of OOB buffer
* @usr_data: user-provided data buffer
* @usr_oob: user-provided OOB buffer
* @mode: MTD mode (see "MTD operation modes")
* @padding: reserved, must be set to 0
*
* This structure supports ioctl(MEMWRITE) operations, allowing data and/or OOB
* writes in various modes. To write to OOB-only, set @usr_data == NULL, and to
* write data-only, set @usr_oob == NULL. However, setting both @usr_data and
* @usr_oob to NULL is not allowed.
*/
struct mtd_write_req {
__u64 start;
__u64 len;
__u64 ooblen;
__u64 usr_data;
__u64 usr_oob;
__u8 mode;
__u8 padding[7];
};
#define MTD_ABSENT 0
#define MTD_RAM 1
#define MTD_ROM 2
#define MTD_NORFLASH 3
#define MTD_NANDFLASH 4
#define MTD_DATAFLASH 6
#define MTD_UBIVOLUME 7
#define MTD_MLCNANDFLASH 8
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
#define MTD_NO_ERASE 0x1000 /* No erase necessary */
#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
/* Some common devices / combinations of capabilities */
#define MTD_CAP_ROM 0
#define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
#define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE)
#define MTD_CAP_NANDFLASH (MTD_WRITEABLE)
/* Obsolete ECC byte placement modes (used with obsolete MEMGETOOBSEL) */
#define MTD_NANDECC_OFF 0 // Switch off ECC (Not recommended)
#define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode)
#define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme
#define MTD_NANDECC_PLACEONLY 3 // Use the given placement in the structure (Do not store ecc result on read)
#define MTD_NANDECC_AUTOPL_USR 4 // Use the given autoplacement scheme rather than using the default
/* OTP mode selection */
#define MTD_OTP_OFF 0
#define MTD_OTP_FACTORY 1
#define MTD_OTP_USER 2
struct mtd_info_user {
__u8 type;
__u32 flags;
__u32 size; /* Total size of the MTD */
__u32 erasesize;
__u32 writesize;
__u32 oobsize; /* Amount of OOB data per block (e.g. 16) */
__u64 padding; /* Old obsolete field; do not use */
};
struct region_info_user {
__u32 offset; /* At which this region starts,
* from the beginning of the MTD */
__u32 erasesize; /* For this region */
__u32 numblocks; /* Number of blocks in this region */
__u32 regionindex;
};
struct otp_info {
__u32 start;
__u32 length;
__u32 locked;
};
/*
* Note, the following ioctl existed in the past and was removed:
* #define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo)
* Try to avoid adding a new ioctl with the same ioctl number.
*/
/* Get basic MTD characteristics info (better to use sysfs) */
#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
/* Erase segment of MTD */
#define MEMERASE _IOW('M', 2, struct erase_info_user)
/* Write out-of-band data from MTD */
#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
/* Read out-of-band data from MTD */
#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
/* Lock a chip (for MTD that supports it) */
#define MEMLOCK _IOW('M', 5, struct erase_info_user)
/* Unlock a chip (for MTD that supports it) */
#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
/* Get the number of different erase regions */
#define MEMGETREGIONCOUNT _IOR('M', 7, int)
/* Get information about the erase region for a specific index */
#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
/* Get info about OOB modes (e.g., RAW, PLACE, AUTO) - legacy interface */
#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo)
/* Check if an eraseblock is bad */
#define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t)
/* Mark an eraseblock as bad */
#define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t)
/* Set OTP (One-Time Programmable) mode (factory vs. user) */
#define OTPSELECT _IOR('M', 13, int)
/* Get number of OTP (One-Time Programmable) regions */
#define OTPGETREGIONCOUNT _IOW('M', 14, int)
/* Get all OTP (One-Time Programmable) info about MTD */
#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info)
/* Lock a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */
#define OTPLOCK _IOR('M', 16, struct otp_info)
/* Get ECC layout (deprecated) */
#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout_user)
/* Get statistics about corrected/uncorrected errors */
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
/* Set MTD mode on a per-file-descriptor basis (see "MTD file modes") */
#define MTDFILEMODE _IO('M', 19)
/* Erase segment of MTD (supports 64-bit address) */
#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
/* Write data to OOB (64-bit version) */
#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64)
/* Read data from OOB (64-bit version) */
#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64)
/* Check if chip is locked (for MTD that supports it) */
#define MEMISLOCKED _IOR('M', 23, struct erase_info_user)
/*
* Most generic write interface; can write in-band and/or out-of-band in various
* modes (see "struct mtd_write_req")
*/
#define MEMWRITE _IOWR('M', 24, struct mtd_write_req)
/*
* Obsolete legacy interface. Keep it in order not to break userspace
* interfaces
*/
struct nand_oobinfo {
__u32 useecc;
__u32 eccbytes;
__u32 oobfree[8][2];
__u32 eccpos[32];
};
struct nand_oobfree {
__u32 offset;
__u32 length;
};
#define MTD_MAX_OOBFREE_ENTRIES 8
#define MTD_MAX_ECCPOS_ENTRIES 64
/*
* OBSOLETE: ECC layout control structure. Exported to user-space via ioctl
* ECCGETLAYOUT for backwards compatbility and should not be mistaken as a
* complete set of ECC information. The ioctl truncates the larger internal
* structure to retain binary compatibility with the static declaration of the
* ioctl. Note that the "MTD_MAX_..._ENTRIES" macros represent the max size of
* the user struct, not the MAX size of the internal struct nand_ecclayout.
*/
struct nand_ecclayout_user {
__u32 eccbytes;
__u32 eccpos[MTD_MAX_ECCPOS_ENTRIES];
__u32 oobavail;
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
};
/**
* struct mtd_ecc_stats - error correction stats
*
* @corrected: number of corrected bits
* @failed: number of uncorrectable errors
* @badblocks: number of bad blocks in this partition
* @bbtblocks: number of blocks reserved for bad block tables
*/
struct mtd_ecc_stats {
__u32 corrected;
__u32 failed;
__u32 badblocks;
__u32 bbtblocks;
};
/*
* MTD file modes - for read/write access to MTD
*
* @MTD_FILE_MODE_NORMAL: OTP disabled, ECC enabled
* @MTD_FILE_MODE_OTP_FACTORY: OTP enabled in factory mode
* @MTD_FILE_MODE_OTP_USER: OTP enabled in user mode
* @MTD_FILE_MODE_RAW: OTP disabled, ECC disabled
*
* These modes can be set via ioctl(MTDFILEMODE). The mode mode will be retained
* separately for each open file descriptor.
*
* Note: %MTD_FILE_MODE_RAW provides the same functionality as %MTD_OPS_RAW -
* raw access to the flash, without error correction or autoplacement schemes.
* Wherever possible, the MTD_OPS_* mode will override the MTD_FILE_MODE_* mode
* (e.g., when using ioctl(MEMWRITE)), but in some cases, the MTD_FILE_MODE is
* used out of necessity (e.g., `write()', ioctl(MEMWRITEOOB64)).
*/
enum mtd_file_modes {
MTD_FILE_MODE_NORMAL = MTD_OTP_OFF,
MTD_FILE_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
MTD_FILE_MODE_OTP_USER = MTD_OTP_USER,
MTD_FILE_MODE_RAW,
};
#endif /* __MTD_ABI_H__ */

34
include/mtd/mtd-user.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __MTD_USER_H__
#define __MTD_USER_H__
#include <stdint.h>
/* This file is blessed for inclusion by userspace */
#include <mtd/mtd-abi.h>
typedef struct mtd_info_user mtd_info_t;
typedef struct erase_info_user erase_info_t;
typedef struct region_info_user region_info_t;
typedef struct nand_oobinfo nand_oobinfo_t;
typedef struct nand_ecclayout_user nand_ecclayout_t;
#endif /* __MTD_USER_H__ */

412
include/mtd/ubi-user.h Normal file
View File

@ -0,0 +1,412 @@
/*
* Copyright (c) International Business Machines Corp., 2006
*
* 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
*
* Author: Artem Bityutskiy (Битюцкий Артём)
*/
#ifndef __UBI_USER_H__
#define __UBI_USER_H__
#include <linux/types.h>
/*
* UBI device creation (the same as MTD device attachment)
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* MTD devices may be attached using %UBI_IOCATT ioctl command of the UBI
* control device. The caller has to properly fill and pass
* &struct ubi_attach_req object - UBI will attach the MTD device specified in
* the request and return the newly created UBI device number as the ioctl
* return value.
*
* UBI device deletion (the same as MTD device detachment)
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* An UBI device maybe deleted with %UBI_IOCDET ioctl command of the UBI
* control device.
*
* UBI volume creation
* ~~~~~~~~~~~~~~~~~~~
*
* UBI volumes are created via the %UBI_IOCMKVOL ioctl command of UBI character
* device. A &struct ubi_mkvol_req object has to be properly filled and a
* pointer to it has to be passed to the ioctl.
*
* UBI volume deletion
* ~~~~~~~~~~~~~~~~~~~
*
* To delete a volume, the %UBI_IOCRMVOL ioctl command of the UBI character
* device should be used. A pointer to the 32-bit volume ID hast to be passed
* to the ioctl.
*
* UBI volume re-size
* ~~~~~~~~~~~~~~~~~~
*
* To re-size a volume, the %UBI_IOCRSVOL ioctl command of the UBI character
* device should be used. A &struct ubi_rsvol_req object has to be properly
* filled and a pointer to it has to be passed to the ioctl.
*
* UBI volumes re-name
* ~~~~~~~~~~~~~~~~~~~
*
* To re-name several volumes atomically at one go, the %UBI_IOCRNVOL command
* of the UBI character device should be used. A &struct ubi_rnvol_req object
* has to be properly filled and a pointer to it has to be passed to the ioctl.
*
* UBI volume update
* ~~~~~~~~~~~~~~~~~
*
* Volume update should be done via the %UBI_IOCVOLUP ioctl command of the
* corresponding UBI volume character device. A pointer to a 64-bit update
* size should be passed to the ioctl. After this, UBI expects user to write
* this number of bytes to the volume character device. The update is finished
* when the claimed number of bytes is passed. So, the volume update sequence
* is something like:
*
* fd = open("/dev/my_volume");
* ioctl(fd, UBI_IOCVOLUP, &image_size);
* write(fd, buf, image_size);
* close(fd);
*
* Logical eraseblock erase
* ~~~~~~~~~~~~~~~~~~~~~~~~
*
* To erase a logical eraseblock, the %UBI_IOCEBER ioctl command of the
* corresponding UBI volume character device should be used. This command
* unmaps the requested logical eraseblock, makes sure the corresponding
* physical eraseblock is successfully erased, and returns.
*
* Atomic logical eraseblock change
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Atomic logical eraseblock change operation is called using the %UBI_IOCEBCH
* ioctl command of the corresponding UBI volume character device. A pointer to
* a &struct ubi_leb_change_req object has to be passed to the ioctl. Then the
* user is expected to write the requested amount of bytes (similarly to what
* should be done in case of the "volume update" ioctl).
*
* Logical eraseblock map
* ~~~~~~~~~~~~~~~~~~~~~
*
* To map a logical eraseblock to a physical eraseblock, the %UBI_IOCEBMAP
* ioctl command should be used. A pointer to a &struct ubi_map_req object is
* expected to be passed. The ioctl maps the requested logical eraseblock to
* a physical eraseblock and returns. Only non-mapped logical eraseblocks can
* be mapped. If the logical eraseblock specified in the request is already
* mapped to a physical eraseblock, the ioctl fails and returns error.
*
* Logical eraseblock unmap
* ~~~~~~~~~~~~~~~~~~~~~~~~
*
* To unmap a logical eraseblock to a physical eraseblock, the %UBI_IOCEBUNMAP
* ioctl command should be used. The ioctl unmaps the logical eraseblocks,
* schedules corresponding physical eraseblock for erasure, and returns. Unlike
* the "LEB erase" command, it does not wait for the physical eraseblock being
* erased. Note, the side effect of this is that if an unclean reboot happens
* after the unmap ioctl returns, you may find the LEB mapped again to the same
* physical eraseblock after the UBI is run again.
*
* Check if logical eraseblock is mapped
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* To check if a logical eraseblock is mapped to a physical eraseblock, the
* %UBI_IOCEBISMAP ioctl command should be used. It returns %0 if the LEB is
* not mapped, and %1 if it is mapped.
*
* Set an UBI volume property
* ~~~~~~~~~~~~~~~~~~~~~~~~~
*
* To set an UBI volume property the %UBI_IOCSETPROP ioctl command should be
* used. A pointer to a &struct ubi_set_prop_req object is expected to be
* passed. The object describes which property should be set, and to which value
* it should be set.
*/
/*
* When a new UBI volume or UBI device is created, users may either specify the
* volume/device number they want to create or to let UBI automatically assign
* the number using these constants.
*/
#define UBI_VOL_NUM_AUTO (-1)
#define UBI_DEV_NUM_AUTO (-1)
/* Maximum volume name length */
#define UBI_MAX_VOLUME_NAME 127
/* ioctl commands of UBI character devices */
#define UBI_IOC_MAGIC 'o'
/* Create an UBI volume */
#define UBI_IOCMKVOL _IOW(UBI_IOC_MAGIC, 0, struct ubi_mkvol_req)
/* Remove an UBI volume */
#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, __s32)
/* Re-size an UBI volume */
#define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req)
/* Re-name volumes */
#define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req)
/* ioctl commands of the UBI control character device */
#define UBI_CTRL_IOC_MAGIC 'o'
/* Attach an MTD device */
#define UBI_IOCATT _IOW(UBI_CTRL_IOC_MAGIC, 64, struct ubi_attach_req)
/* Detach an MTD device */
#define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, __s32)
/* ioctl commands of UBI volume character devices */
#define UBI_VOL_IOC_MAGIC 'O'
/* Start UBI volume update */
#define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, __s64)
/* LEB erasure command, used for debugging, disabled by default */
#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, __s32)
/* Atomic LEB change command */
#define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, __s32)
/* Map LEB command */
#define UBI_IOCEBMAP _IOW(UBI_VOL_IOC_MAGIC, 3, struct ubi_map_req)
/* Unmap LEB command */
#define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, __s32)
/* Check if LEB is mapped command */
#define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, __s32)
/* Set an UBI volume property */
#define UBI_IOCSETPROP _IOW(UBI_VOL_IOC_MAGIC, 6, struct ubi_set_prop_req)
/* Maximum MTD device name length supported by UBI */
#define MAX_UBI_MTD_NAME_LEN 127
/* Maximum amount of UBI volumes that can be re-named at one go */
#define UBI_MAX_RNVOL 32
/*
* UBI data type hint constants.
*
* UBI_LONGTERM: long-term data
* UBI_SHORTTERM: short-term data
* UBI_UNKNOWN: data persistence is unknown
*
* These constants are used when data is written to UBI volumes in order to
* help the UBI wear-leveling unit to find more appropriate physical
* eraseblocks.
*/
enum {
UBI_LONGTERM = 1,
UBI_SHORTTERM = 2,
UBI_UNKNOWN = 3,
};
/*
* UBI volume type constants.
*
* @UBI_DYNAMIC_VOLUME: dynamic volume
* @UBI_STATIC_VOLUME: static volume
*/
enum {
UBI_DYNAMIC_VOLUME = 3,
UBI_STATIC_VOLUME = 4,
};
/*
* UBI set property ioctl constants
*
* @UBI_PROP_DIRECT_WRITE: allow / disallow user to directly write and
* erase individual eraseblocks on dynamic volumes
*/
enum {
UBI_PROP_DIRECT_WRITE = 1,
};
/**
* struct ubi_attach_req - attach MTD device request.
* @ubi_num: UBI device number to create
* @mtd_num: MTD device number to attach
* @vid_hdr_offset: VID header offset (use defaults if %0)
* @padding: reserved for future, not used, has to be zeroed
*
* This data structure is used to specify MTD device UBI has to attach and the
* parameters it has to use. The number which should be assigned to the new UBI
* device is passed in @ubi_num. UBI may automatically assign the number if
* @UBI_DEV_NUM_AUTO is passed. In this case, the device number is returned in
* @ubi_num.
*
* Most applications should pass %0 in @vid_hdr_offset to make UBI use default
* offset of the VID header within physical eraseblocks. The default offset is
* the next min. I/O unit after the EC header. For example, it will be offset
* 512 in case of a 512 bytes page NAND flash with no sub-page support. Or
* it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages.
*
* But in rare cases, if this optimizes things, the VID header may be placed to
* a different offset. For example, the boot-loader might do things faster if
* the VID header sits at the end of the first 2KiB NAND page with 4 sub-pages.
* As the boot-loader would not normally need to read EC headers (unless it
* needs UBI in RW mode), it might be faster to calculate ECC. This is weird
* example, but it real-life example. So, in this example, @vid_hdr_offer would
* be 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes
* aligned, which is OK, as UBI is clever enough to realize this is 4th
* sub-page of the first page and add needed padding.
*/
struct ubi_attach_req {
__s32 ubi_num;
__s32 mtd_num;
__s32 vid_hdr_offset;
__s8 padding[12];
};
/**
* struct ubi_mkvol_req - volume description data structure used in
* volume creation requests.
* @vol_id: volume number
* @alignment: volume alignment
* @bytes: volume size in bytes
* @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
* @padding1: reserved for future, not used, has to be zeroed
* @name_len: volume name length
* @padding2: reserved for future, not used, has to be zeroed
* @name: volume name
*
* This structure is used by user-space programs when creating new volumes. The
* @used_bytes field is only necessary when creating static volumes.
*
* The @alignment field specifies the required alignment of the volume logical
* eraseblock. This means, that the size of logical eraseblocks will be aligned
* to this number, i.e.,
* (UBI device logical eraseblock size) mod (@alignment) = 0.
*
* To put it differently, the logical eraseblock of this volume may be slightly
* shortened in order to make it properly aligned. The alignment has to be
* multiple of the flash minimal input/output unit, or %1 to utilize the entire
* available space of logical eraseblocks.
*
* The @alignment field may be useful, for example, when one wants to maintain
* a block device on top of an UBI volume. In this case, it is desirable to fit
* an integer number of blocks in logical eraseblocks of this UBI volume. With
* alignment it is possible to update this volume using plane UBI volume image
* BLOBs, without caring about how to properly align them.
*/
struct ubi_mkvol_req {
__s32 vol_id;
__s32 alignment;
__s64 bytes;
__s8 vol_type;
__s8 padding1;
__s16 name_len;
__s8 padding2[4];
char name[UBI_MAX_VOLUME_NAME + 1];
} __attribute__ ((packed));
/**
* struct ubi_rsvol_req - a data structure used in volume re-size requests.
* @vol_id: ID of the volume to re-size
* @bytes: new size of the volume in bytes
*
* Re-sizing is possible for both dynamic and static volumes. But while dynamic
* volumes may be re-sized arbitrarily, static volumes cannot be made to be
* smaller than the number of bytes they bear. To arbitrarily shrink a static
* volume, it must be wiped out first (by means of volume update operation with
* zero number of bytes).
*/
struct ubi_rsvol_req {
__s64 bytes;
__s32 vol_id;
} __attribute__ ((packed));
/**
* struct ubi_rnvol_req - volumes re-name request.
* @count: count of volumes to re-name
* @padding1: reserved for future, not used, has to be zeroed
* @vol_id: ID of the volume to re-name
* @name_len: name length
* @padding2: reserved for future, not used, has to be zeroed
* @name: new volume name
*
* UBI allows to re-name up to %32 volumes at one go. The count of volumes to
* re-name is specified in the @count field. The ID of the volumes to re-name
* and the new names are specified in the @vol_id and @name fields.
*
* The UBI volume re-name operation is atomic, which means that should power cut
* happen, the volumes will have either old name or new name. So the possible
* use-cases of this command is atomic upgrade. Indeed, to upgrade, say, volumes
* A and B one may create temporary volumes %A1 and %B1 with the new contents,
* then atomically re-name A1->A and B1->B, in which case old %A and %B will
* be removed.
*
* If it is not desirable to remove old A and B, the re-name request has to
* contain 4 entries: A1->A, A->A1, B1->B, B->B1, in which case old A1 and B1
* become A and B, and old A and B will become A1 and B1.
*
* It is also OK to request: A1->A, A1->X, B1->B, B->Y, in which case old A1
* and B1 become A and B, and old A and B become X and Y.
*
* In other words, in case of re-naming into an existing volume name, the
* existing volume is removed, unless it is re-named as well at the same
* re-name request.
*/
struct ubi_rnvol_req {
__s32 count;
__s8 padding1[12];
struct {
__s32 vol_id;
__s16 name_len;
__s8 padding2[2];
char name[UBI_MAX_VOLUME_NAME + 1];
} ents[UBI_MAX_RNVOL];
} __attribute__ ((packed));
/**
* struct ubi_leb_change_req - a data structure used in atomic LEB change
* requests.
* @lnum: logical eraseblock number to change
* @bytes: how many bytes will be written to the logical eraseblock
* @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
* @padding: reserved for future, not used, has to be zeroed
*/
struct ubi_leb_change_req {
__s32 lnum;
__s32 bytes;
__s8 dtype;
__s8 padding[7];
} __attribute__ ((packed));
/**
* struct ubi_map_req - a data structure used in map LEB requests.
* @lnum: logical eraseblock number to unmap
* @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
* @padding: reserved for future, not used, has to be zeroed
*/
struct ubi_map_req {
__s32 lnum;
__s8 dtype;
__s8 padding[3];
} __attribute__ ((packed));
/**
* struct ubi_set_prop_req - a data structure used to set an ubi volume
* property.
* @property: property to set (%UBI_PROP_DIRECT_WRITE)
* @padding: reserved for future, not used, has to be zeroed
* @value: value to set
*/
struct ubi_set_prop_req {
__u8 property;
__u8 padding[7];
__u64 value;
} __attribute__ ((packed));
#endif /* __UBI_USER_H__ */

View File

@ -393,6 +393,8 @@ typedef unsigned smalluint;
#define HAVE_MNTENT_H 1
#define HAVE_NET_ETHERNET_H 1
#define HAVE_SYS_STATFS_H 1
#define HAVE_WAIT3 1
#define HAVE_ISSETUGID 1
#if defined(__UCLIBC__)
# if UCLIBC_VERSION < KERNEL_VERSION(0, 9, 32)
@ -494,16 +496,22 @@ typedef unsigned smalluint;
# else
/* ANDROID >= 21 has standard dprintf */
# endif
# if __ANDROID_API__ > 18
# undef HAVE_ISSETUGID
# endif
# if __ANDROID_API__ < 21
# undef HAVE_TTYNAME_R
# undef HAVE_GETLINE
# undef HAVE_STPCPY
# else
# undef HAVE_WAIT3
# endif
# undef HAVE_MEMPCPY
# undef HAVE_STRCHRNUL
# undef HAVE_STRVERSCMP
# undef HAVE_UNLOCKED_LINE_OPS
# undef HAVE_NET_ETHERNET_H
# undef HAVE_SETBIT
#endif
/*
@ -584,4 +592,14 @@ extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC
extern ssize_t getline(char **lineptr, size_t *n, FILE *stream) FAST_FUNC;
#endif
#ifndef HAVE_WAIT3
/* Wrap wait3() to wait4() for libc implementations without (e.g. Bionic on ANDROID >= 21) */
# include <sys/wait.h> /* for rusage */
static pid_t wait3(int* status, int options, struct rusage* rusage) { return wait4(-1, status, options, rusage); }
#endif
#ifndef HAVE_ISSETUGID
extern int issetugid(void) FAST_FUNC;
#endif
#endif

225
include/scsi/scsi.h Normal file
View File

@ -0,0 +1,225 @@
/* Copyright (C) 1998-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/*
* This header file contains public constants and structures used by
* the scsi code for linux.
*/
#ifndef _SCSI_SCSI_H
#define _SCSI_SCSI_H 1
#include <features.h>
/*
* SCSI opcodes
*/
#define TEST_UNIT_READY 0x00
#define REZERO_UNIT 0x01
#define REQUEST_SENSE 0x03
#define FORMAT_UNIT 0x04
#define READ_BLOCK_LIMITS 0x05
#define REASSIGN_BLOCKS 0x07
#define READ_6 0x08
#define WRITE_6 0x0a
#define SEEK_6 0x0b
#define READ_REVERSE 0x0f
#define WRITE_FILEMARKS 0x10
#define SPACE 0x11
#define INQUIRY 0x12
#define RECOVER_BUFFERED_DATA 0x14
#define MODE_SELECT 0x15
#define RESERVE 0x16
#define RELEASE 0x17
#define COPY 0x18
#define ERASE 0x19
#define MODE_SENSE 0x1a
#define START_STOP 0x1b
#define RECEIVE_DIAGNOSTIC 0x1c
#define SEND_DIAGNOSTIC 0x1d
#define ALLOW_MEDIUM_REMOVAL 0x1e
#define SET_WINDOW 0x24
#define READ_CAPACITY 0x25
#define READ_10 0x28
#define WRITE_10 0x2a
#define SEEK_10 0x2b
#define WRITE_VERIFY 0x2e
#define VERIFY 0x2f
#define SEARCH_HIGH 0x30
#define SEARCH_EQUAL 0x31
#define SEARCH_LOW 0x32
#define SET_LIMITS 0x33
#define PRE_FETCH 0x34
#define READ_POSITION 0x34
#define SYNCHRONIZE_CACHE 0x35
#define LOCK_UNLOCK_CACHE 0x36
#define READ_DEFECT_DATA 0x37
#define MEDIUM_SCAN 0x38
#define COMPARE 0x39
#define COPY_VERIFY 0x3a
#define WRITE_BUFFER 0x3b
#define READ_BUFFER 0x3c
#define UPDATE_BLOCK 0x3d
#define READ_LONG 0x3e
#define WRITE_LONG 0x3f
#define CHANGE_DEFINITION 0x40
#define WRITE_SAME 0x41
#define READ_TOC 0x43
#define LOG_SELECT 0x4c
#define LOG_SENSE 0x4d
#define MODE_SELECT_10 0x55
#define RESERVE_10 0x56
#define RELEASE_10 0x57
#define MODE_SENSE_10 0x5a
#define PERSISTENT_RESERVE_IN 0x5e
#define PERSISTENT_RESERVE_OUT 0x5f
#define MOVE_MEDIUM 0xa5
#define READ_12 0xa8
#define WRITE_12 0xaa
#define WRITE_VERIFY_12 0xae
#define SEARCH_HIGH_12 0xb0
#define SEARCH_EQUAL_12 0xb1
#define SEARCH_LOW_12 0xb2
#define READ_ELEMENT_STATUS 0xb8
#define SEND_VOLUME_TAG 0xb6
#define WRITE_LONG_2 0xea
/*
* Status codes
*/
#define GOOD 0x00
#define CHECK_CONDITION 0x01
#define CONDITION_GOOD 0x02
#define BUSY 0x04
#define INTERMEDIATE_GOOD 0x08
#define INTERMEDIATE_C_GOOD 0x0a
#define RESERVATION_CONFLICT 0x0c
#define COMMAND_TERMINATED 0x11
#define QUEUE_FULL 0x14
#define STATUS_MASK 0x3e
/*
* SENSE KEYS
*/
#define NO_SENSE 0x00
#define RECOVERED_ERROR 0x01
#define NOT_READY 0x02
#define MEDIUM_ERROR 0x03
#define HARDWARE_ERROR 0x04
#define ILLEGAL_REQUEST 0x05
#define UNIT_ATTENTION 0x06
#define DATA_PROTECT 0x07
#define BLANK_CHECK 0x08
#define COPY_ABORTED 0x0a
#define ABORTED_COMMAND 0x0b
#define VOLUME_OVERFLOW 0x0d
#define MISCOMPARE 0x0e
/*
* DEVICE TYPES
*/
#define TYPE_DISK 0x00
#define TYPE_TAPE 0x01
#define TYPE_PROCESSOR 0x03 /* HP scanners use this */
#define TYPE_WORM 0x04 /* Treated as ROM by our system */
#define TYPE_ROM 0x05
#define TYPE_SCANNER 0x06
#define TYPE_MOD 0x07 /* Magneto-optical disk -
* - treated as TYPE_DISK */
#define TYPE_MEDIUM_CHANGER 0x08
#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
#define TYPE_NO_LUN 0x7f
/*
* standard mode-select header prepended to all mode-select commands
*
* moved here from cdrom.h -- kraxel
*/
struct ccs_modesel_head
{
unsigned char _r1; /* reserved. */
unsigned char medium; /* device-specific medium type. */
unsigned char _r2; /* reserved. */
unsigned char block_desc_length; /* block descriptor length. */
unsigned char density; /* device-specific density code. */
unsigned char number_blocks_hi; /* number of blocks in this block
desc. */
unsigned char number_blocks_med;
unsigned char number_blocks_lo;
unsigned char _r3;
unsigned char block_length_hi; /* block length for blocks in this
desc. */
unsigned char block_length_med;
unsigned char block_length_lo;
};
/*
* MESSAGE CODES
*/
#define COMMAND_COMPLETE 0x00
#define EXTENDED_MESSAGE 0x01
#define EXTENDED_MODIFY_DATA_POINTER 0x00
#define EXTENDED_SDTR 0x01
#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */
#define EXTENDED_WDTR 0x03
#define SAVE_POINTERS 0x02
#define RESTORE_POINTERS 0x03
#define DISCONNECT 0x04
#define INITIATOR_ERROR 0x05
#define ABORT 0x06
#define MESSAGE_REJECT 0x07
#define NOP 0x08
#define MSG_PARITY_ERROR 0x09
#define LINKED_CMD_COMPLETE 0x0a
#define LINKED_FLG_CMD_COMPLETE 0x0b
#define BUS_DEVICE_RESET 0x0c
#define INITIATE_RECOVERY 0x0f /* SCSI-II only */
#define RELEASE_RECOVERY 0x10 /* SCSI-II only */
#define SIMPLE_QUEUE_TAG 0x20
#define HEAD_OF_QUEUE_TAG 0x21
#define ORDERED_QUEUE_TAG 0x22
/*
* Here are some scsi specific ioctl commands which are sometimes useful.
*/
/* These are a few other constants only used by scsi devices. */
#define SCSI_IOCTL_GET_IDLUN 0x5382
/* Used to turn on and off tagged queuing for scsi devices. */
#define SCSI_IOCTL_TAGGED_ENABLE 0x5383
#define SCSI_IOCTL_TAGGED_DISABLE 0x5384
/* Used to obtain the host number of a device. */
#define SCSI_IOCTL_PROBE_HOST 0x5385
/* Used to get the bus number for a device. */
#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386
#endif /* scsi/scsi.h */

276
include/scsi/sg.h Normal file
View File

@ -0,0 +1,276 @@
/* Copyright (C) 1997-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/*
History:
Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user
process control of SCSI devices.
Development Sponsored by Killy Corp. NY NY
*/
#ifndef _SCSI_SG_H
#define _SCSI_SG_H 1
#include <features.h>
#define __need_size_t
#include <stddef.h>
/* New interface introduced in the 3.x SG drivers follows */
/* Same structure as used by readv() Linux system call. It defines one
scatter-gather element. */
typedef struct sg_iovec
{
void * iov_base; /* Starting address */
size_t iov_len; /* Length in bytes */
} sg_iovec_t;
typedef struct sg_io_hdr
{
int interface_id; /* [i] 'S' for SCSI generic (required) */
int dxfer_direction; /* [i] data transfer direction */
unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */
unsigned char mx_sb_len; /* [i] max length to write to sbp */
unsigned short int iovec_count; /* [i] 0 implies no scatter gather */
unsigned int dxfer_len; /* [i] byte count of data transfer */
void * dxferp; /* [i], [*io] points to data transfer memory
or scatter gather list */
unsigned char * cmdp; /* [i], [*i] points to command to perform */
unsigned char * sbp; /* [i], [*o] points to sense_buffer memory */
unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */
unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */
int pack_id; /* [i->o] unused internally (normally) */
void * usr_ptr; /* [i->o] unused internally */
unsigned char status; /* [o] scsi status */
unsigned char masked_status;/* [o] shifted, masked scsi status */
unsigned char msg_status; /* [o] messaging level data (optional) */
unsigned char sb_len_wr; /* [o] byte count actually written to sbp */
unsigned short int host_status; /* [o] errors from host adapter */
unsigned short int driver_status;/* [o] errors from software driver */
int resid; /* [o] dxfer_len - actual_transferred */
unsigned int duration; /* [o] time taken by cmd (unit: millisec) */
unsigned int info; /* [o] auxiliary information */
} sg_io_hdr_t;
/* Use negative values to flag difference from original sg_header structure. */
#define SG_DXFER_NONE -1 /* e.g. a SCSI Test Unit Ready command */
#define SG_DXFER_TO_DEV -2 /* e.g. a SCSI WRITE command */
#define SG_DXFER_FROM_DEV -3 /* e.g. a SCSI READ command */
#define SG_DXFER_TO_FROM_DEV -4 /* treated like SG_DXFER_FROM_DEV with the
additional property than during indirect
IO the user buffer is copied into the
kernel buffers before the transfer */
/* following flag values can be "or"-ed together */
#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */
#define SG_FLAG_LUN_INHIBIT 2 /* default is to put device's lun into */
/* the 2nd byte of SCSI command */
#define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */
/* user space (debug indirect IO) */
/* The following 'info' values are "or"-ed together. */
#define SG_INFO_OK_MASK 0x1
#define SG_INFO_OK 0x0 /* no sense, host nor driver "noise" */
#define SG_INFO_CHECK 0x1 /* something abnormal happened */
#define SG_INFO_DIRECT_IO_MASK 0x6
#define SG_INFO_INDIRECT_IO 0x0 /* data xfer via kernel buffers (or no xfer) */
#define SG_INFO_DIRECT_IO 0x2 /* direct IO requested and performed */
#define SG_INFO_MIXED_IO 0x4 /* part direct, part indirect IO */
/* Request information about a specific SG device, used by
SG_GET_SCSI_ID ioctl (). */
struct sg_scsi_id {
/* Host number as in "scsi<n>" where 'n' is one of 0, 1, 2 etc. */
int host_no;
int channel;
/* SCSI id of target device. */
int scsi_id;
int lun;
/* TYPE_... defined in <scsi/scsi.h>. */
int scsi_type;
/* Host (adapter) maximum commands per lun. */
short int h_cmd_per_lun;
/* Device (or adapter) maximum queue length. */
short int d_queue_depth;
/* Unused, set to 0 for now. */
int unused[2];
};
/* Used by SG_GET_REQUEST_TABLE ioctl(). */
typedef struct sg_req_info {
char req_state; /* 0 -> not used, 1 -> written, 2 -> ready to read */
char orphan; /* 0 -> normal request, 1 -> from interruped SG_IO */
char sg_io_owned; /* 0 -> complete with read(), 1 -> owned by SG_IO */
char problem; /* 0 -> no problem detected, 1 -> error to report */
int pack_id; /* pack_id associated with request */
void * usr_ptr; /* user provided pointer (in new interface) */
unsigned int duration; /* millisecs elapsed since written (req_state==1)
or request duration (req_state==2) */
int unused;
} sg_req_info_t;
/* IOCTLs: Those ioctls that are relevant to the SG 3.x drivers follow.
[Those that only apply to the SG 2.x drivers are at the end of the file.]
(_GET_s yield result via 'int *' 3rd argument unless otherwise indicated) */
#define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */
/* Used to configure SCSI command transformation layer for ATAPI devices */
/* Only supported by the ide-scsi driver */
#define SG_SET_TRANSFORM 0x2204 /* N.B. 3rd arg is not pointer but value: */
/* 3rd arg = 0 to disable transform, 1 to enable it */
#define SG_GET_TRANSFORM 0x2205
#define SG_SET_RESERVED_SIZE 0x2275 /* request a new reserved buffer size */
#define SG_GET_RESERVED_SIZE 0x2272 /* actual size of reserved buffer */
/* The following ioctl has a 'sg_scsi_id_t *' object as its 3rd argument. */
#define SG_GET_SCSI_ID 0x2276 /* Yields fd's bus, chan, dev, lun + type */
/* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */
/* Override host setting and always DMA using low memory ( <16MB on i386) */
#define SG_SET_FORCE_LOW_DMA 0x2279 /* 0-> use adapter setting, 1-> force */
#define SG_GET_LOW_DMA 0x227a /* 0-> use all ram for dma; 1-> low dma ram */
/* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which
tries to fetch a packet with a matching pack_id, waits, or returns EAGAIN.
If pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0
then pack_id ignored by read() and oldest readable fetched. */
#define SG_SET_FORCE_PACK_ID 0x227b
#define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */
#define SG_GET_NUM_WAITING 0x227d /* Number of commands awaiting read() */
/* Yields max scatter gather tablesize allowed by current host adapter */
#define SG_GET_SG_TABLESIZE 0x227F /* 0 implies can't do scatter gather */
#define SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */
/* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */
#define SG_SCSI_RESET 0x2284
/* Associated values that can be given to SG_SCSI_RESET follow */
#define SG_SCSI_RESET_NOTHING 0
#define SG_SCSI_RESET_DEVICE 1
#define SG_SCSI_RESET_BUS 2
#define SG_SCSI_RESET_HOST 3
/* synchronous SCSI command ioctl, (only in version 3 interface) */
#define SG_IO 0x2285 /* similar effect as write() followed by read() */
#define SG_GET_REQUEST_TABLE 0x2286 /* yields table of active requests */
/* How to treat EINTR during SG_IO ioctl(), only in SG 3.x series */
#define SG_SET_KEEP_ORPHAN 0x2287 /* 1 -> hold for read(), 0 -> drop (def) */
#define SG_GET_KEEP_ORPHAN 0x2288
#define SG_SCATTER_SZ (8 * 4096) /* PAGE_SIZE not available to user */
/* Largest size (in bytes) a single scatter-gather list element can have.
The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on
i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
by adapter then this value is the largest data block that can be
read/written by a single scsi command. The user can find the value of
PAGE_SIZE by calling getpagesize() defined in unistd.h . */
#define SG_DEFAULT_RETRIES 1
/* Defaults, commented if they differ from original sg driver */
#define SG_DEF_FORCE_LOW_DMA 0 /* was 1 -> memory below 16MB on i386 */
#define SG_DEF_FORCE_PACK_ID 0
#define SG_DEF_KEEP_ORPHAN 0
#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */
/* maximum outstanding requests, write() yields EDOM if exceeded */
#define SG_MAX_QUEUE 16
#define SG_BIG_BUFF SG_DEF_RESERVED_SIZE /* for backward compatibility */
/* Alternate style type names, "..._t" variants preferred */
typedef struct sg_io_hdr Sg_io_hdr;
typedef struct sg_io_vec Sg_io_vec;
typedef struct sg_scsi_id Sg_scsi_id;
typedef struct sg_req_info Sg_req_info;
/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
/* The older SG interface based on the 'sg_header' structure follows. */
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
#define SG_MAX_SENSE 16 /* this only applies to the sg_header interface */
struct sg_header
{
/* Length of incoming packet (including header). */
int pack_len;
/* Maximal length of expected reply. */
int reply_len;
/* Id number of packet. */
int pack_id;
/* 0==ok, otherwise error number. */
int result;
/* Force 12 byte command length for group 6 & 7 commands. */
unsigned int twelve_byte:1;
/* SCSI status from target. */
unsigned int target_status:5;
/* Host status (see "DID" codes). */
unsigned int host_status:8;
/* Driver status+suggestion. */
unsigned int driver_status:8;
/* Unused. */
unsigned int other_flags:10;
/* Output in 3 cases:
when target_status is CHECK_CONDITION or
when target_status is COMMAND_TERMINATED or
when (driver_status & DRIVER_SENSE) is true. */
unsigned char sense_buffer[SG_MAX_SENSE];
};
/* IOCTLs: The following are not required (or ignored) when the sg_io_hdr_t
interface is used. They are kept for backward compatibility with
the original and version 2 drivers. */
#define SG_SET_TIMEOUT 0x2201 /* Set timeout; *(int *)arg==timeout. */
#define SG_GET_TIMEOUT 0x2202 /* Get timeout; return timeout. */
/* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q). */
#define SG_GET_COMMAND_Q 0x2270 /* Yields 0 (queuing off) or 1 (on). */
#define SG_SET_COMMAND_Q 0x2271 /* Change queuing state with 0 or 1. */
/* Turn on error sense trace (1..8), dump this device to log/console (9)
or dump all sg device states ( >9 ) to log/console. */
#define SG_SET_DEBUG 0x227e /* 0 -> turn off debug */
#define SG_NEXT_CMD_LEN 0x2283 /* Override SCSI command length with given
number on the next write() on this file
descriptor. */
/* Defaults, commented if they differ from original sg driver */
#define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */
#define SG_DEF_COMMAND_Q 0 /* command queuing is always on when
the new interface is used */
#define SG_DEF_UNDERRUN_FLAG 0
#endif /* scsi/sg.h */

34
include/sys/kd.h Normal file
View File

@ -0,0 +1,34 @@
/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SYS_KD_H
#define _SYS_KD_H 1
/* Make sure the <linux/types.h> header is not loaded. */
#ifndef _LINUX_TYPES_H
# define _LINUX_TYPES_H 1
# define __undef_LINUX_TYPES_H
#endif
#include <linux/kd.h>
#ifdef __undef_LINUX_TYPES_H
# undef _LINUX_TYPES_H
# undef __undef_LINUX_TYPES_H
#endif
#endif /* sys/kd.h */

138
include/sys/syslog.h Normal file
View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)syslog.h 8.1 (Berkeley) 6/2/93
*
* 2011/7/5 - DD - modified to fit android Bionic environment
*/
#ifndef _SYS_SYSLOG_H
#define _SYS_SYSLOG_H 1
#include <features.h>
#define __need___va_list
#include <stdarg.h>
/*
* priorities/facilities are encoded into a single 32-bit quantity, where the
* bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
* (0-big number). Both the priorities and the facilities map roughly
* one-to-one to strings in the syslogd(8) source code. This mapping is
* included in this file.
*
* priorities (these are ordered)
*/
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
#ifdef SYSLOG_NAMES
#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
/* mark "facility" */
#define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0)
typedef struct _code {
char *c_name;
int c_val;
} CODE;
CODE prioritynames[] =
{
{ "alert", LOG_ALERT },
{ "crit", LOG_CRIT },
{ "debug", LOG_DEBUG },
{ "emerg", LOG_EMERG },
{ "err", LOG_ERR },
{ "error", LOG_ERR }, /* DEPRECATED */
{ "info", LOG_INFO },
{ "none", INTERNAL_NOPRI }, /* INTERNAL */
{ "notice", LOG_NOTICE },
{ "panic", LOG_EMERG }, /* DEPRECATED */
{ "warn", LOG_WARNING }, /* DEPRECATED */
{ "warning", LOG_WARNING },
{ NULL, -1 }
};
#endif
#define LOG_NFACILITIES 24 /* current number of facilities */
#ifdef SYSLOG_NAMES
CODE facilitynames[] =
{
{ "auth", LOG_AUTH },
{ "authpriv", LOG_AUTHPRIV },
{ "cron", LOG_CRON },
{ "daemon", LOG_DAEMON },
{ "ftp", LOG_FTP },
{ "kern", LOG_KERN },
{ "lpr", LOG_LPR },
{ "mail", LOG_MAIL },
{ "mark", INTERNAL_MARK }, /* INTERNAL */
{ "news", LOG_NEWS },
{ "security", LOG_AUTH }, /* DEPRECATED */
{ "syslog", LOG_SYSLOG },
{ "user", LOG_USER },
{ "uucp", LOG_UUCP },
{ "local0", LOG_LOCAL0 },
{ "local1", LOG_LOCAL1 },
{ "local2", LOG_LOCAL2 },
{ "local3", LOG_LOCAL3 },
{ "local4", LOG_LOCAL4 },
{ "local5", LOG_LOCAL5 },
{ "local6", LOG_LOCAL6 },
{ "local7", LOG_LOCAL7 },
{ NULL, -1 }
};
#endif
/*
* arguments to setlogmask.
*/
#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
/*
* Option flags for openlog.
*
* LOG_ODELAY no longer does anything.
* LOG_NDELAY is the inverse of what it used to be.
*/
#define LOG_PID 0x01 /* log the pid with each message */
#define LOG_CONS 0x02 /* log on the console if errors in sending */
#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */
#define LOG_NDELAY 0x08 /* don't delay open */
#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */
#define LOG_PERROR 0x20 /* log to stderr as well */
#endif /* sys/syslog.h */

View File

@ -84,6 +84,10 @@
#include "libbb.h"
#include "reboot.h"
#ifdef __BIONIC__
#include "reboot.c"
#endif
#if ENABLE_FEATURE_WTMP
#include <sys/utsname.h>
@ -153,6 +157,29 @@ int halt_main(int argc UNUSED_PARAM, char **argv)
if (!(flags & 2)) /* no -n */
sync();
#ifdef __BIONIC__
char *mode[4];
int c = 1;
mode[0] = strdup("reboot");
mode[1] = mode[2] = mode[3] = NULL;
switch (which) {
case 0:
case 1:
//-p for halt
mode[1] = strdup("-p");
c = 2;
break;
case 2:
//reboot
if (argc > 1) {
mode[1] = strdup(argv[1]);
c = 2;
}
break;
}
return reboot_android(c, mode);
#endif
/* Perform action. */
rc = 1;
if (!(flags & 4)) { /* no -f */

View File

@ -1094,7 +1094,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
/* Make sure environs is set to something sane */
putenv((char *) "HOME=/");
putenv((char *) bb_PATH_root_path);
putenv((char *) "SHELL=/bin/sh");
putenv((char *) "SHELL=/sbin/sh");
putenv((char *) "USER=root"); /* needed? why? */
if (argv[1])

33
init/reboot.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int reboot_android(int argc, char *argv[])
{
int ret;
const char* restart_cmd = NULL;
char* prop_value;
char* prop_cmd;
restart_cmd = "reboot";
while (true) {
int c = getopt(argc, argv, "p");
if (c == EOF)
break;
switch (c) {
case 'p':
restart_cmd = "shutdown";
break;
}
}
if (argc > optind)
asprintf(&prop_value, "%s,%s", restart_cmd, argv[optind]);
else
asprintf(&prop_value, "%s", restart_cmd);
asprintf(&prop_cmd, "setprop sys.powerctl %s", prop_value);
ret = execlp("sh", "sh", "-c", prop_cmd, NULL);
return ret;
}

View File

@ -114,6 +114,9 @@ lib-y += xgethostbyname.o
lib-y += xreadlink.o
lib-y += xrealloc_vector.o
# for android-busybox-ndk
lib-y += mntent_r.o
lib-$(CONFIG_PLATFORM_LINUX) += match_fstype.o
lib-$(CONFIG_FEATURE_UTMP) += utmp.o

View File

@ -10,6 +10,50 @@
#include <sys/syscall.h>
#include "libbb.h"
#ifndef __NR_shmget
#define __NR_shmget 29
#endif
#ifndef __NR_shmat
#define __NR_shmat 30
#endif
#ifndef __NR_shmctl
#define __NR_shmctl 31
#endif
#ifndef __NR_semget
#define __NR_semget 64
#endif
#ifndef __NR_semop
#define __NR_semop 65
#endif
#ifndef __NR_semctl
#define __NR_semctl 66
#endif
#ifndef __NR_shmdt
#define __NR_shmdt 67
#endif
#ifndef __NR_msgget
#define __NR_msgget 68
#endif
#ifndef __NR_msgsnd
#define __NR_msgsnd 69
#endif
#ifndef __NR_msgrcv
#define __NR_msgrcv 70
#endif
#ifndef __NR_msgctl
#define __NR_msgctl 71
#endif
#if defined(ANDROID) || defined(__ANDROID__)
pid_t getsid(pid_t pid)
{
@ -40,6 +84,60 @@ int pivot_root(const char *new_root, const char *put_old)
return syscall(__NR_pivot_root, new_root, put_old);
}
int swapoff(const char *path)
{
return syscall(__NR_swapoff, path);
}
int swapon(const char *path, int swapflags)
{
return syscall(__NR_swapon, path, swapflags);
}
int shmget(key_t key, size_t size, int shmflg)
{
return syscall(__NR_shmget, key, size, shmflg);
}
int shmdt(const void *shmaddr)
{
return syscall(__NR_shmdt, shmaddr);
}
void *shmat(int shmid, const void *shmaddr, int shmflg)
{
return (void *)syscall(__NR_shmat, shmid, shmaddr, shmflg);
}
int msgget(key_t key, int msgflg)
{
return syscall(__NR_msgget, key, msgflg);
}
int semget(key_t key, int nsems, int semflg)
{
return syscall(__NR_semget, key, nsems, semflg);
}
struct msqid_ds; /* #include <linux/msg.h> */
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
{
return syscall(__NR_msgctl, msqid, cmd, buf);
}
struct shmid_ds; /* #include <linux/shm.h> */
// NOTE: IPC_INFO takes a struct shminfo64
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
{
return syscall(__NR_shmctl, shmid, cmd, buf);
}
struct sembuf; /* #include <linux/sem.h> */
int semop(int semid, struct sembuf *sops, unsigned nsops)
{
return syscall(__NR_semop, semid, sops, nsops);
}
# if __ANDROID_API__ < 21
int tcdrain(int fd)
{

288
libbb/mntent_r.c Normal file
View File

@ -0,0 +1,288 @@
/* Utilities for reading/writing fstab, mtab, etc.
Copyright (C) 1995-2000, 2001, 2002, 2003, 2006, 2010, 2011
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
// file extracted from patch 'Bionic Patch V1.0 (Vitaly Greck)':
// https://busybox-android.googlecode.com/files/patch
//
// looks like its based on misc/mntent_r.c from glibc,
// contains all fixes in current master (2012-03-19),
// but is not source identical (mostly stuff removed)
// using the upstream one fails to build
#include <alloca.h>
#include <mntent.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
/* Prepare to begin reading and/or writing mount table entries from the
beginning of FILE. MODE is as for `fopen'. */
FILE *setmntent (const char *file, const char *mode)
{
/* Extend the mode parameter with "c" to disable cancellation in the
I/O functions and "e" to set FD_CLOEXEC. */
size_t modelen = strlen (mode);
char newmode[modelen + 3];
memcpy (newmode, mode, modelen);
memcpy (newmode + modelen, "ce", 3);
FILE *result = fopen (file, newmode);
return result;
}
/* Close a stream opened with `setmntent'. */
int endmntent (FILE *stream)
{
if (stream) /* SunOS 4.x allows for NULL stream */
fclose (stream);
return 1; /* SunOS 4.x says to always return 1 */
}
/* Since the values in a line are separated by spaces, a name cannot
contain a space. Therefore some programs encode spaces in names
by the strings "\040". We undo the encoding when reading an entry.
The decoding happens in place. */
static char *
decode_name (char *buf)
{
char *rp = buf;
char *wp = buf;
do
if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0')
{
/* \040 is a SPACE. */
*wp++ = ' ';
rp += 3;
}
else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '1')
{
/* \011 is a TAB. */
*wp++ = '\t';
rp += 3;
}
else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
{
/* \012 is a NEWLINE. */
*wp++ = '\n';
rp += 3;
}
else if (rp[0] == '\\' && rp[1] == '\\')
{
/* We have to escape \\ to be able to represent all characters. */
*wp++ = '\\';
rp += 1;
}
else if (rp[0] == '\\' && rp[1] == '1' && rp[2] == '3' && rp[3] == '4')
{
/* \134 is also \\. */
*wp++ = '\\';
rp += 3;
}
else
*wp++ = *rp;
while (*rp++ != '\0');
return buf;
}
/* Read one mount table entry from STREAM. Returns a pointer to storage
reused on the next call, or null for EOF or error (use feof/ferror to
check). */
struct mntent *getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
{
char *cp;
char *head;
do
{
char *end_ptr;
if (fgets (buffer, bufsiz, stream) == NULL)
{
return NULL;
}
end_ptr = strchr (buffer, '\n');
if (end_ptr != NULL) /* chop newline */
*end_ptr = '\0';
else
{
/* Not the whole line was read. Do it now but forget it. */
char tmp[1024];
while (fgets (tmp, sizeof tmp, stream) != NULL)
if (strchr (tmp, '\n') != NULL)
break;
}
head = buffer + strspn (buffer, " \t");
/* skip empty lines and comment lines: */
}
while (head[0] == '\0' || head[0] == '#');
cp = strsep (&head, " \t");
mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
if (head)
head += strspn (head, " \t");
cp = strsep (&head, " \t");
mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
if (head)
head += strspn (head, " \t");
cp = strsep (&head, " \t");
mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
if (head)
head += strspn (head, " \t");
cp = strsep (&head, " \t");
mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
{
case 0:
mp->mnt_freq = 0;
case 1:
mp->mnt_passno = 0;
case 2:
break;
}
return mp;
}
struct mntent *getmntent (FILE *stream)
{
static struct mntent m;
static char *getmntent_buffer;
#define BUFFER_SIZE 4096
if (getmntent_buffer == NULL) {
getmntent_buffer = (char *) malloc (BUFFER_SIZE);
}
return getmntent_r (stream, &m, getmntent_buffer, BUFFER_SIZE);
#undef BUFFER_SIZE
}
/* We have to use an encoding for names if they contain spaces or tabs.
To be able to represent all characters we also have to escape the
backslash itself. This "function" must be a macro since we use
`alloca'. */
#define encode_name(name) \
do { \
const char *rp = name; \
\
while (*rp != '\0') \
if (*rp == ' ' || *rp == '\t' || *rp == '\n' || *rp == '\\') \
break; \
else \
++rp; \
\
if (*rp != '\0') \
{ \
/* In the worst case the length of the string can increase to \
four times the current length. */ \
char *wp; \
\
rp = name; \
name = wp = (char *) alloca (strlen (name) * 4 + 1); \
\
do \
if (*rp == ' ') \
{ \
*wp++ = '\\'; \
*wp++ = '0'; \
*wp++ = '4'; \
*wp++ = '0'; \
} \
else if (*rp == '\t') \
{ \
*wp++ = '\\'; \
*wp++ = '0'; \
*wp++ = '1'; \
*wp++ = '1'; \
} \
else if (*rp == '\n') \
{ \
*wp++ = '\\'; \
*wp++ = '0'; \
*wp++ = '1'; \
*wp++ = '2'; \
} \
else if (*rp == '\\') \
{ \
*wp++ = '\\'; \
*wp++ = '\\'; \
} \
else \
*wp++ = *rp; \
while (*rp++ != '\0'); \
} \
} while (0)
/* Write the mount table entry described by MNT to STREAM.
Return zero on success, nonzero on failure. */
int addmntent (FILE *stream, const struct mntent *mnt)
{
struct mntent mntcopy = *mnt;
if (fseek (stream, 0, SEEK_END))
return 1;
/* Encode spaces and tabs in the names. */
encode_name (mntcopy.mnt_fsname);
encode_name (mntcopy.mnt_dir);
encode_name (mntcopy.mnt_type);
encode_name (mntcopy.mnt_opts);
return (fprintf (stream, "%s %s %s %s %d %d\n",
mntcopy.mnt_fsname,
mntcopy.mnt_dir,
mntcopy.mnt_type,
mntcopy.mnt_opts,
mntcopy.mnt_freq,
mntcopy.mnt_passno) < 0
|| fflush (stream) != 0);
}
/* Search MNT->mnt_opts for an option matching OPT.
Returns the address of the substring, or null if none found. */
char *hasmntopt (const struct mntent *mnt, const char *opt)
{
const size_t optlen = strlen (opt);
char *rest = mnt->mnt_opts, *p;
while ((p = strstr (rest, opt)) != NULL)
{
if ((p == rest || p[-1] == ',')
&& (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
return p;
rest = strchr (p, ',');
if (rest == NULL)
break;
++rest;
}
return NULL;
}

View File

@ -213,3 +213,11 @@ int ttyname_r(int fd, char *buf, size_t buflen)
return 0;
}
#endif
#ifndef HAVE_ISSETUGID
int issetugid(void)
{
/* for Bionic, this is sufficient */
return 0;
}
#endif

62
libbb/semctl.c Normal file
View File

@ -0,0 +1,62 @@
/* Copyright (C) 1995,1997,1998,2000,2003,2004,2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* originally from glibc-2.14/sysdeps/unix/sysv/linux/semctl.c, modified */
// syscall used by syslogd, ipcrm, ipcs
//kbuild:lib-y += semctl.o
#include <sys/syscall.h> /* For __NR_xxx definitions */
#include <stdarg.h>
#include <linux/sem.h>
#include "libbb.h"
#ifndef __NR_semctl
#define __NR_semctl 66
#endif
/* code from GLIBC */
int semctl(int semid, int semnum, int cmd, ...) {
union semun arg;
va_list ap;
va_start (ap, cmd);
/* Get the argument only if required. */
arg.buf = NULL;
switch (cmd)
{
case SETVAL: /* arg.val */
case GETALL: /* arg.array */
case SETALL:
case IPC_STAT: /* arg.buf */
case IPC_SET:
case SEM_STAT:
case IPC_INFO: /* arg.__buf */
case SEM_INFO:
va_start (ap, cmd);
arg = va_arg (ap, union semun);
va_end (ap);
break;
}
va_end (ap);
return syscall(__NR_semctl, semid, semnum, cmd, arg);
}

View File

@ -12,6 +12,8 @@
#include <netinet/in.h>
#include <net/if.h>
#include <sys/un.h>
#include <netdb.h>
#include "../libres/dietdns.h"
#include "libbb.h"
int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval)
@ -282,7 +284,7 @@ IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
* for each possible socket type (tcp,udp,raw...): */
hint.ai_socktype = SOCK_STREAM;
hint.ai_flags = ai_flags & ~DIE_ON_ERROR;
rc = getaddrinfo(host, NULL, &hint, &result);
rc = diet_getaddrinfo(host, NULL, &hint, &result); /* hack to use dietlibc's resolver to work around static compile issue */
if (rc || !result) {
bb_error_msg("bad address '%s'", org_host);
if (ai_flags & DIE_ON_ERROR)
@ -309,7 +311,7 @@ IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
set_nport(&r->u.sa, htons(port));
ret:
if (result)
freeaddrinfo(result);
diet_freeaddrinfo(result); /* hack to use dietlibc's resolver to work around static compile issue */
return r;
}
#if !ENABLE_FEATURE_IPV6

11
libres/Kbuild.src Normal file
View File

@ -0,0 +1,11 @@
# Makefile for busybox
#
# Copyright (C) 2012-2012 by Tias Guns <tias@ulyssis.org>
#
# Licensed under GPLv2, see file LICENSE in this source tree.
lib-$(CONFIG_NSLOOKUP) += getaddrinfo.o gethostbyname2_r.o freeaddrinfo.o
lib-$(CONFIG_NSLOOKUP) += dnscruft.o dnscruft2.o dnscruft3.o
lib-$(CONFIG_NSLOOKUP) += res_init.o res_query.o res_mkquery.o
lib-$(CONFIG_NSLOOKUP) += h_errno.o gai_strerror.o
lib-$(CONFIG_NSLOOKUP) += dn_expand.o

32
libres/Makefile Normal file
View File

@ -0,0 +1,32 @@
CC=agcc
OBJECTS=getaddrinfo.o
OBJECTS+=gethostbyname2_r.o
OBJECTS+=dnscruft.o
OBJECTS+=dnscruft2.o
OBJECTS+=dnscruft3.o
OBJECTS+=h_errno.o
OBJECTS+=res_query.o
OBJECTS+=res_mkquery.o
OBJECTS+=gai_strerror.o
OBJECTS+=freeaddrinfo.o
OBJECTS+=res_init.o
OBJECTS+=dn_expand.o
CFLAGS+=-Wall
all: libres.a test
clean:
rm -f $(OBJECTS) libres.a test.o test
test: libres.a test.o
$(CC) $(CFLAGS) -o test test.o libres.a
libres.a: $(OBJECTS)
ar r libres.a $(OBJECTS)
ranlib libres.a
.PHONY: all clean
%.o: %.c dietdns.h
$(CC) $(CFLAGS) -c $<

5
libres/README Normal file
View File

@ -0,0 +1,5 @@
all these files are from dietlibc, modified to fit as a plug-in resolver
Work by Dan Drown, called libres-0.32-1
available at:
http://dan.drown.org/android/src/libres/

189
libres/dietdns.h Normal file
View File

@ -0,0 +1,189 @@
#ifndef __DIETDNS_H_
#define __DIETDNS_H_
#define DIET_MAXDNAME 1025 /* maximum domain name */
#define DIET_PACKETSZ 512
#define DIET_MAXNS 8 /* max # name servers we'll track */
#define DIET_MAXDNSRCH 6 /* max # domains in search path */
#define DIET_MAXRESOLVSORT 10 /* number of net to sort on */
struct diet_res_state {
int retrans; /* retransmission time interval */
int retry; /* number of times to retransmit */
unsigned long options; /* option flags - see below. */
int nscount; /* number of name servers */
struct sockaddr_in
nsaddr_list[DIET_MAXNS]; /* address of name server */
#define nsaddr nsaddr_list[0] /* for backward compatibility */
unsigned short id; /* current message id */
char *dnsrch[DIET_MAXDNSRCH+1]; /* components of domain to search */
char defdname[256]; /* default domain (deprecated) */
unsigned long pfcode; /* RES_PRF_ flags - see below. */
unsigned ndots:4; /* threshold for initial abs. query */
unsigned nsort:4; /* number of elements in sort_list[] */
char unused[3];
struct {
struct in_addr addr;
uint32_t mask;
} sort_list[DIET_MAXRESOLVSORT];
char pad[72];
};
/*
* Values for class field
*/
enum diet_ns_class {
diet_ns_c_invalid = 0, /* Cookie. */
diet_ns_c_in = 1, /* Internet. */
diet_ns_c_2 = 2, /* unallocated/unsupported. */
diet_ns_c_chaos = 3, /* MIT Chaos-net. */
diet_ns_c_hs = 4, /* MIT Hesiod. */
/* Query class values which do not appear in resource records */
diet_ns_c_none = 254, /* for prereq. sections in update requests */
diet_ns_c_any = 255, /* Wildcard match. */
diet_ns_c_max = 65536
};
#define DIET_C_IN diet_ns_c_in
/*
* Currently defined opcodes.
*/
enum diet_ns_opcode {
diet_ns_o_query = 0, /* Standard query. */
diet_ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */
diet_ns_o_status = 2, /* Name server status query (unsupported). */
/* Opcode 3 is undefined/reserved. */
diet_ns_o_notify = 4, /* Zone change notification. */
diet_ns_o_update = 5, /* Zone update message. */
diet_ns_o_max = 6
};
#define DIET_QUERY diet_ns_o_query
/*
* Currently defined type values for resources and queries.
*/
enum diet_ns_type {
diet_ns_t_invalid = 0, /* Cookie. */
diet_ns_t_a = 1, /* Host address. */
diet_ns_t_ns = 2, /* Authoritative server. */
diet_ns_t_md = 3, /* Mail destination. */
diet_ns_t_mf = 4, /* Mail forwarder. */
diet_ns_t_cname = 5, /* Canonical name. */
diet_ns_t_soa = 6, /* Start of authority zone. */
diet_ns_t_mb = 7, /* Mailbox domain name. */
diet_ns_t_mg = 8, /* Mail group member. */
diet_ns_t_mr = 9, /* Mail rename name. */
diet_ns_t_null = 10, /* Null resource record. */
diet_ns_t_wks = 11, /* Well known service. */
diet_ns_t_ptr = 12, /* Domain name pointer. */
diet_ns_t_hinfo = 13, /* Host information. */
diet_ns_t_minfo = 14, /* Mailbox information. */
diet_ns_t_mx = 15, /* Mail routing information. */
diet_ns_t_txt = 16, /* Text strings. */
diet_ns_t_rp = 17, /* Responsible person. */
diet_ns_t_afsdb = 18, /* AFS cell database. */
diet_ns_t_x25 = 19, /* X_25 calling address. */
diet_ns_t_isdn = 20, /* ISDN calling address. */
diet_ns_t_rt = 21, /* Router. */
diet_ns_t_nsap = 22, /* NSAP address. */
diet_ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
diet_ns_t_sig = 24, /* Security signature. */
diet_ns_t_key = 25, /* Security key. */
diet_ns_t_px = 26, /* X.400 mail mapping. */
diet_ns_t_gpos = 27, /* Geographical position (withdrawn). */
diet_ns_t_aaaa = 28, /* Ip6 Address. */
diet_ns_t_loc = 29, /* Location Information. */
diet_ns_t_nxt = 30, /* Next domain (security). */
diet_ns_t_eid = 31, /* Endpoint identifier. */
diet_ns_t_nimloc = 32, /* Nimrod Locator. */
diet_ns_t_srv = 33, /* Server Selection. */
diet_ns_t_atma = 34, /* ATM Address */
diet_ns_t_naptr = 35, /* Naming Authority PoinTeR */
diet_ns_t_kx = 36, /* Key Exchange */
diet_ns_t_cert = 37, /* Certification record */
diet_ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */
diet_ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */
diet_ns_t_sink = 40, /* Kitchen sink (experimentatl) */
diet_ns_t_opt = 41, /* EDNS0 option (meta-RR) */
diet_ns_t_tsig = 250, /* Transaction signature. */
diet_ns_t_ixfr = 251, /* Incremental zone transfer. */
diet_ns_t_axfr = 252, /* Transfer zone of authority. */
diet_ns_t_mailb = 253, /* Transfer mailbox records. */
diet_ns_t_maila = 254, /* Transfer mail agent records. */
diet_ns_t_any = 255, /* Wildcard match. */
diet_ns_t_zxfr = 256, /* BIND-specific, nonstandard. */
diet_ns_t_max = 65536
};
#define DIET_T_A diet_ns_t_a
#define DIET_T_NS diet_ns_t_ns
#define DIET_T_CNAME diet_ns_t_cname
#define DIET_T_SOA diet_ns_t_soa
#define DIET_T_PTR diet_ns_t_ptr
#define DIET_T_MX diet_ns_t_mx
#define DIET_T_TXT diet_ns_t_txt
#define DIET_T_AAAA diet_ns_t_aaaa
#define DIET_T_ANY diet_ns_t_any
/*
* Currently defined response codes.
*/
enum diet_ns_rcode {
diet_ns_r_noerror = 0, /* No error occurred. */
diet_ns_r_formerr = 1, /* Format error. */
diet_ns_r_servfail = 2, /* Server failure. */
diet_ns_r_nxdomain = 3, /* Name error. */
diet_ns_r_notimpl = 4, /* Unimplemented. */
diet_ns_r_refused = 5, /* Operation refused. */
/* these are for BIND_UPDATE */
diet_ns_r_yxdomain = 6, /* Name exists */
diet_ns_r_yxrrset = 7, /* RRset exists */
diet_ns_r_nxrrset = 8, /* RRset does not exist */
diet_ns_r_notauth = 9, /* Not authoritative for zone */
diet_ns_r_notzone = 10, /* Zone of record different from zone section */
diet_ns_r_max = 11,
/* The following are TSIG extended errors */
diet_ns_r_badsig = 16,
diet_ns_r_badkey = 17,
diet_ns_r_badtime = 18
};
#define DIET_NOERROR diet_ns_r_noerror
#define DIET_FORMERR diet_ns_r_formerr
#define DIET_SERVFAIL diet_ns_r_servfail
#define DIET_NXDOMAIN diet_ns_r_nxdomain
#define DIET_NOTIMP diet_ns_r_notimpl
#define DIET_REFUSED diet_ns_r_refused
#define DIET_YXDOMAIN diet_ns_r_yxdomain
#define DIET_YXRRSET diet_ns_r_yxrrset
#define DIET_NXRRSET diet_ns_r_nxrrset
#define DIET_NOTAUTH diet_ns_r_notauth
#define DIET_NOTZONE diet_ns_r_notzone
#define DIET_RES_RECURSE 0x00000040 /* recursion desired */
extern struct diet_res_state _diet_res;
extern int diet_h_errno;
int __dns_gethostbyx_r(const char* name, struct hostent* result,
char *buf, size_t buflen,
struct hostent **RESULT, int *h_errnop, int lookfor);
int diet_gethostbyname2_r(const char* name, int AF, struct hostent* result,
char *buf, size_t buflen,
struct hostent **RESULT, int *h_errnop);
int diet_res_query(const char *dname, int class, int type, unsigned char *answer, int anslen);
int diet_res_mkquery(int op, const char *dname, int class, int type, char* data,
int datalen, const unsigned char* newrr, char* buf, int buflen);
const char* diet_gai_strerror(int error);
int diet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
void diet_freeaddrinfo(struct addrinfo *res);
int diet_res_init(void);
int diet_dn_expand(const unsigned char *msg, const unsigned char *eomorig, const unsigned char *comp_dn, unsigned char *exp_dn, int length);
#endif

12
libres/dn_expand.c Normal file
View File

@ -0,0 +1,12 @@
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
#include "dietdns.h"
extern int __dns_decodename(const unsigned char *packet,unsigned int ofs,unsigned char *dest,
unsigned int maxlen,const unsigned char* behindpacket);
int diet_dn_expand(const unsigned char *msg, const unsigned char *eomorig, const unsigned char *comp_dn, unsigned char *exp_dn, int length) {
return __dns_decodename(msg,comp_dn-msg,exp_dn,length,eomorig)-(comp_dn-msg);
}

134
libres/dnscruft.c Normal file
View File

@ -0,0 +1,134 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <resolv.h>
#include <net/if.h>
#include <netdb.h>
#include "dietdns.h"
#ifdef __BIONIC__
#include <sys/system_properties.h>
#endif
/* needs:
* _res
*/
int __dns_fd=-1;
/* the ad-hoc internal API from hell ;-) */
void __dns_make_fd(void);
void __dns_make_fd6(void);
void __dns_readstartfiles(void);
int __dns_decodename(const unsigned char *packet,unsigned int offset,unsigned char *dest,
unsigned int maxlen,const unsigned char* behindpacket);
void __dns_make_fd(void) {
int tmp;
struct sockaddr_in si;
if (__dns_fd>=0) return;
tmp=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (tmp<0) return;
fcntl(tmp,F_SETFD,FD_CLOEXEC);
si.sin_family=AF_INET;
si.sin_port=0;
si.sin_addr.s_addr=INADDR_ANY;
if (bind(tmp,(struct sockaddr*)&si,sizeof(si))) return;
__dns_fd=tmp;
}
static int parsesockaddr(const char* c,void* x) {
struct sockaddr_in to;
if (inet_aton(c,&to.sin_addr)) {
to.sin_port=htons(53);
to.sin_family=AF_INET;
memmove(x,&to,sizeof(struct sockaddr_in));
return 1;
}
return 0;
}
#define MAX_DNS_PROPERTIES 8
#define DNS_PROP_NAME_PREFIX "net.dns"
void __dns_readstartfiles(void) {
#ifdef __BIONIC__
char propvalue[PROP_VALUE_MAX];
char propname[PROP_NAME_MAX];
char propcmd[PROP_NAME_MAX+8];
char pbuf[256];
FILE *fp;
int i;
#endif
if (_diet_res.nscount>0)
return;
_diet_res.options=DIET_RES_RECURSE;
#ifdef __BIONIC__
for(i = 1; i <= MAX_DNS_PROPERTIES; i++) {
snprintf(propname, sizeof(propname), "%s%d", DNS_PROP_NAME_PREFIX, i);
if(__system_property_get(propname, propvalue) < 1) {
/* attempt to get the property via command instead since the call to Bionic libc failed */
snprintf(propcmd, sizeof(propcmd), "getprop %s", propname);
if((fp = popen(propcmd, "r"))) {
if((fgets(pbuf, sizeof(pbuf)-1, fp) != NULL) && (strlen(pbuf) > 0)) {
if (pbuf[strlen(pbuf)-1] == '\n')
pbuf[strlen(pbuf)-1] = '\0'; /* strip trailing newline */
strncpy(propvalue, pbuf, sizeof(propvalue));
}
}
pclose(fp);
memset(&propname[0], 0, sizeof(propname)); /* clear propname to avoid unpredictable behavior */
if(strlen(propvalue) < 1)
strcpy(propvalue, "8.8.8.8"); /* use a fallback nameserver since we still fail to get the property correctly */
}
if (parsesockaddr(propvalue,&_diet_res.nsaddr_list[_diet_res.nscount]))
if (_diet_res.nscount<DIET_MAXNS)
++_diet_res.nscount;
}
#else
/* testing */
parsesockaddr("127.0.0.1",&_diet_res.nsaddr_list[_diet_res.nscount]);
++_diet_res.nscount;
#endif
}
/* return length of decoded data or -1 */
int __dns_decodename(const unsigned char *packet,unsigned int offset,unsigned char *dest,
unsigned int maxlen,const unsigned char* behindpacket) {
const unsigned char *tmp;
const unsigned char *max=dest+maxlen;
const unsigned char *after=packet+offset;
int ok=0;
for (tmp=after; maxlen>0&&*tmp; ) {
if (tmp>=behindpacket) return -1;
if ((*tmp>>6)==3) { /* goofy DNS decompression */
unsigned int ofs=((unsigned int)(*tmp&0x3f)<<8)|*(tmp+1);
if (ofs>=(unsigned int)offset) return -1; /* RFC1035: "pointer to a _prior_ occurrance" */
if (after<tmp+2) after=tmp+2;
tmp=packet+ofs;
ok=0;
} else {
unsigned int duh;
if (dest+*tmp+1>max) return -1;
if (tmp+*tmp+1>=behindpacket) return -1;
for (duh=*tmp; duh>0; --duh)
*dest++=*++tmp;
*dest++='.'; ok=1;
++tmp;
if (tmp>after) { after=tmp; if (!*tmp) ++after; }
}
}
if (ok) --dest;
*dest=0;
return after-packet;
}

132
libres/dnscruft2.c Normal file
View File

@ -0,0 +1,132 @@
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "dietdns.h"
/* needs:
* __dns_decodename
* res_query
*/
extern int __dns_decodename(unsigned char *packet,unsigned int offset,unsigned char *dest,
unsigned int maxlen,unsigned char* behindpacket);
/* Oh boy, this interface sucks so badly, there are no words for it.
* Not one, not two, but _three_ error signalling methods! (*h_errnop
* nonzero? return value nonzero? *RESULT zero?) The glibc goons
* really outdid themselves with this one. */
int __dns_gethostbyx_r(const char* name, struct hostent* result,
char *buf, size_t buflen,
struct hostent **RESULT, int *h_errnop, int lookfor) {
int names,ips;
char *cur;
char *max;
char inpkg[1500];
char* tmp;
int size;
if (lookfor==1) {
result->h_addrtype=AF_INET;
result->h_length=4;
} else {
result->h_addrtype=AF_INET6;
result->h_length=16;
}
result->h_aliases=(char**)(buf+8*sizeof(char*));
result->h_addr_list=(char**)buf;
result->h_aliases[0]=0;
cur=buf+16*sizeof(char*);
max=buf+buflen;
names=ips=0;
if ((size=diet_res_query(name,DIET_C_IN,lookfor,(unsigned char*)inpkg,512))<0) {
invalidpacket:
*h_errnop=HOST_NOT_FOUND;
return -1;
}
{
tmp=inpkg+12;
{
unsigned char Name[257];
unsigned short q=((unsigned short)inpkg[4]<<8)+inpkg[5];
while (q>0) {
if (tmp>(char*)inpkg+size) goto invalidpacket;
while (*tmp) { tmp+=*tmp+1; if (tmp>(char*)inpkg+size) goto invalidpacket; }
tmp+=5;
--q;
}
if (tmp>inpkg+size) goto invalidpacket;
q=((unsigned short)inpkg[6]<<8)+inpkg[7];
if (q<1) goto nodata;
while (q>0) {
int decofs=__dns_decodename((unsigned char*)inpkg,(size_t)(tmp-(char*)inpkg),Name,256,(unsigned char*)inpkg+size);
if (decofs<0) break;
tmp=inpkg+decofs;
--q;
if (tmp[0]!=0 || tmp[1]!=lookfor || /* TYPE != A */
tmp[2]!=0 || tmp[3]!=1) { /* CLASS != IN */
if (tmp[1]==5) { /* CNAME */
tmp+=10;
decofs=__dns_decodename((unsigned char*)inpkg,(size_t)(tmp-(char*)inpkg),Name,256,(unsigned char*)inpkg+size);
if (decofs<0) break;
tmp=inpkg+decofs;
} else
break;
continue;
}
tmp+=10; /* skip type, class, TTL and length */
{
int slen;
if (lookfor==1 || lookfor==28) /* A or AAAA*/ {
slen=strlen((char*)Name);
if (cur+slen+8+(lookfor==28?12:0)>=max) { *h_errnop=NO_RECOVERY; return -1; }
} else {
if (lookfor==12) /* PTR */ {
decofs=__dns_decodename((unsigned char*)inpkg,(size_t)(tmp-(char*)inpkg),Name,256,(unsigned char*)inpkg+size);
if (decofs<0) break;
tmp=inpkg+decofs;
}
slen=strlen((char*)Name);
}
strcpy(cur,(char*)Name);
if (names==0)
result->h_name=cur;
else
result->h_aliases[names-1]=cur;
result->h_aliases[names]=0;
if (names<8) ++names;
/* cur+=slen+1; */
cur+=(slen|3)+1;
result->h_addr_list[ips++] = cur;
if (lookfor==1) /* A */ {
memcpy(cur,tmp,4);
cur+=4; tmp+=4;
result->h_addr_list[ips]=0;
} else if (lookfor==28) /* AAAA */ {
memcpy(cur,tmp,16);
cur+=16; tmp+=16;
result->h_addr_list[ips]=0;
}
}
/* puts(Name); */
}
}
}
if (!names) {
nodata:
*h_errnop=NO_DATA;
return -1;
}
*h_errnop=0;
*RESULT=result;
return 0;
}

6
libres/dnscruft3.c Normal file
View File

@ -0,0 +1,6 @@
#include <netinet/in.h>
#include <resolv.h>
#include <netdb.h>
#include "dietdns.h"
struct diet_res_state _diet_res; /* don't ask. */

14
libres/freeaddrinfo.c Normal file
View File

@ -0,0 +1,14 @@
#include <sys/socket.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include "dietdns.h"
void diet_freeaddrinfo(struct addrinfo *res) {
while (res) {
struct addrinfo *duh;
duh=res;
res=res->ai_next;
free(duh);
}
}

14
libres/gai_strerror.c Normal file
View File

@ -0,0 +1,14 @@
#include <sys/socket.h>
#include <netdb.h>
const char* diet_gai_strerror(int error) {
switch (error) {
case EAI_FAMILY: return "family not supported";
case EAI_SOCKTYPE: return "socket type not supported";
case EAI_NONAME: return "unknown host";
case EAI_SERVICE: return "unknown service";
case EAI_MEMORY: return "memory allocation failure";
case EAI_AGAIN: return "temporary failure";
}
return "DNS error. Sorry.";
}

137
libres/getaddrinfo.c Normal file
View File

@ -0,0 +1,137 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <net/if.h>
#include <arpa/inet.h>
#include "dietdns.h"
/* XXX TODO FIXME */
/* needs:
* gethostbyname2_r
*/
int diet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
struct addrinfo **tmp;
int family;
tmp=res; *res=0;
if (hints) {
if (hints->ai_family && hints->ai_family != PF_INET6 && hints->ai_family != PF_INET) return EAI_FAMILY;
if (hints->ai_socktype && hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM) return EAI_SOCKTYPE;
}
for (family=PF_INET6; ; family=PF_INET) {
if (!hints || hints->ai_family==family || hints->ai_family==AF_UNSPEC) { /* IPv6 addresses are OK */
struct hostent h;
struct hostent *H;
int herrno=0;
char buf[4096];
int lookupok=0, i;
char* interface;
h.h_addr_list=(char**)buf+16;
h.h_addr_list[1]=0;
if (node) {
if ((interface=strchr(node,'%'))) ++interface;
if (family==PF_INET6 && inet_pton(AF_INET,node,buf)) continue;
if (inet_pton(family,node,buf)>0) {
h.h_name=(char*)node;
h.h_addr_list[0]=buf;
lookupok=1;
} else if ((!hints || !(hints->ai_flags&AI_NUMERICHOST)) &&
!diet_gethostbyname2_r(node,family,&h,buf,4096,&H,&herrno)) {
lookupok=1;
} else {
if (herrno==TRY_AGAIN) { diet_freeaddrinfo(*res); return EAI_AGAIN; }
}
} else {
h.h_name=0;
h.h_addr_list[0]=buf;
interface=0;
memset(buf,0,16);
if (!hints || !(hints->ai_flags&AI_PASSIVE)) {
if (family==AF_INET) {
buf[0]=127; buf[3]=1;
} else
buf[15]=1;
}
lookupok=1;
}
if (lookupok) {
for (i=0; h.h_addr_list[i]; ++i) {
struct ai_v6 {
struct addrinfo ai;
union {
struct sockaddr_in6 ip6;
struct sockaddr_in ip4;
} ip;
char name[1];
} *foo;
unsigned short port;
int len;
len=sizeof(struct ai_v6)+(h.h_name?strlen(h.h_name):0);
if (!(foo=malloc(len))) goto error;
foo->ai.ai_next=0;
foo->ai.ai_addrlen=family==PF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in);
foo->ai.ai_addr=(struct sockaddr*)&foo->ip;
if (family==PF_INET6) {
memset(&foo->ip,0,sizeof(foo->ip));
memmove(&foo->ip.ip6.sin6_addr,h.h_addr_list[i],16);
if (interface) foo->ip.ip6.sin6_scope_id=if_nametoindex(interface);
} else {
memmove(&foo->ip.ip4.sin_addr,h.h_addr_list[i],4);
}
foo->ip.ip6.sin6_family=foo->ai.ai_family=family;
if (h.h_name) {
foo->ai.ai_canonname=foo->name;
memmove(foo->name,h.h_name,strlen(h.h_name)+1);
} else
foo->ai.ai_canonname=0;
for (foo->ai.ai_socktype=SOCK_STREAM; ; foo->ai.ai_socktype=SOCK_DGRAM) {
char* type,* x;
if (foo->ai.ai_socktype==SOCK_STREAM) { /* TCP */
if (hints && hints->ai_socktype==SOCK_DGRAM) continue;
foo->ai.ai_protocol=IPPROTO_TCP;
type="tcp";
} else { /* UDP */
if (hints && hints->ai_socktype==SOCK_STREAM) break;
foo->ai.ai_protocol=IPPROTO_UDP;
type="udp";
}
port=htons(strtol(service?service:"0",&x,0));
if (*x) { /* service is not numeric :-( */
free(foo);
/* no getservbyname on android */
diet_freeaddrinfo(*res);
return EAI_SERVICE;
}
if (family==PF_INET6)
foo->ip.ip6.sin6_port=port;
else
foo->ip.ip4.sin_port=port;
if (!*tmp) *tmp=&(foo->ai); else (*tmp)->ai_next=&(foo->ai);
if (!(foo=malloc(len))) goto error;
memmove(foo,*tmp,len);
tmp=&(*tmp)->ai_next;
foo->ai.ai_addr=(struct sockaddr*)&foo->ip;
if (foo->ai.ai_canonname)
foo->ai.ai_canonname=foo->name;
if (foo->ai.ai_socktype==SOCK_DGRAM) break;
}
free(foo);
}
}
}
if (family==PF_INET) break;
}
if (*res==0) return EAI_NONAME; /* kludge kludge... */
return 0;
error:
diet_freeaddrinfo(*res);
return EAI_MEMORY;
}

35
libres/gethostbyname2_r.c Normal file
View File

@ -0,0 +1,35 @@
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include "dietdns.h"
/* needs:
* __dns_gethostbyx_r
*/
/* Oh boy, this interface sucks so badly, there are no words for it.
* Not one, not two, but _three_ error signalling methods! (*h_errnop
* nonzero? return value nonzero? *RESULT zero?) The glibc goons
* really outdid themselves with this one. */
int diet_gethostbyname2_r(const char* name, int AF, struct hostent* result,
char *buf, size_t buflen,
struct hostent **RESULT, int *h_errnop) {
size_t L=strlen(name);
int lookfor=0;
switch (AF) {
case AF_INET: lookfor=1; break;
case AF_INET6: lookfor=28; break;
default: *h_errnop=EINVAL; return 1;
}
result->h_name=buf;
if (buflen<L) { *h_errnop=ERANGE; return 1; }
strcpy(buf,name);
return __dns_gethostbyx_r(name,result,buf+L,buflen-L,RESULT,h_errnop,lookfor);
}

1
libres/h_errno.c Normal file
View File

@ -0,0 +1 @@
int diet_h_errno;

12
libres/res_init.c Normal file
View File

@ -0,0 +1,12 @@
#include <resolv.h>
#include <netdb.h>
#include <netinet/in.h>
#include "dietdns.h"
extern void __dns_readstartfiles(void);
int diet_res_init(void) {
_diet_res.nscount=0;
__dns_readstartfiles();
return 0;
}

85
libres/res_mkquery.c Normal file
View File

@ -0,0 +1,85 @@
#include <resolv.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/nameser.h>
#include "dietdns.h"
/* needs:
* _res
*/
static char dnspacket[]="\xfe\xfe\001\000\000\001\000\000\000\000\000\000";
/*
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/
extern void __dns_make_fd(void);
extern int __dns_fd;
extern int __dns_servers;
extern struct sockaddr __dns_server_ips[];
extern void __dns_readstartfiles(void);
int diet_res_mkquery(int op, const char *dname, int class, int type, char* data,
int datalen, const unsigned char* newrr, char* buf, int buflen) {
unsigned char packet[512];
unsigned long len;
memcpy(packet,dnspacket,12);
len=rand();
packet[0]=len;
packet[1]=len>>8;
len=0;
if ((_diet_res.options&DIET_RES_RECURSE)==0) packet[2]=0;
{
unsigned char* x;
const char* y,* tmp;
x=packet+12; y=dname;
while (*y) {
while (*y=='.') ++y;
for (tmp=y; *tmp && *tmp!='.'; ++tmp) ;
if (tmp-y > 63) return -1;
*x=tmp-y;
if (!(tmp-y)) break;
if ((len+=*x+1) > 254) return -1;
++x;
// if (x>=packet+510-(tmp-y)) { return -1; }
memmove(x,y,tmp-y);
x+=tmp-y;
if (!*tmp) {
*x=0;
break;
}
y=tmp;
}
*++x= 0; *++x= type; /* A */
*++x= 0; *++x= class; /* IN */
++x;
if (x-packet>buflen) return -1;
memmove(buf,packet,x-packet);
return x-packet;
}
}

81
libres/res_query.c Normal file
View File

@ -0,0 +1,81 @@
#include <resolv.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <poll.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/nameser.h>
#include <fcntl.h>
#include <sys/time.h>
#include "dietdns.h"
/* needs:
* __dns_fd
* __dns_make_fd
* __dns_readstartfiles
* h_errno
* diet_res_mkquery
* _res
*/
extern void __dns_make_fd(void);
extern int __dns_fd;
extern void __dns_readstartfiles(void);
int diet_res_query(const char *dname, int class, int type, unsigned char *answer, int anslen) {
unsigned char packet[512];
int size;
struct pollfd duh[2];
__dns_make_fd();
__dns_readstartfiles();
if ((size=diet_res_mkquery(DIET_QUERY,dname,class,type,0,0,0,(char*)packet,512))<0) { diet_h_errno=NO_RECOVERY; return -1; }
{
{
int i; /* current server */
int j; /* timeout count down */
struct timeval last,now;
i=0;
duh[0].events=POLLIN;
duh[0].fd=0;
last.tv_sec=0;
for (j=20; j>0; --j) {
gettimeofday(&now,0);
if (now.tv_sec-last.tv_sec>10) {
duh[0].fd=__dns_fd;
sendto(__dns_fd,packet,size,0,(struct sockaddr*)&(_diet_res.nsaddr_list[i]),sizeof(struct sockaddr));
last=now;
}
if (++i >= _diet_res.nscount) i=0;
if (poll(duh,1,1000) == 1) {
/* read and parse answer */
unsigned char inpkg[1500];
int len=read(duh[0].fd,inpkg,sizeof(inpkg));
/* header, question, answer, authority, additional */
if (inpkg[0]!=packet[0] || inpkg[1]!=packet[1]) continue; /* wrong ID */
if ((inpkg[2]&0xf9) != (_diet_res.options&DIET_RES_RECURSE?0x81:0x80)) continue; /* not answer */
if ((inpkg[3]&0x0f) != 0) {
diet_h_errno=HOST_NOT_FOUND;
return -1;
} /* error */
if (len>anslen) {
diet_h_errno=NO_RECOVERY;
return -1;
}
memcpy(answer,inpkg,len);
return len;
}
/*kaputt:*/
}
}
}
diet_h_errno=TRY_AGAIN;
return -1;
}

105
libres/test.c Normal file
View File

@ -0,0 +1,105 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/icmp6.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "dietdns.h"
union common_sockaddr {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};
typedef union common_sockaddr sockaddr_any;
static int getaddr (const char *name, sockaddr_any *addr, int af) {
int ret;
struct addrinfo hints, *ai, *res = NULL;
memset (&hints, 0, sizeof (hints));
hints.ai_family = af;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_ADDRCONFIG;
ret = diet_getaddrinfo (name, NULL, &hints, &res);
if (ret) {
fprintf (stderr, "%s: %s\n", name, diet_gai_strerror (ret));
return -1;
}
for (ai = res; ai; ai = ai->ai_next) {
if (ai->ai_family == af) break;
}
if (!ai) ai = res; /* anything... */
if (ai->ai_addrlen > sizeof (*addr))
return -1; /* paranoia */
memcpy (addr, ai->ai_addr, ai->ai_addrlen);
if(res != NULL)
diet_freeaddrinfo (res);
return 0;
}
static void printaddr(sockaddr_any *addr) {
char addr_str[INET6_ADDRSTRLEN];
if(addr->sa.sa_family == AF_INET) {
printf("family = AF_INET\n");
if(inet_ntop(addr->sin.sin_family, &addr->sin.sin_addr, (char *)&addr_str, sizeof(addr_str)) == NULL) {
perror("inet_ntop failed");
return;
}
printf("addr = %s\n", addr_str);
} else if(addr->sa.sa_family == AF_INET6) {
printf("family = AF_INET6\n");
if(inet_ntop(addr->sin6.sin6_family, &addr->sin6.sin6_addr, (char *)&addr_str, sizeof(addr_str)) == NULL) {
perror("inet_ntop failed");
return;
}
printf("addr = %s\n", addr_str);
} else {
printf("unknown family = %d\n",addr->sa.sa_family);
}
}
int main() {
sockaddr_any dst_addr = {{ 0, }, };
struct sockaddr_in lsa_u;
if (getaddr("www.datapipe.net", &dst_addr, AF_INET) < 0) {
fprintf(stderr, "getaddr failed\n");
} else {
printaddr(&dst_addr);
}
if (getaddr("www.datapipe.net", &dst_addr, AF_INET6) < 0) {
fprintf(stderr, "getaddr failed\n");
} else {
printaddr(&dst_addr);
}
inet_aton("127.0.0.1",&lsa_u.sin_addr);
lsa_u.sin_port=htons(53);
lsa_u.sin_family=AF_INET;
_diet_res.nscount = 1;
_diet_res.nsaddr_list[0] = lsa_u;
if (getaddr("www.datapipe.net", &dst_addr, AF_INET6) < 0) {
fprintf(stderr, "getaddr failed\n");
} else {
printaddr(&dst_addr);
}
return 0;
}

View File

@ -49,7 +49,10 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA
image = xmalloc_open_zipped_read_close(fname, &len);
e = moddb_get_or_create(modules, bb_get_last_path_component_nostrip(fname));
e->name = xstrdup(fname + 2); /* skip "./" */
if (strncmp(fname, "./", 2) == 0)
e->name = xstrdup(fname + 2);
else
e->name = xstrdup(fname);
for (ptr = image; ptr < image + len - 10; ptr++) {
if (is_prefixed_with(ptr, "depends=")) {

View File

@ -21,6 +21,10 @@
#include "libbb.h"
#include "modutils.h"
#if defined(ANDROID) || defined(__ANDROID__)
#define DONT_USE_UTS_REL_FOLDER
#endif
static const char *const shortcuts[] = {
"filename", // -n
"author", // -a
@ -64,7 +68,7 @@ static void modinfo(const char *path, const char *version,
{
size_t len;
int j;
char *ptr, *the_module;
char *ptr, *fullpath, *the_module;
char *allocated;
int tags = option_mask32;
@ -75,8 +79,14 @@ static void modinfo(const char *path, const char *version,
if (path[0] == '/')
return;
/* Newer depmod puts relative paths in modules.dep */
path = allocated = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
the_module = xmalloc_open_zipped_read_close(path, &len);
fullpath = allocated = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
the_module = xmalloc_open_zipped_read_close(fullpath, &len);
#ifdef DONT_USE_UTS_REL_FOLDER
if (!the_module) {
fullpath = allocated = xasprintf("%s/%s", CONFIG_DEFAULT_MODULES_DIR, path);
the_module = xmalloc_open_zipped_read_close(fullpath, &len);
}
#endif
if (!the_module) {
bb_error_msg("module '%s' not found", path);
goto ret;
@ -158,9 +168,23 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
uname(&uts);
parser = config_open2(
xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, uts.release, CONFIG_DEFAULT_DEPMOD_FILE),
xfopen_for_read
fopen_for_read
);
#ifdef DONT_USE_UTS_REL_FOLDER
if (!parser) {
parser = config_open2(
xasprintf("%s/%s", CONFIG_DEFAULT_MODULES_DIR, CONFIG_DEFAULT_DEPMOD_FILE),
fopen_for_read
);
}
if (!parser) {
strcpy(uts.release,"");
goto no_modules_dep;
}
#endif
while (config_read(parser, tokens, 2, 1, "# \t", PARSE_NORMAL)) {
colon = last_char_is(tokens[0], ':');
if (colon == NULL)
@ -177,6 +201,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
if (ENABLE_FEATURE_CLEAN_UP)
config_close(parser);
no_modules_dep:
for (i = 0; argv[i]; i++) {
if (argv[i][0]) {
modinfo(argv[i], uts.release, field);

View File

@ -173,6 +173,10 @@ static const char modprobe_longopts[] ALIGN1 =
#define MODULE_FLAG_BLACKLISTED 0x0008
#define MODULE_FLAG_BUILTIN 0x0010
#if defined(ANDROID) || defined(__ANDROID__)
#define DONT_USE_UTS_REL_FOLDER
#endif
struct globals {
llist_t *probes; /* MEs of module(s) requested on cmdline */
#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
@ -478,10 +482,17 @@ static int do_modprobe(struct module_entry *m)
#endif
if (option_mask32 & OPT_SHOW_DEPS) {
#ifndef DONT_USE_UTS_REL_FOLDER
printf(options ? "insmod %s/%s/%s %s\n"
: "insmod %s/%s/%s\n",
CONFIG_DEFAULT_MODULES_DIR, G.uts.release, fn,
options);
#else
printf(options ? "insmod %s/%s %s\n"
: "insmod %s/%s\n",
CONFIG_DEFAULT_MODULES_DIR, fn,
options);
#endif
free(options);
continue;
}
@ -563,6 +574,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
int rc;
unsigned opt;
struct module_entry *me;
struct stat info;
INIT_G();
@ -573,8 +585,12 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
/* Goto modules location */
xchdir(CONFIG_DEFAULT_MODULES_DIR);
#ifndef DONT_USE_UTS_REL_FOLDER
uname(&G.uts);
xchdir(G.uts.release);
if (stat(G.uts.release, &info) == 0) {
xchdir(G.uts.release);
}
#endif
if (opt & OPT_LIST_ONLY) {
int i;

View File

@ -37,6 +37,7 @@
#include <net/if.h>
#include <netinet/ether.h>
#include <netpacket/packet.h>
#include <linux/if_arp.h> /* for arphdr */
#include "libbb.h"
#include "common_bufsiz.h"

View File

@ -130,12 +130,14 @@
#endif
#if ENABLE_FEATURE_IPV6
#ifndef __BIONIC__
struct in6_ifreq {
struct in6_addr ifr6_addr;
uint32_t ifr6_prefixlen;
int ifr6_ifindex;
};
#endif
#endif
/*
* Here are the bit masks for the "flags" member of struct options below.

View File

@ -56,6 +56,7 @@
#ifdef HAVE_AFINET6
# ifndef _LINUX_IN6_H
# ifndef __BIONIC__
/*
* This is from linux/include/net/ipv6.h
*/
@ -64,6 +65,7 @@ struct in6_ifreq {
uint32_t ifr6_prefixlen;
unsigned int ifr6_ifindex;
};
# endif
# endif
#endif /* HAVE_AFINET6 */

View File

@ -35,6 +35,9 @@
//usage: "Address: 127.0.0.1\n"
#include <resolv.h>
#include <netinet/in.h>
#include <netdb.h>
#include "../libres/dietdns.h"
#include "libbb.h"
/*
@ -87,7 +90,7 @@ static int print_host(const char *hostname, const char *header)
* for each possible socket type (tcp,udp,raw...): */
hint.ai_socktype = SOCK_STREAM;
// hint.ai_flags = AI_CANONNAME;
rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result);
rc = diet_getaddrinfo(hostname, NULL /*service*/, &hint, &result);
if (rc == 0) {
struct addrinfo *cur = result;
@ -118,7 +121,7 @@ static int print_host(const char *hostname, const char *header)
#endif
}
if (ENABLE_FEATURE_CLEAN_UP && result)
freeaddrinfo(result);
diet_freeaddrinfo(result);
return (rc != 0);
}
@ -128,11 +131,11 @@ static void server_print(void)
char *server;
struct sockaddr *sa;
#if ENABLE_FEATURE_IPV6
sa = (struct sockaddr*)_res._u._ext.nsaddrs[0];
#if 0
sa = (struct sockaddr*)_diet_res._u._ext.nsaddrs[0];
if (!sa)
#endif
sa = (struct sockaddr*)&_res.nsaddr_list[0];
sa = (struct sockaddr*)&_diet_res.nsaddr_list[0];
server = xmalloc_sockaddr2dotted_noport(sa);
print_host(server, "Server:");
@ -154,11 +157,11 @@ static void set_default_dns(const char *server)
lsa = xhost2sockaddr(server, 53);
if (lsa->u.sa.sa_family == AF_INET) {
_res.nscount = 1;
_diet_res.nscount = 1;
/* struct copy */
_res.nsaddr_list[0] = lsa->u.sin;
_diet_res.nsaddr_list[0] = lsa->u.sin;
}
#if ENABLE_FEATURE_IPV6
#if 0
/* Hoped libc can cope with IPv4 address there too.
* No such luck, glibc 2.4 segfaults even with IPv6,
* maybe I misunderstand how to make glibc use IPv6 addr?
@ -167,9 +170,9 @@ static void set_default_dns(const char *server)
// glibc neither SEGVs nor sends any dgrams with this
// (strace shows no socket ops):
//_res.nscount = 0;
_res._u._ext.nscount = 1;
_diet_res._u._ext.nscount = 1;
/* store a pointer to part of malloc'ed lsa */
_res._u._ext.nsaddrs[0] = &lsa->u.sin6;
_diet_res._u._ext.nsaddrs[0] = &lsa->u.sin6;
/* must not free(lsa)! */
}
#endif
@ -188,7 +191,7 @@ int nslookup_main(int argc, char **argv)
/* initialize DNS structure _res used in printing the default
* name server and in the explicit name server option feature. */
res_init();
diet_res_init();
/* rfc2133 says this enables IPv6 lookups */
/* (but it also says "may be enabled in /etc/resolv.conf") */
/*_res.options |= RES_USE_INET6;*/

View File

@ -43,8 +43,11 @@
//usage: "\n -e Display other/more information"
//usage: "\n -A inet" IF_FEATURE_IPV6("{6}") " Select address family"
#include <netinet/in.h>
#include <net/route.h>
#include <net/if.h>
#include <linux/in6.h>
#include <linux/ipv6_route.h>
#include "libbb.h"
#include "inet_common.h"

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)if_ether.h 8.3 (Berkeley) 5/2/95
* $FreeBSD$
*/
#ifndef STRUCT_ETHERARP_H
#define STRUCT_ETHERARP_H 1
#include <net/if_arp.h>
/*
* Macro to map an IP multicast address to an Ethernet multicast address.
* The high-order 25 bits of the Ethernet address are statically assigned,
* and the low-order 23 bits are taken from the low end of the IP address.
*/
#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \
/* struct in_addr *ipaddr; */ \
/* u_char enaddr[ETH_ALEN]; */ \
{ \
(enaddr)[0] = 0x01; \
(enaddr)[1] = 0x00; \
(enaddr)[2] = 0x5e; \
(enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \
(enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \
(enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \
}
/*
* Ethernet Address Resolution Protocol.
*
* See RFC 826 for protocol description. Structure below is adapted
* to resolving internet addresses. Field names used correspond to
* RFC 826.
*/
struct ether_arp {
struct arphdr ea_hdr; /* fixed-size header */
u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */
u_int8_t arp_spa[4]; /* sender protocol address */
u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */
u_int8_t arp_tpa[4]; /* target protocol address */
};
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
#endif /* STRUCT_ETHERARP_H */

View File

@ -43,6 +43,7 @@
//applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP))
//kbuild:lib-$(CONFIG_UDHCPC6) += d6_dhcpc.o d6_packet.o d6_socket.o common.o socket.o signalpipe.o
//kbuild:lib-$(CONFIG_UDHCPC6) += ifaddrs.o
//kbuild:lib-$(CONFIG_FEATURE_UDHCPC6_RFC3646) += domain_codec.o
//kbuild:lib-$(CONFIG_FEATURE_UDHCPC6_RFC4704) += domain_codec.o

View File

@ -7,7 +7,7 @@
#include "common.h"
#include "d6_common.h"
#include <net/if.h>
#include <ifaddrs.h>
#include "ifaddrs.h"
#include <netpacket/packet.h>
int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_addr *nip6, uint8_t *mac)

600
networking/udhcp/ifaddrs.c Normal file
View File

@ -0,0 +1,600 @@
/*
Copyright (c) 2013, Kenneth MacKay
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ifaddrs.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
typedef struct NetlinkList
{
struct NetlinkList *m_next;
struct nlmsghdr *m_data;
unsigned int m_size;
} NetlinkList;
static int netlink_socket(void)
{
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(l_socket < 0)
{
return -1;
}
struct sockaddr_nl l_addr;
memset(&l_addr, 0, sizeof(l_addr));
l_addr.nl_family = AF_NETLINK;
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
{
close(l_socket);
return -1;
}
return l_socket;
}
static int netlink_send(int p_socket, int p_request)
{
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
memset(l_buffer, 0, sizeof(l_buffer));
struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer;
struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
l_hdr->nlmsg_type = p_request;
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
l_hdr->nlmsg_pid = 0;
l_hdr->nlmsg_seq = p_socket;
l_msg->rtgen_family = AF_UNSPEC;
struct sockaddr_nl l_addr;
memset(&l_addr, 0, sizeof(l_addr));
l_addr.nl_family = AF_NETLINK;
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
}
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
{
struct msghdr l_msg;
struct iovec l_iov = { p_buffer, p_len };
struct sockaddr_nl l_addr;
int l_result;
for(;;)
{
l_msg.msg_name = (void *)&l_addr;
l_msg.msg_namelen = sizeof(l_addr);
l_msg.msg_iov = &l_iov;
l_msg.msg_iovlen = 1;
l_msg.msg_control = NULL;
l_msg.msg_controllen = 0;
l_msg.msg_flags = 0;
int l_result = recvmsg(p_socket, &l_msg, 0);
if(l_result < 0)
{
if(errno == EINTR)
{
continue;
}
return -2;
}
if(l_msg.msg_flags & MSG_TRUNC)
{ // buffer was too small
return -1;
}
return l_result;
}
}
static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
{
size_t l_size = 4096;
void *l_buffer = NULL;
for(;;)
{
free(l_buffer);
l_buffer = malloc(l_size);
int l_read = netlink_recv(p_socket, l_buffer, l_size);
*p_size = l_read;
if(l_read == -2)
{
free(l_buffer);
return NULL;
}
if(l_read >= 0)
{
pid_t l_pid = getpid();
struct nlmsghdr *l_hdr;
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
{
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
{
continue;
}
if(l_hdr->nlmsg_type == NLMSG_DONE)
{
*p_done = 1;
break;
}
if(l_hdr->nlmsg_type == NLMSG_ERROR)
{
free(l_buffer);
return NULL;
}
}
return l_buffer;
}
l_size *= 2;
}
}
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
{
NetlinkList *l_item = malloc(sizeof(NetlinkList));
l_item->m_next = NULL;
l_item->m_data = p_data;
l_item->m_size = p_size;
return l_item;
}
static void freeResultList(NetlinkList *p_list)
{
NetlinkList *l_cur;
while(p_list)
{
l_cur = p_list;
p_list = p_list->m_next;
free(l_cur->m_data);
free(l_cur);
}
}
static NetlinkList *getResultList(int p_socket, int p_request)
{
if(netlink_send(p_socket, p_request) < 0)
{
return NULL;
}
NetlinkList *l_list = NULL;
NetlinkList *l_end = NULL;
int l_size;
int l_done = 0;
while(!l_done)
{
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
if(!l_hdr)
{ // error
freeResultList(l_list);
return NULL;
}
NetlinkList *l_item = newListItem(l_hdr, l_size);
if(!l_list)
{
l_list = l_item;
}
else
{
l_end->m_next = l_item;
}
l_end = l_item;
}
return l_list;
}
static size_t maxSize(size_t a, size_t b)
{
return (a > b ? a : b);
}
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
{
switch(p_family)
{
case AF_INET:
return sizeof(struct sockaddr_in);
case AF_INET6:
return sizeof(struct sockaddr_in6);
case AF_PACKET:
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
default:
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
}
}
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
{
switch(p_family)
{
case AF_INET:
memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
break;
case AF_INET6:
memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
break;
case AF_PACKET:
memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
break;
default:
memcpy(p_dest->sa_data, p_data, p_size);
break;
}
p_dest->sa_family = p_family;
}
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
{
if(!*p_resultList)
{
*p_resultList = p_entry;
}
else
{
struct ifaddrs *l_cur = *p_resultList;
while(l_cur->ifa_next)
{
l_cur = l_cur->ifa_next;
}
l_cur->ifa_next = p_entry;
}
}
static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
{
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
size_t l_nameSize = 0;
size_t l_addrSize = 0;
size_t l_dataSize = 0;
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
struct rtattr *l_rta;
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
void *l_rtaData = RTA_DATA(l_rta);
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type)
{
case IFLA_ADDRESS:
case IFLA_BROADCAST:
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
break;
case IFLA_IFNAME:
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
break;
case IFLA_STATS:
l_dataSize += NLMSG_ALIGN(l_rtaSize);
break;
default:
break;
}
}
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
memset(l_entry, 0, sizeof(struct ifaddrs));
l_entry->ifa_name = "";
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
char *l_addr = l_name + l_nameSize;
char *l_data = l_addr + l_addrSize;
l_entry->ifa_flags = l_info->ifi_flags;
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
void *l_rtaData = RTA_DATA(l_rta);
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type)
{
case IFLA_ADDRESS:
case IFLA_BROADCAST:
{
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
if(l_rta->rta_type == IFLA_ADDRESS)
{
l_entry->ifa_addr = (struct sockaddr *)l_addr;
}
else
{
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
}
l_addr += NLMSG_ALIGN(l_addrLen);
break;
}
case IFLA_IFNAME:
strncpy(l_name, l_rtaData, l_rtaDataSize);
l_name[l_rtaDataSize] = '\0';
l_entry->ifa_name = l_name;
break;
case IFLA_STATS:
memcpy(l_data, l_rtaData, l_rtaDataSize);
l_entry->ifa_data = l_data;
break;
default:
break;
}
}
addToEnd(p_resultList, l_entry);
p_links[l_info->ifi_index - 1] = l_entry;
}
static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
{
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
size_t l_nameSize = 0;
size_t l_addrSize = 0;
int l_addedNetmask = 0;
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
struct rtattr *l_rta;
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
void *l_rtaData = RTA_DATA(l_rta);
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
if(l_info->ifa_family == AF_PACKET)
{
continue;
}
switch(l_rta->rta_type)
{
case IFA_ADDRESS:
case IFA_LOCAL:
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
{ // make room for netmask
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
l_addedNetmask = 1;
}
case IFA_BROADCAST:
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
break;
case IFA_LABEL:
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
break;
default:
break;
}
}
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
memset(l_entry, 0, sizeof(struct ifaddrs));
l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
char *l_addr = l_name + l_nameSize;
l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
void *l_rtaData = RTA_DATA(l_rta);
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type)
{
case IFA_ADDRESS:
case IFA_BROADCAST:
case IFA_LOCAL:
{
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
if(l_info->ifa_family == AF_INET6)
{
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
{
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
}
}
if(l_rta->rta_type == IFA_ADDRESS)
{ // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
if(l_entry->ifa_addr)
{
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
}
else
{
l_entry->ifa_addr = (struct sockaddr *)l_addr;
}
}
else if(l_rta->rta_type == IFA_LOCAL)
{
if(l_entry->ifa_addr)
{
l_entry->ifa_dstaddr = l_entry->ifa_addr;
}
l_entry->ifa_addr = (struct sockaddr *)l_addr;
}
else
{
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
}
l_addr += NLMSG_ALIGN(l_addrLen);
break;
}
case IFA_LABEL:
strncpy(l_name, l_rtaData, l_rtaDataSize);
l_name[l_rtaDataSize] = '\0';
l_entry->ifa_name = l_name;
break;
default:
break;
}
}
if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
{
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
char l_mask[16] = {0};
unsigned i;
for(i=0; i<(l_prefix/8); ++i)
{
l_mask[i] = 0xff;
}
l_mask[i] = 0xff << (8 - (l_prefix % 8));
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
}
addToEnd(p_resultList, l_entry);
}
static void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
{
pid_t l_pid = getpid();
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
{
unsigned int l_nlsize = p_netlinkList->m_size;
struct nlmsghdr *l_hdr;
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
{
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
{
continue;
}
if(l_hdr->nlmsg_type == NLMSG_DONE)
{
break;
}
if(l_hdr->nlmsg_type == RTM_NEWLINK)
{
interpretLink(l_hdr, p_links, p_resultList);
}
else if(l_hdr->nlmsg_type == RTM_NEWADDR)
{
interpretAddr(l_hdr, p_links, p_resultList);
}
}
}
}
static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
{
unsigned l_links = 0;
pid_t l_pid = getpid();
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
{
unsigned int l_nlsize = p_netlinkList->m_size;
struct nlmsghdr *l_hdr;
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
{
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
{
continue;
}
if(l_hdr->nlmsg_type == NLMSG_DONE)
{
break;
}
if(l_hdr->nlmsg_type == RTM_NEWLINK)
{
++l_links;
}
}
}
return l_links;
}
int getifaddrs(struct ifaddrs **ifap)
{
if(!ifap)
{
return -1;
}
*ifap = NULL;
int l_socket = netlink_socket();
if(l_socket < 0)
{
return -1;
}
NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
if(!l_linkResults)
{
close(l_socket);
return -1;
}
NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
if(!l_addrResults)
{
close(l_socket);
freeResultList(l_linkResults);
return -1;
}
unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
struct ifaddrs *l_links[l_numLinks];
memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
interpret(l_socket, l_linkResults, l_links, ifap);
interpret(l_socket, l_addrResults, l_links, ifap);
freeResultList(l_linkResults);
freeResultList(l_addrResults);
close(l_socket);
return 0;
}
void freeifaddrs(struct ifaddrs *ifa)
{
struct ifaddrs *l_cur;
while(ifa)
{
l_cur = ifa;
ifa = ifa->ifa_next;
free(l_cur);
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 1995, 1999
* Berkeley Software Design, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
*/
#ifndef _IFADDRS_H_
#define _IFADDRS_H_
struct ifaddrs {
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
void *ifa_data;
};
/*
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
* to be included it must be included before this header file.
*/
#ifndef ifa_broadaddr
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
#endif
#include <sys/cdefs.h>
__BEGIN_DECLS
extern int getifaddrs(struct ifaddrs **ifap);
extern void freeifaddrs(struct ifaddrs *ifa);
__END_DECLS
#endif

View File

@ -61,6 +61,7 @@
#include <net/if.h>
#include <net/if_arp.h>
#include <linux/sockios.h>
#include "struct-etherarp.h"
#include <syslog.h>

View File

@ -13615,11 +13615,13 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
if (argv[0] && argv[0][0] == '-')
isloginsh = 1;
else
isloginsh = 1;
if (isloginsh) {
const char *hp;
state = 1;
read_profile("/etc/profile");
read_profile("/system/etc/profile");
state1:
state = 2;
hp = lookupvar("HOME");
@ -13657,6 +13659,9 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
if (iflag) {
const char *hp = lookupvar("HISTFILE");
if (!hp) {
#ifdef __ANDROID__
setvar("HISTFILE", "/mnt/sdcard/ash_history", 0);
#else
hp = lookupvar("HOME");
if (hp) {
INT_OFF;
@ -13666,6 +13671,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
INT_ON;
hp = lookupvar("HISTFILE");
}
#endif
}
if (hp)
line_input_state->hist_file = hp;

786
shell/glob.c Normal file
View File

@ -0,0 +1,786 @@
/*
* Modified for the Android NDK by Gabor Cselle, http://www.gaborcselle.com/
* Tested with Android NDK version 5b: http://developer.android.com/sdk/ndk/index.html
* Last modified: March 3 2011
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
/*
* glob(3) -- a superset of the one defined in POSIX 1003.2.
*
* The [!...] convention to negate a range is supported (SysV, Posix, ksh).
*
* Optional extra services, controlled by flags not defined by POSIX:
*
* GLOB_QUOTE:
* Escaping convention: \ inhibits any special meaning the following
* character might have (except \ at end of string is retained).
* GLOB_MAGCHAR:
* Set in gl_flags if pattern contained a globbing character.
* GLOB_NOMAGIC:
* Same as GLOB_NOCHECK, but it will only append pattern if it did
* not contain any magic characters. [Used in csh style globbing]
* GLOB_ALTDIRFUNC:
* Use alternately specified directory access functions.
* GLOB_TILDE:
* expand ~user/foo to the /home/dir/of/user/foo
* GLOB_BRACE:
* expand {1,2}{a,b} to 1a 1b 2a 2b
* gl_matchc:
* Number of matches in the current invocation of glob.
*/
/*
* Some notes on multibyte character support:
* 1. Patterns with illegal byte sequences match nothing - even if
* GLOB_NOCHECK is specified.
* 2. Illegal byte sequences in filenames are handled by treating them as
* single-byte characters with a value of the first byte of the sequence
* cast to wchar_t.
* 3. State-dependent encodings are not currently supported.
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include "glob.h"
#include <limits.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//#include "collate.h" - NOTE(gabor): I took this out because it's not available for Android
// and collate is only used once for string comparisons. As a side-effect, you might not
// be able to match non-ASCII filenames.
#define DOLLAR '$'
#define DOT '.'
#define EOS '\0'
#define LBRACKET '['
#define NOT '!'
#define QUESTION '?'
#define QUOTE '\\'
#define RANGE '-'
#define RBRACKET ']'
#define SEP '/'
#define STAR '*'
#define TILDE '~'
#define UNDERSCORE '_'
#define LBRACE '{'
#define RBRACE '}'
#define SLASH '/'
#define COMMA ','
#define M_PROTECT 0x40
#define M_MASK 0xff
#define M_ALL '*'
#define M_END ']'
#define M_NOT '!'
#define M_ONE '?'
#define M_RNG '-'
#define M_SET '['
static int g_stat(char *, struct stat *, glob_t *);
static int g_lstat(char *, struct stat *, glob_t *);
static DIR *g_opendir(char *, glob_t *);
static int compare(const void *, const void *);
static int glob0(const char *, glob_t *, size_t *);
static int glob1(char *, glob_t *, size_t *);
static int glob2(char *, char *, char *, char *, glob_t *, size_t *);
static int glob3(char *, char *, char *, char *, char *, glob_t *, size_t *);
static int globextend(const char *, glob_t *, size_t *);
static const char *
globtilde(const char *, char *, size_t, glob_t *);
static int globexp1(const char *, glob_t *, size_t *);
static int globexp2(const char *, const char *, glob_t *, int *, size_t *);
static int match(char *, char *, char *);
int ismeta(char c) {
return c == M_ALL || c == M_END || c == M_NOT || c == M_ONE || c == M_RNG || c == M_SET;
}
int
glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob)
{
const char *patnext;
size_t limit;
char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
patnext = pattern;
if (!(flags & GLOB_APPEND)) {
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
if (!(flags & GLOB_DOOFFS))
pglob->gl_offs = 0;
}
if (flags & GLOB_LIMIT) {
limit = pglob->gl_matchc;
if (limit == 0)
limit = 131072;
} else
limit = 0;
pglob->gl_flags = flags & ~GLOB_MAGCHAR;
pglob->gl_errfunc = errfunc;
pglob->gl_matchc = 0;
bufnext = patbuf;
bufend = bufnext + MAXPATHLEN - 1;
if (flags & GLOB_NOESCAPE) {
strncpy(bufnext, patnext, sizeof(patbuf));
} else {
/* Protect the quoted characters. */
while (bufend >= bufnext && *patnext != EOS) {
if (*patnext == QUOTE) {
if (*++patnext == EOS) {
*bufnext++ = QUOTE | M_PROTECT;
continue;
}
prot = M_PROTECT;
} else
prot = 0;
*bufnext++ = *patnext;
patnext++;
}
}
*bufnext = EOS;
if (flags & GLOB_BRACE)
return globexp1(patbuf, pglob, &limit);
else
return glob0(patbuf, pglob, &limit);
}
/*
* Expand recursively a glob {} pattern. When there is no more expansion
* invoke the standard globbing routine to glob the rest of the magic
* characters
*/
static int
globexp1(const char *pattern, glob_t *pglob, size_t *limit)
{
const char* ptr = pattern;
int rv;
/* Protect a single {}, for find(1), like csh */
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
return glob0(pattern, pglob, limit);
while ((ptr = strchr(ptr, LBRACE)) != NULL)
if (!globexp2(ptr, pattern, pglob, &rv, limit))
return rv;
return glob0(pattern, pglob, limit);
}
/*
* Recursive brace globbing helper. Tries to expand a single brace.
* If it succeeds then it invokes globexp1 with the new pattern.
* If it fails then it tries to glob the rest of the pattern and returns.
*/
static int
globexp2(const char *ptr, const char *pattern, glob_t *pglob, int *rv, size_t *limit)
{
int i;
char *lm, *ls;
const char *pe, *pm, *pm1, *pl;
char patbuf[MAXPATHLEN];
/* copy part up to the brace */
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
continue;
*lm = EOS;
ls = lm;
/* Find the balanced brace */
for (i = 0, pe = ++ptr; *pe; pe++)
if (*pe == LBRACKET) {
/* Ignore everything between [] */
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
continue;
if (*pe == EOS) {
/*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
pe = pm;
}
}
else if (*pe == LBRACE)
i++;
else if (*pe == RBRACE) {
if (i == 0)
break;
i--;
}
/* Non matching braces; just glob the pattern */
if (i != 0 || *pe == EOS) {
*rv = glob0(patbuf, pglob, limit);
return 0;
}
for (i = 0, pl = pm = ptr; pm <= pe; pm++)
switch (*pm) {
case LBRACKET:
/* Ignore everything between [] */
for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++)
continue;
if (*pm == EOS) {
/*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
pm = pm1;
}
break;
case LBRACE:
i++;
break;
case RBRACE:
if (i) {
i--;
break;
}
/* FALLTHROUGH */
case COMMA:
if (i && *pm == COMMA)
break;
else {
/* Append the current string */
for (lm = ls; (pl < pm); *lm++ = *pl++)
continue;
/*
* Append the rest of the pattern after the
* closing brace
*/
for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
continue;
/* Expand the current pattern */
*rv = globexp1(patbuf, pglob, limit);
/* move after the comma, to the next string */
pl = pm + 1;
}
break;
default:
break;
}
*rv = 0;
return 0;
}
/*
* expand tilde from the passwd file.
*/
static const char *
globtilde(const char *pattern, char *patbuf, size_t patbuf_len, glob_t *pglob)
{
struct passwd *pwd;
char *h;
const char *p;
char *b, *eb;
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return pattern;
/*
* Copy up to the end of the string or /
*/
eb = &patbuf[patbuf_len - 1];
for (p = pattern + 1, h = (char *) patbuf;
h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
continue;
*h = EOS;
if (((char *) patbuf)[0] == EOS) {
/*
* handle a plain ~ or ~/ by expanding $HOME first (iff
* we're not running setuid or setgid) and then trying
* the password file
*/
#ifndef __GLIBC__
if (issetugid() != 0 ||
(h = getenv("HOME")) == NULL) {
if (((h = getlogin()) != NULL &&
(pwd = getpwnam(h)) != NULL) ||
(pwd = getpwuid(getuid())) != NULL)
h = pwd->pw_dir;
else
return pattern;
}
#endif
}
else {
/*
* Expand a ~user
*/
if ((pwd = getpwnam((char*) patbuf)) == NULL)
return pattern;
else
h = pwd->pw_dir;
}
/* Copy the home directory */
for (b = patbuf; b < eb && *h; *b++ = *h++)
continue;
/* Append the rest of the pattern */
while (b < eb && (*b++ = *p++) != EOS)
continue;
*b = EOS;
return patbuf;
}
/*
* The main glob() routine: compiles the pattern (optionally processing
* quotes), calls glob1() to do the real pattern matching, and finally
* sorts the list (unless unsorted operation is requested). Returns 0
* if things went well, nonzero if errors occurred.
*/
static int
glob0(const char *pattern, glob_t *pglob, size_t *limit)
{
const char *qpatnext;
int err;
size_t oldpathc;
char *bufnext, c, patbuf[MAXPATHLEN];
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
/* We don't need to check for buffer overflow any more. */
while ((c = *qpatnext++) != EOS) {
switch (c) {
case LBRACKET:
c = *qpatnext;
if (c == NOT)
++qpatnext;
if (*qpatnext == EOS ||
strchr(qpatnext+1, RBRACKET) == NULL) {
*bufnext++ = LBRACKET;
if (c == NOT)
--qpatnext;
break;
}
*bufnext++ = M_SET;
if (c == NOT)
*bufnext++ = M_NOT;
c = *qpatnext++;
do {
*bufnext++ = c;
if (*qpatnext == RANGE &&
(c = qpatnext[1]) != RBRACKET) {
*bufnext++ = M_RNG;
*bufnext++ = c;
qpatnext += 2;
}
} while ((c = *qpatnext++) != RBRACKET);
pglob->gl_flags |= GLOB_MAGCHAR;
*bufnext++ = M_END;
break;
case QUESTION:
pglob->gl_flags |= GLOB_MAGCHAR;
*bufnext++ = M_ONE;
break;
case STAR:
pglob->gl_flags |= GLOB_MAGCHAR;
/* collapse adjacent stars to one,
* to avoid exponential behavior
*/
if (bufnext == patbuf || bufnext[-1] != M_ALL)
*bufnext++ = M_ALL;
break;
default:
*bufnext++ = c;
break;
}
}
*bufnext = EOS;
if ((err = glob1(patbuf, pglob, limit)) != 0)
return(err);
/*
* If there was no match we are going to append the pattern
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
* and the pattern did not contain any magic characters
* GLOB_NOMAGIC is there just for compatibility with csh.
*/
if (pglob->gl_pathc == oldpathc) {
if (((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & GLOB_NOMAGIC) &&
!(pglob->gl_flags & GLOB_MAGCHAR))))
return(globextend(pattern, pglob, limit));
else
return(GLOB_NOMATCH);
}
if (!(pglob->gl_flags & GLOB_NOSORT))
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
return(0);
}
static int
compare(const void *p, const void *q)
{
return(strcmp(*(char **)p, *(char **)q));
}
static int
glob1(char *pattern, glob_t *pglob, size_t *limit)
{
char pathbuf[MAXPATHLEN];
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
if (*pattern == EOS)
return(0);
return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
pattern, pglob, limit));
}
/*
* The functions glob2 and glob3 are mutually recursive; there is one level
* of recursion for each segment in the pattern that contains one or more
* meta characters.
*/
static int
glob2(char *pathbuf, char *pathend, char *pathend_last, char *pattern,
glob_t *pglob, size_t *limit)
{
struct stat sb;
char *p, *q;
int anymeta;
/*
* Loop over pattern segments until end of pattern or until
* segment with meta character found.
*/
for (anymeta = 0;;) {
if (*pattern == EOS) { /* End of pattern? */
*pathend = EOS;
if (g_lstat(pathbuf, &sb, pglob))
return(0);
if (((pglob->gl_flags & GLOB_MARK) &&
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
|| (S_ISLNK(sb.st_mode) &&
(g_stat(pathbuf, &sb, pglob) == 0) &&
S_ISDIR(sb.st_mode)))) {
if (pathend + 1 > pathend_last)
return (GLOB_ABORTED);
*pathend++ = SEP;
*pathend = EOS;
}
++pglob->gl_matchc;
return(globextend(pathbuf, pglob, limit));
}
/* Find end of next segment, copy tentatively to pathend. */
q = pathend;
p = pattern;
while (*p != EOS && *p != SEP) {
if (ismeta(*p))
anymeta = 1;
if (q + 1 > pathend_last)
return (GLOB_ABORTED);
*q++ = *p++;
}
if (!anymeta) { /* No expansion, do next segment. */
pathend = q;
pattern = p;
while (*pattern == SEP) {
if (pathend + 1 > pathend_last)
return (GLOB_ABORTED);
*pathend++ = *pattern++;
}
} else /* Need expansion, recurse. */
return(glob3(pathbuf, pathend, pathend_last, pattern, p,
pglob, limit));
}
/* NOTREACHED */
}
static int
glob3(char *pathbuf, char *pathend, char *pathend_last,
char *pattern, char *restpattern,
glob_t *pglob, size_t *limit)
{
struct dirent *dp;
DIR *dirp;
int err;
char buf[MAXPATHLEN];
/*
* The readdirfunc declaration can't be prototyped, because it is
* assigned, below, to two functions which are prototyped in glob.h
* and dirent.h as taking pointers to differently typed opaque
* structures.
*/
struct dirent *(*readdirfunc)();
if (pathend > pathend_last)
return (GLOB_ABORTED);
*pathend = EOS;
errno = 0;
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
/* TODO: don't call for ENOENT or ENOTDIR? */
if (pglob->gl_errfunc) {
if (pglob->gl_errfunc(buf, errno) ||
pglob->gl_flags & GLOB_ERR)
return (GLOB_ABORTED);
}
return(0);
}
err = 0;
/* Search directory for matching names. */
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
readdirfunc = pglob->gl_readdir;
else
readdirfunc = readdir;
while ((dp = (*readdirfunc)(dirp))) {
char *sc;
char *dc;
/* Initial DOT must be matched literally. */
if (dp->d_name[0] == DOT && *pattern != DOT)
continue;
dc = pathend;
sc = dp->d_name;
while (dc < pathend_last) {
if ((*dc++ = *sc) == EOS)
break;
sc++;
}
if (!match(pathend, pattern, restpattern)) {
*pathend = EOS;
continue;
}
err = glob2(pathbuf, --dc, pathend_last, restpattern,
pglob, limit);
if (err)
break;
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
(*pglob->gl_closedir)(dirp);
else
closedir(dirp);
return(err);
}
/*
* Extend the gl_pathv member of a glob_t structure to accomodate a new item,
* add the new item, and update gl_pathc.
*
* This assumes the BSD realloc, which only copies the block when its size
* crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
* behavior.
*
* Return 0 if new item added, error code if memory couldn't be allocated.
*
* Invariant of the glob_t structure:
* Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
static int
globextend(const char *path, glob_t *pglob, size_t *limit)
{
char **pathv;
size_t i, newsize, len;
char *copy;
const char *p;
if (*limit && pglob->gl_pathc > *limit) {
errno = 0;
return (GLOB_NOSPACE);
}
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
pathv = pglob->gl_pathv ?
realloc((char *)pglob->gl_pathv, newsize) :
malloc(newsize);
if (pathv == NULL) {
if (pglob->gl_pathv) {
free(pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
return(GLOB_NOSPACE);
}
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
pathv += pglob->gl_offs;
for (i = pglob->gl_offs + 1; --i > 0; )
*--pathv = NULL;
}
pglob->gl_pathv = pathv;
for (p = path; *p++;)
continue;
len = (size_t)(p - path); /* XXX overallocation */
if ((copy = malloc(len)) != NULL) {
strncpy(copy, path, len);
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
}
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
return(copy == NULL ? GLOB_NOSPACE : 0);
}
/*
* pattern matching function for filenames. Each occurrence of the *
* pattern causes a recursion level.
*/
static int
match(char *name, char *pat, char *patend)
{
int ok, negate_range;
char c, k;
while (pat < patend) {
c = *pat++;
switch (c & M_MASK) {
case M_ALL:
if (pat == patend)
return(1);
do
if (match(name, pat, patend))
return(1);
while (*name++ != EOS);
return(0);
case M_ONE:
if (*name++ == EOS)
return(0);
break;
case M_SET:
ok = 0;
if ((k = *name++) == EOS)
return(0);
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) {
// NOTE(gabor): This used to be as below, but I took out the collate.h
// if (__collate_load_error ?
// CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
// __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
// && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0
// )
if (c <= k && k <= pat[1])
ok = 1;
pat += 2;
} else if (c == k)
ok = 1;
if (ok == negate_range)
return(0);
break;
default:
if (*name++ != c)
return(0);
break;
}
}
return(*name == EOS);
}
/* Free allocated data belonging to a glob_t structure. */
void
globfree(glob_t *pglob)
{
size_t i;
char **pp;
if (pglob->gl_pathv != NULL) {
pp = pglob->gl_pathv + pglob->gl_offs;
for (i = pglob->gl_pathc; i--; ++pp)
if (*pp)
free(*pp);
free(pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
}
static int
g_stat(char *fn, struct stat *sb, glob_t *pglob)
{
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_stat)(fn, sb));
return(stat(fn, sb));
}
static DIR *
g_opendir(char *str, glob_t *pglob)
{
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_opendir)(str));
return(opendir(str));
}
static int
g_lstat(char *fn, struct stat *sb, glob_t *pglob)
{
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_lstat)(fn, sb));
return(lstat(fn, sb));
}

113
shell/glob.h Normal file
View File

@ -0,0 +1,113 @@
/*
* Modified for the Android NDK by Gabor Cselle, http://www.gaborcselle.com/
* Tested with Android NDK version 5b: http://developer.android.com/sdk/ndk/index.html
* Last modified: March 3 2011
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)glob.h 8.1 (Berkeley) 6/2/93
* $FreeBSD$
*/
#ifndef _GLOB_H_
#define _GLOB_H_
#include <sys/cdefs.h>
//#include <sys/_types.h>
#ifndef _SIZE_T_DECLARED
typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
struct stat;
typedef struct {
size_t gl_pathc; /* Count of total paths so far. */
size_t gl_matchc; /* Count of paths matching pattern. */
size_t gl_offs; /* Reserved at beginning of gl_pathv. */
int gl_flags; /* Copy of flags parameter to glob. */
char **gl_pathv; /* List of paths matching pattern. */
/* Copy of errfunc parameter to glob. */
int (*gl_errfunc)(const char *, int);
/*
* Alternate filesystem access methods for glob; replacement
* versions of closedir(3), readdir(3), opendir(3), stat(2)
* and lstat(2).
*/
void (*gl_closedir)(void *);
struct dirent *(*gl_readdir)(void *);
void *(*gl_opendir)(const char *);
int (*gl_lstat)(const char *, struct stat *);
int (*gl_stat)(const char *, struct stat *);
} glob_t;
#if __POSIX_VISIBLE >= 199209
/* Believed to have been introduced in 1003.2-1992 */
#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
#define GLOB_ERR 0x0004 /* Return on error. */
#define GLOB_MARK 0x0008 /* Append / to matching directories. */
#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
#define GLOB_NOSORT 0x0020 /* Don't sort. */
#define GLOB_NOESCAPE 0x2000 /* Disable backslash escaping. */
/* Error values returned by glob(3) */
#define GLOB_NOSPACE (-1) /* Malloc call failed. */
#define GLOB_ABORTED (-2) /* Unignored error. */
#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK was not set. */
#define GLOB_NOSYS (-4) /* Obsolete: source comptability only. */
#endif /* __POSIX_VISIBLE >= 199209 */
#if __BSD_VISIBLE
#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
#define GLOB_LIMIT 0x1000 /* limit number of returned paths */
/* source compatibility, these are the old names */
#define GLOB_MAXPATH GLOB_LIMIT
#define GLOB_ABEND GLOB_ABORTED
#endif /* __BSD_VISIBLE */
__BEGIN_DECLS
int glob(const char *, int, int (*)(const char *, int), glob_t *);
void globfree(glob_t *);
__END_DECLS
#endif /* !_GLOB_H_ */

View File

@ -283,8 +283,11 @@
//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
//kbuild:lib-$(CONFIG_HUSH) += glob.o sigisemptyset.o
//kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o
//kbuild:lib-$(CONFIG_SH_IS_HUSH) += glob.o sigisemptyset.o
//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o
//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += glob.o sigisemptyset.o
//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
/* -i (interactive) and -s (read stdin) are also accepted,
@ -302,7 +305,7 @@
)
# include <malloc.h> /* for malloc_trim */
#endif
#include <glob.h>
#include "glob.h"
/* #include <dmalloc.h> */
#if ENABLE_HUSH_CASE
# include <fnmatch.h>

8
shell/sigisemptyset.c Normal file
View File

@ -0,0 +1,8 @@
// in androids asm/signal.h, sigset_t is a simple unsigned long
#include <signal.h>
int sigisemptyset(const sigset_t *set)
{
return set;
}

View File

@ -45,8 +45,8 @@
#include "libbb.h"
#include "common_bufsiz.h"
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <linux/sem.h>
#include <linux/shm.h>
#define DEBUG 0

View File

@ -172,8 +172,8 @@
#if ENABLE_FEATURE_IPC_SYSLOG
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <linux/sem.h>
#include <linux/shm.h>
#endif

View File

@ -12,6 +12,7 @@
#define SYSLOG_NAMES
#define SYSLOG_NAMES_CONST
#include <syslog.h>
#include <sys/syslog.h>
#if 0
/* For the record: with SYSLOG_NAMES <syslog.h> defines

View File

@ -33,11 +33,12 @@
/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <linux/shm.h>
#include <linux/msg.h>
#include <linux/sem.h>
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) || \
defined(__ANDROID__)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */

View File

@ -40,9 +40,9 @@
/* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include "libbb.h"
@ -88,7 +88,8 @@ struct shm_info {
/* The last arg of semctl is a union semun, but where is it defined?
X/OPEN tells us to define it ourselves, but until recently
Linux include files would also define it. */
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) || \
defined(__ANDROID__)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */

View File

@ -54,6 +54,8 @@ struct minix_dir_entry {
/* Believe it or not, but mount.h has this one #defined */
#undef BLOCK_SIZE
#undef MINIX2_SUPER_MAGIC
#undef MINIX2_SUPER_MAGIC2
enum {
BLOCK_SIZE = 1024,
BITS_PER_BLOCK = BLOCK_SIZE << 3,

View File

@ -235,7 +235,11 @@ static int do_em_all_in_fstab(void)
/* swapon -a should ignore entries with noauto,
* but swapoff -a should process them
*/
if (do_swapoff || hasmntopt(m, MNTOPT_NOAUTO) == NULL) {
if (do_swapoff
#ifdef MNTOPT_NOAUTO
|| hasmntopt(m, MNTOPT_NOAUTO) == NULL
#endif
) {
/* each swap space might have different flags */
/* save global flags for the next round */
save_g_flags();