static void print_sem(int semid) { struct semid_ds semds; struct ipc_perm *ipcp = &semds.sem_perm; union semun arg; unsigned int i; arg.buf = &semds; if (semctl(semid, 0, IPC_STAT, arg)) { bb_perror_msg("semctl"); return; } printf("\nSemaphore Array semid=%d\n" "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n" "mode=%#o, access_perms=%#o\n" "nsems = %ld\n" "otime = %-26.24s\n", semid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode, ipcp->mode & 0777, (long) semds.sem_nsems, semds.sem_otime ? ctime(&semds.sem_otime) : "Not set"); printf("ctime = %-26.24s\n" "%-10s %-10s %-10s %-10s %-10s\n", ctime(&semds.sem_ctime), "semnum", "value", "ncount", "zcount", "pid"); arg.val = 0; for (i = 0; i < semds.sem_nsems; i++) { int val, ncnt, zcnt, pid; val = semctl(semid, i, GETVAL, arg); ncnt = semctl(semid, i, GETNCNT, arg); zcnt = semctl(semid, i, GETZCNT, arg); pid = semctl(semid, i, GETPID, arg); if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) { bb_perror_msg_and_die("semctl"); } printf("%-10u %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid); } bb_putchar('\n'); }
/* * Load the filesystem database from /etc/fstab */ static void load_fs_info(const char *filename) { FILE *f; char buf[1024]; int lineno = 0; int old_fstab = 1; struct fs_info *fs; if ((f = fopen(filename, "r")) == NULL) { bb_perror_msg("WARNING: cannot open %s", filename); return; } while (!feof(f)) { lineno++; if (!fgets(buf, sizeof(buf), f)) break; buf[sizeof(buf)-1] = 0; if (parse_fstab_line(buf, &fs) < 0) { bb_error_msg("WARNING: bad format " "on line %d of %s\n", lineno, filename); continue; } if (!fs) continue; if (fs->passno < 0) fs->passno = 0; else old_fstab = 0; } fclose(f); if (old_fstab) { fputs("\007\007\007" "WARNING: Your /etc/fstab does not contain the fsck passno\n" " field. I will kludge around things for you, but you\n" " should fix your /etc/fstab file as soon as you can.\n\n", stderr); for (fs = filesys_info; fs; fs = fs->next) { fs->passno = 1; } } }
static int do_sendto(int fd, const struct sockaddr *from, const struct sockaddr *to, socklen_t addrlen, msg_t *msg, ssize_t len) { ssize_t ret; errno = 0; if (!from) { ret = sendto(fd, msg, len, MSG_DONTWAIT, to, addrlen); } else { ret = send_to_from(fd, msg, len, MSG_DONTWAIT, to, from, addrlen); } if (ret != len) { bb_perror_msg("send failed"); return -1; } return 0; }
/* Returns kernel version encoded as major*65536 + minor*256 + patch, * so, for example, to check if the kernel is greater than 2.2.11: * if (get_kernel_revision() <= 2*65536+2*256+11) { <stuff> } */ int get_kernel_revision(void) { struct utsname name; char *s; int i, r; if (uname(&name) == -1) { bb_perror_msg("cannot get system information"); return (0); } s = name.release; r = 0; for (i=0 ; i<3 ; i++) { r = r * 256 + atoi(strtok(s, ".")); s = NULL; } return r; }
static void ping4(len_and_sockaddr *lsa) { struct icmp *pkt; int c; pkt = (struct icmp *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp_type = ICMP_ECHO; pkt->icmp_id = G.myid; pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); /* listen for replies */ while (1) { #if 0 struct sockaddr_in from; socklen_t fromlen = sizeof(from); c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &fromlen); #else c = recv(pingsock, G.packet, sizeof(G.packet), 0); #endif if (c < 0) { if (errno != EINTR) bb_perror_msg("recvfrom"); continue; } if (c >= 76) { /* ip + icmp */ struct iphdr *iphdr = (struct iphdr *) G.packet; pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ if (pkt->icmp_id != G.myid) continue; /* not our ping */ if (pkt->icmp_type == ICMP_ECHOREPLY) break; } } if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); }
static void ping6(len_and_sockaddr *lsa) { struct icmp6_hdr *pkt; int c; int sockopt; pkt = (struct icmp6_hdr *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp6_type = ICMP6_ECHO_REQUEST; pkt->icmp6_id = G.myid; sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len); /* listen for replies */ while (1) { #if 0 struct sockaddr_in6 from; socklen_t fromlen = sizeof(from); c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &fromlen); #else c = recv(pingsock, G.packet, sizeof(G.packet), 0); #endif if (c < 0) { if (errno != EINTR) bb_perror_msg("recvfrom"); continue; } if (c >= ICMP_MINLEN) { /* icmp6_hdr */ if (pkt->icmp6_id != G.myid) continue; /* not our ping */ if (pkt->icmp6_type == ICMP6_ECHO_REPLY) break; } } if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); }
/* Wrapper which restarts poll on EINTR or ENOMEM. * On other errors does perror("poll") and returns. * Warning! May take longer than timeout_ms to return! */ int FAST_FUNC safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout) { while (1) { int n = poll(ufds, nfds, timeout); if (n >= 0) return n; /* Make sure we inch towards completion */ if (timeout > 0) timeout--; /* E.g. strace causes poll to return this */ if (errno == EINTR) continue; /* Kernel is very low on memory. Retry. */ /* I doubt many callers would handle this correctly! */ if (errno == ENOMEM) continue; bb_perror_msg("poll"); return n; } }
static int do_del_ioctl(char *basedev, struct ip_tunnel_parm *p) { struct ifreq ifr; int fd; int err; if (p->name[0]) { strcpy(ifr.ifr_name, p->name); } else { strcpy(ifr.ifr_name, basedev); } ifr.ifr_ifru.ifru_data = (void*)p; fd = socket(AF_INET, SOCK_DGRAM, 0); err = ioctl(fd, SIOCDELTUNNEL, &ifr); if (err) { bb_perror_msg("ioctl"); } close(fd); return err; }
int mkfifo_main(int argc, char **argv) { mode_t mode; int retval = EXIT_SUCCESS; mode = getopt_mk_fifo_nod(argc, argv); if (!*(argv += optind)) { bb_show_usage(); } do { if (mkfifo(*argv, mode) < 0) { bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */ retval = EXIT_FAILURE; } } while (*++argv); return retval; }
int FAST_FUNC cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf) { if (sf(fn, fn_stat) < 0) { if (errno != ENOENT) { #if ENABLE_FEATURE_VERBOSE_CP_MESSAGE if (errno == ENOTDIR) { bb_error_msg("cannot stat '%s': Path has non-directory component", fn); return -1; } #endif bb_perror_msg("cannot stat '%s'", fn); return -1; } return 0; } if (S_ISDIR(fn_stat->st_mode)) { return 3; } return 1; }
int dumpkmap_main(int argc, char **argv) { struct kbentry ke; int i, j, fd; char flags[MAX_NR_KEYMAPS], magic[] = "bkeymap"; if (argc >= 2 && *argv[1] == '-') bb_show_usage(); fd = bb_xopen(CURRENT_VC, O_RDWR); write(1, magic, 7); /* Here we want to set everything to 0 except for indexes: * [0-2] [4-6] [8-10] [12] */ memset(flags, 0x00, MAX_NR_KEYMAPS); memset(flags, 0x01, 13); flags[3] = flags[7] = flags[11] = 0; /* dump flags */ write(1, flags, MAX_NR_KEYMAPS); for (i = 0; i < MAX_NR_KEYMAPS; i++) { if (flags[i] == 1) { for (j = 0; j < NR_KEYS; j++) { ke.kb_index = j; ke.kb_table = i; if (ioctl(fd, KDGKBENT, &ke) < 0) { bb_perror_msg("ioctl failed with %s, %s, %p", (char *)&ke.kb_index, (char *)&ke.kb_table, &ke.kb_value); } else { write(1, (void*)&ke.kb_value, 2); } } } } close(fd); return EXIT_SUCCESS; }
static void do_stop(void) { char what[1024]; struct pid_list *p; int killed = 0; do_procinit(); if (cmdname) strcpy(what, cmdname); else if (execname) strcpy(what, execname); else if (pidfile) sprintf(what, "process in pidfile `%.200s'", pidfile); else if (userspec) sprintf(what, "process(es) owned by `%s'", userspec); else bb_error_msg_and_die ("internal error, please report"); if (!found) { if (!quiet) printf("no %s found; none killed.\n", what); return; } for (p = found; p; p = p->next) { if (kill(p->pid, signal_nr) == 0) { p->pid = -p->pid; killed++; } else { bb_perror_msg("warning: failed to kill %d", p->pid); } } if (!quiet && killed) { printf("stopped %s (pid", what); for (p = found; p; p = p->next) if(p->pid < 0) printf(" %d", -p->pid); printf(").\n"); } }
/** * Broadcast an ARP packet. */ static void arp( /* int op, - always ARPOP_REQUEST */ /* const struct ether_addr *source_eth, - always ð_addr */ struct in_addr source_ip, const struct ether_addr *target_eth, struct in_addr target_ip) { enum { op = ARPOP_REQUEST }; #define source_eth (ð_addr) struct arp_packet p; memset(&p, 0, sizeof(p)); // ether header p.eth.ether_type = htons(ETHERTYPE_ARP); memcpy(p.eth.ether_shost, source_eth, ETH_ALEN); memset(p.eth.ether_dhost, 0xff, ETH_ALEN); // arp request p.arp.arp_hrd = htons(ARPHRD_ETHER); p.arp.arp_pro = htons(ETHERTYPE_IP); p.arp.arp_hln = ETH_ALEN; p.arp.arp_pln = 4; p.arp.arp_op = htons(op); memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN); memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa)); memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN); memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); // send it // Even though sock_fd is already bound to saddr, just send() // won't work, because "socket is not connected" // (and connect() won't fix that, "operation not supported"). // Thus we sendto() to saddr. I wonder which sockaddr // (from bind() or from sendto()?) kernel actually uses // to determine iface to emit the packet from... if (sendto(sock_fd, &p, sizeof(p), 0, &saddr, sizeof(saddr)) < 0) { bb_perror_msg("sendto"); cleanup(EXIT_FAILURE); } #undef source_eth }
static ssize_t tail_read(int fd, char *buf, size_t count) { ssize_t r; off_t current; struct stat sbuf; /* /proc files report zero st_size, don't lseek them. */ if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { current = lseek(fd, 0, SEEK_CUR); if (sbuf.st_size < current) xlseek(fd, 0, SEEK_SET); } r = full_read(fd, buf, count); if (r < 0) { bb_perror_msg(bb_msg_read_error); G.exitcode = EXIT_FAILURE; } return r; }
static int fuser_kill_pid_list(pid_list *plist, int sig) { pid_list *curr = plist; pid_t mypid = getpid(); int success = 1; if (plist == NULL) return 0; while (curr != NULL) { if (curr->pid > 0 && curr->pid != mypid) { printf("\r\nkill pid: %d.\n", curr->pid); if (kill(curr->pid, sig) != 0) { bb_perror_msg("kill pid '%d'", curr->pid); success = 0; } } curr = curr->next; } return success; }
/* create (sym)links for each applet */ static void install_links(const char *busybox, int use_symbolic_links) { __link_f Link = link; char *fpc; int i; int rc; if (use_symbolic_links) Link = symlink; for (i = 0; applets[i].name != NULL; i++) { fpc = concat_path_file( install_dir[applets[i].location], applets[i].name); rc = Link(busybox, fpc); if (rc!=0 && errno!=EEXIST) { bb_perror_msg("%s", fpc); } free(fpc); } }
extern char *xreadlink(const char *path) { static const int GROWBY = 80; /* how large we will grow strings by */ char *buf = NULL; int bufsize = 0, readsize = 0; do { buf = xrealloc(buf, bufsize += GROWBY); readsize = readlink(path, buf, bufsize); /* 1st try */ if (readsize == -1) { bb_perror_msg("%s", path); return NULL; } } while (bufsize < readsize + 1); buf[readsize] = '\0'; return buf; }
static void print_queuelen(char *name) { struct ifreq ifr; int s; s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) return; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) { bb_perror_msg("SIOCGIFXQLEN"); close(s); return; } close(s); if (ifr.ifr_qlen) printf("qlen %d", ifr.ifr_qlen); }
static ssize_t tail_read(int fd, char *buf, size_t count) { ssize_t r; off_t current; struct stat sbuf; /* (A good comment is missing here) */ current = lseek(fd, 0, SEEK_CUR); /* /proc files report zero st_size, don't lseek them. */ if (fstat(fd, &sbuf) == 0 && sbuf.st_size) if (sbuf.st_size < current) lseek(fd, 0, SEEK_SET); r = full_read(fd, buf, count); if (r < 0) { bb_perror_msg(bb_msg_read_error); G.status = EXIT_FAILURE; } return r; }
char *xmalloc_readlink_or_warn(const char *path) { enum { GROWBY = 80 }; /* how large we will grow strings by */ char *buf = NULL; int bufsize = 0, readsize = 0; do { buf = xrealloc(buf, bufsize += GROWBY); readsize = readlink(path, buf, bufsize); /* 1st try */ if (readsize == -1) { bb_perror_msg("%s", path); free(buf); return NULL; } } while (bufsize < readsize + 1); buf[readsize] = '\0'; return buf; }
static void do_info(const char *file, const char *name, void (*proc)(int, const char *)) { int lnr = 0; FILE *procinfo; procinfo = fopen(file, "r"); if (procinfo == NULL) { if (errno != ENOENT) { bb_perror_msg("%s", file); } else { bb_error_msg("no support for '%s' on this system", name); } return; } do { char *buffer = xmalloc_fgets(procinfo); if (buffer) { (proc)(lnr++, buffer); free(buffer); } } while (!feof(procinfo)); fclose(procinfo); }
static unsigned svstatus_print(char *m) { int pid; int normallyup = 0; struct stat s; if (stat("down", &s) == -1) { if (errno != ENOENT) { bb_perror_msg(WARN"cannot stat %s/down", *service); return 0; } normallyup = 1; } pid = (unsigned char) svstatus[15]; pid <<= 8; pid += (unsigned char)svstatus[14]; pid <<= 8; pid += (unsigned char)svstatus[13]; pid <<= 8; pid += (unsigned char)svstatus[12]; tai_unpack(svstatus, &tstatus); if (pid) { switch (svstatus[19]) { case 1: printf(RUN); break; case 2: printf(FINISH); break; } printf("%s: (pid %d) ", m, pid); } else { printf(DOWN"%s: ", m); } printf("%lus", (unsigned long)(tnow.sec.x < tstatus.x ? 0 : tnow.sec.x-tstatus.x)); if (pid && !normallyup) printf(", normally down"); if (!pid && normallyup) printf(", normally up"); if (pid && svstatus[16]) printf(", paused"); if (!pid && (svstatus[17] == 'u')) printf(", want up"); if (pid && (svstatus[17] == 'd')) printf(", want down"); if (pid && svstatus[18]) printf(", got TERM"); return pid ? 1 : 2; }
static void crondlog(const char *ctl, ...) { va_list va; const char *fmt; int level = (int) (ctl[0] & 0xf); int type = level == 20 ? LOG_ERR : ((ctl[0] & 0100) ? LOG_WARNING : LOG_NOTICE); va_start(va, ctl); fmt = ctl + 1; if (level >= LogLevel) { #ifdef FEATURE_DEBUG_OPT if (DebugOpt) { vfprintf(stderr, fmt, va); } else #endif if (LogFile == 0) { vsyslog(type, fmt, va); } else { int logfd = open(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600); if (logfd >= 0) { vdprintf(logfd, fmt, va); close(logfd); #ifdef FEATURE_DEBUG_OPT } else { bb_perror_msg("Can't open log file"); #endif } } } va_end(va); if (ctl[0] & 0200) { exit(20); } }
IF_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, void *wbuf) { int n, n2, ret; strm->avail_in = rlen; strm->next_in = rbuf; while (1) { strm->avail_out = IOBUF_SIZE; strm->next_out = wbuf; ret = BZ2_bzCompress(strm, rlen ? BZ_RUN : BZ_FINISH); if (ret != BZ_RUN_OK /* BZ_RUNning */ && ret != BZ_FINISH_OK /* BZ_FINISHing, but not done yet */ && ret != BZ_STREAM_END /* BZ_FINISHed */ ) { bb_error_msg_and_die("internal error %d", ret); } n = IOBUF_SIZE - strm->avail_out; if (n) { n2 = full_write(STDOUT_FILENO, wbuf, n); if (n2 != n) { if (n2 >= 0) errno = 0; /* prevent bogus error message */ bb_perror_msg(n2 >= 0 ? "short write" : bb_msg_write_error); return -1; } } if (ret == BZ_STREAM_END) break; if (rlen && strm->avail_in == 0) break; } return 0 IF_DESKTOP( + strm->total_out ); }
static int swap_enable_disable(const char *device) { int status; struct stat st; xstat(device, &st); /* test for holes */ if (S_ISREG(st.st_mode)) if (st.st_blocks * 512 < st.st_size) bb_error_msg_and_die("swap file has holes"); if (bb_applet_name[5] == 'n') status = swapon(device, 0); else status = swapoff(device); if (status != 0) { bb_perror_msg("%s", device); return 1; } return 0; }
static void up_iface(void) { struct ifreq ifrequest; if (!G.iface_exists) return; set_ifreq_to_ifname(&ifrequest); if (network_ioctl(SIOCGIFFLAGS, &ifrequest, "getting interface flags") < 0) { G.iface_exists = 0; return; } if (!(ifrequest.ifr_flags & IFF_UP)) { ifrequest.ifr_flags |= IFF_UP; /* Let user know we mess up with interface */ bb_error_msg("upping interface"); if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0) { if (errno != ENODEV && errno != EADDRNOTAVAIL) xfunc_die(); G.iface_exists = 0; return; } } #if 0 /* why do we mess with IP addr? It's not our business */ if (network_ioctl(SIOCGIFADDR, &ifrequest, "can't get interface address") < 0) { } else if (ifrequest.ifr_addr.sa_family != AF_INET) { bb_perror_msg("the interface is not IP-based"); } else { ((struct sockaddr_in*)(&ifrequest.ifr_addr))->sin_addr.s_addr = INADDR_ANY; network_ioctl(SIOCSIFADDR, &ifrequest, "can't set interface address"); } network_ioctl(SIOCGIFFLAGS, &ifrequest, "can't get interface flags"); #endif }
static uint8_t *hash_file(const char *filename, hash_algo_t hash_algo) { int src_fd, hash_len, count; union _ctx_ { sha1_ctx_t sha1; md5_ctx_t md5; } context; uint8_t *hash_value = NULL; RESERVE_CONFIG_UBUFFER(in_buf, 4096); void (*update)(const void*, size_t, void*); void (*final)(void*, void*); if (strcmp(filename, "-") == 0) { src_fd = STDIN_FILENO; } else if(0 > (src_fd = open(filename, O_RDONLY))) { bb_perror_msg("%s", filename); return NULL; } /* figure specific hash algorithims */ if (ENABLE_MD5SUM && hash_algo==HASH_MD5) { md5_begin(&context.md5); update = (void (*)(const void*, size_t, void*))md5_hash; final = (void (*)(void*, void*))md5_end;
/* * Display all the sysctl settings * */ int sysctl_display_all(const char *path, int output, int show_table) { int retval = 0; int retval2; DIR *dp; struct dirent *de; char *tmpdir; struct stat ts; dp = opendir(path); if (!dp) { retval = -1; } else { while ((de = readdir(dp)) != NULL) { tmpdir = concat_subpath_file(path, de->d_name); if (tmpdir == NULL) continue; retval2 = stat(tmpdir, &ts); if (retval2 != 0) bb_perror_msg(tmpdir); else { if (S_ISDIR(ts.st_mode)) { sysctl_display_all(tmpdir, output, show_table); } else retval |= sysctl_read_setting(tmpdir + strlen(PROC_PATH), output); } free(tmpdir); } /* end while */ closedir(dp); } return retval; } /* end sysctl_display_all() */
/** * Run a script. argv[2] is already NULL. */ static int run(char *argv[3], struct in_addr *ip) { int status; char *addr = addr; /* for gcc */ const char *fmt = "%s %s %s" + 3; VDBG("%s run %s %s\n", intf, argv[0], argv[1]); if (ip) { addr = inet_ntoa(*ip); setenv("ip", addr, 1); fmt -= 3; } bb_info_msg(fmt, argv[1], intf, addr); status = wait4pid(spawn(argv)); if (status < 0) { bb_perror_msg("%s %s %s" + 3, argv[1], intf); return -errno; } if (status != 0) bb_error_msg("script %s %s failed, exitcode=%d", argv[0], argv[1], status); return status; }
int copy_file(const char *source, const char *dest, int flags) { struct stat source_stat; struct stat dest_stat; int dest_exists = 0; int status = 0; if ((!(flags & FILEUTILS_DEREFERENCE) && lstat(source, &source_stat) < 0) || ((flags & FILEUTILS_DEREFERENCE) && stat(source, &source_stat) < 0)) { bb_perror_msg("%s", source); return -1; } if (lstat(dest, &dest_stat) < 0) { if (errno != ENOENT) { bb_perror_msg("unable to stat `%s'", dest); return -1; } } else { if (source_stat.st_dev == dest_stat.st_dev && source_stat.st_ino == dest_stat.st_ino) { bb_error_msg("`%s' and `%s' are the same file", source, dest); return -1; } dest_exists = 1; } if (S_ISDIR(source_stat.st_mode)) { DIR *dp; struct dirent *d; mode_t saved_umask = 0; if (!(flags & FILEUTILS_RECUR)) { bb_error_msg("%s: omitting directory", source); return -1; } /* Create DEST. */ if (dest_exists) { if (!S_ISDIR(dest_stat.st_mode)) { bb_error_msg("`%s' is not a directory", dest); return -1; } } else { mode_t mode; saved_umask = umask(0); mode = source_stat.st_mode; if (!(flags & FILEUTILS_PRESERVE_STATUS)) mode = source_stat.st_mode & ~saved_umask; mode |= S_IRWXU; if (mkdir(dest, mode) < 0) { umask(saved_umask); bb_perror_msg("cannot create directory `%s'", dest); return -1; } umask(saved_umask); } /* Recursively copy files in SOURCE. */ if ((dp = opendir(source)) == NULL) { bb_perror_msg("unable to open directory `%s'", source); status = -1; goto end; } while ((d = readdir(dp)) != NULL) { char *new_source, *new_dest; new_source = concat_subpath_file(source, d->d_name); if(new_source == NULL) continue; new_dest = concat_path_file(dest, d->d_name); if (copy_file(new_source, new_dest, flags) < 0) status = -1; free(new_source); free(new_dest); } /* closedir have only EBADF error, but "dp" not changes */ closedir(dp); if (!dest_exists && chmod(dest, source_stat.st_mode & ~saved_umask) < 0) { bb_perror_msg("unable to change permissions of `%s'", dest); status = -1; } } else if (S_ISREG(source_stat.st_mode)) { int src_fd; int dst_fd = -1; #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS char *link_name; if (!(flags & FILEUTILS_DEREFERENCE) && is_in_ino_dev_hashtable(&source_stat, &link_name)) { if (link(link_name, dest) < 0) { bb_perror_msg("unable to link `%s'", dest); return -1; } return 0; } #endif src_fd = open(source, O_RDONLY); if (src_fd == -1) { bb_perror_msg("unable to open `%s'", source); return(-1); } if (dest_exists) { if (flags & FILEUTILS_INTERACTIVE) { fprintf(stderr, "%s: overwrite `%s'? ", bb_applet_name, dest); if (!bb_ask_confirmation()) { close (src_fd); return 0; } } dst_fd = open(dest, O_WRONLY|O_TRUNC); if (dst_fd == -1) { if (!(flags & FILEUTILS_FORCE)) { bb_perror_msg("unable to open `%s'", dest); close(src_fd); return -1; } if (unlink(dest) < 0) { bb_perror_msg("unable to remove `%s'", dest); close(src_fd); return -1; } dest_exists = 0; } } if (!dest_exists) { dst_fd = open(dest, O_WRONLY|O_CREAT, source_stat.st_mode); if (dst_fd == -1) { bb_perror_msg("unable to open `%s'", dest); close(src_fd); return(-1); } } if (bb_copyfd_eof(src_fd, dst_fd) == -1) status = -1; if (close(dst_fd) < 0) { bb_perror_msg("unable to close `%s'", dest); status = -1; } if (close(src_fd) < 0) { bb_perror_msg("unable to close `%s'", source); status = -1; } } else if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) || S_ISLNK(source_stat.st_mode)) { if (dest_exists) { if((flags & FILEUTILS_FORCE) == 0) { fprintf(stderr, "`%s' exists\n", dest); return -1; } if(unlink(dest) < 0) { bb_perror_msg("unable to remove `%s'", dest); return -1; } } } else { bb_error_msg("internal error: unrecognized file type"); return -1; } if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || S_ISSOCK(source_stat.st_mode)) { if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) { bb_perror_msg("unable to create `%s'", dest); return -1; } } else if (S_ISFIFO(source_stat.st_mode)) { if (mkfifo(dest, source_stat.st_mode) < 0) { bb_perror_msg("cannot create fifo `%s'", dest); return -1; } } else if (S_ISLNK(source_stat.st_mode)) { char *lpath; lpath = xreadlink(source); if (symlink(lpath, dest) < 0) { bb_perror_msg("cannot create symlink `%s'", dest); return -1; } free(lpath); #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) if (flags & FILEUTILS_PRESERVE_STATUS) if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0) bb_perror_msg("unable to preserve ownership of `%s'", dest); #endif #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS add_to_ino_dev_hashtable(&source_stat, dest); #endif return 0; } #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS if (! S_ISDIR(source_stat.st_mode)) { add_to_ino_dev_hashtable(&source_stat, dest); } #endif end: if (flags & FILEUTILS_PRESERVE_STATUS) { struct utimbuf times; times.actime = source_stat.st_atime; times.modtime = source_stat.st_mtime; if (utime(dest, ×) < 0) bb_perror_msg("unable to preserve times of `%s'", dest); if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) { source_stat.st_mode &= ~(S_ISUID | S_ISGID); bb_perror_msg("unable to preserve ownership of `%s'", dest); } if (chmod(dest, source_stat.st_mode) < 0) bb_perror_msg("unable to preserve permissions of `%s'", dest); } return status; }