mirror of
https://github.com/topjohnwu/ndk-busybox.git
synced 2024-11-27 05:30:34 +00:00
Apply patches from osm0sis/android-busybox-ndk
Auto generated by ndk-busybox-kitchen
This commit is contained in:
parent
81e26c4b8e
commit
12da53078d
1
Makefile
1
Makefile
@ -476,6 +476,7 @@ libs-y := \
|
||||
init/ \
|
||||
libbb/ \
|
||||
libpwdgrp/ \
|
||||
libres/ \
|
||||
loginutils/ \
|
||||
mailutils/ \
|
||||
miscutils/ \
|
||||
|
@ -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"
|
||||
|
58
include/linux/ipv6_route.h
Normal file
58
include/linux/ipv6_route.h
Normal 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
277
include/mtd/mtd-abi.h
Normal 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
34
include/mtd/mtd-user.h
Normal 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
412
include/mtd/ubi-user.h
Normal 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__ */
|
@ -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
225
include/scsi/scsi.h
Normal 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
276
include/scsi/sg.h
Normal 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
34
include/sys/kd.h
Normal 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
138
include/sys/syslog.h
Normal 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 */
|
27
init/halt.c
27
init/halt.c
@ -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 */
|
||||
|
@ -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
33
init/reboot.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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
288
libbb/mntent_r.c
Normal 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;
|
||||
}
|
@ -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
62
libbb/semctl.c
Normal 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);
|
||||
}
|
@ -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
11
libres/Kbuild.src
Normal 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
32
libres/Makefile
Normal 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
5
libres/README
Normal 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
189
libres/dietdns.h
Normal 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
12
libres/dn_expand.c
Normal 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
134
libres/dnscruft.c
Normal 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
132
libres/dnscruft2.c
Normal 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
6
libres/dnscruft3.c
Normal 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
14
libres/freeaddrinfo.c
Normal 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
14
libres/gai_strerror.c
Normal 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
137
libres/getaddrinfo.c
Normal 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
35
libres/gethostbyname2_r.c
Normal 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
1
libres/h_errno.c
Normal file
@ -0,0 +1 @@
|
||||
int diet_h_errno;
|
12
libres/res_init.c
Normal file
12
libres/res_init.c
Normal 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
85
libres/res_mkquery.c
Normal 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
81
libres/res_query.c
Normal 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
105
libres/test.c
Normal 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;
|
||||
}
|
@ -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=")) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;*/
|
||||
|
@ -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"
|
||||
|
75
networking/struct-etherarp.h
Normal file
75
networking/struct-etherarp.h
Normal 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 */
|
@ -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
|
||||
|
||||
|
@ -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
600
networking/udhcp/ifaddrs.c
Normal 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);
|
||||
}
|
||||
}
|
54
networking/udhcp/ifaddrs.h
Normal file
54
networking/udhcp/ifaddrs.h
Normal 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
|
@ -61,6 +61,7 @@
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <linux/sockios.h>
|
||||
#include "struct-etherarp.h"
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
|
@ -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
786
shell/glob.c
Normal 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
113
shell/glob.h
Normal 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_ */
|
@ -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
8
shell/sigisemptyset.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user