/* Grab a filename. Whitespace at start is skipped, then goes to EOL. */ static int parse_file_cmd(sed_cmd_t * sed_cmd, const char *filecmdstr, char **retval) { int start = 0, idx, hack=0; /* Skip whitespace, then grab filename to end of line */ while (isspace(filecmdstr[start])) start++; idx=start; while(filecmdstr[idx] && filecmdstr[idx]!='\n') idx++; /* If lines glued together, put backslash back. */ if(filecmdstr[idx]=='\n') hack=1; if(idx==start) bb_error_msg_and_die("Empty filename"); *retval = bb_xstrndup(filecmdstr+start, idx-start+hack+1); if(hack) *(idx+*retval)='\\'; return idx; }
/* * Gets the next package field from package_buffer, seperated into the field name * and field value, it returns the int offset to the first character of the next field */ int read_package_field(const char *package_buffer, char **field_name, char **field_value) { int offset_name_start = 0; int offset_name_end = 0; int offset_value_start = 0; int offset_value_end = 0; int offset = 0; int next_offset; int name_length; int value_length; int exit_flag = FALSE; if (package_buffer == NULL) { *field_name = NULL; *field_value = NULL; return(-1); } while (1) { next_offset = offset + 1; switch (package_buffer[offset]) { case('\0'): exit_flag = TRUE; break; case(':'): if (offset_name_end == 0) { offset_name_end = offset; offset_value_start = next_offset; } /* TODO: Name might still have trailing spaces if ':' isnt * immediately after name */ break; case('\n'): /* TODO: The char next_offset may be out of bounds */ if (package_buffer[next_offset] != ' ') { exit_flag = TRUE; break; } case('\t'): case(' '): /* increment the value start point if its a just filler */ if (offset_name_start == offset) { offset_name_start++; } if (offset_value_start == offset) { offset_value_start++; } break; } if (exit_flag) { /* Check that the names are valid */ offset_value_end = offset; name_length = offset_name_end - offset_name_start; value_length = offset_value_end - offset_value_start; if (name_length == 0) { break; } if ((name_length > 0) && (value_length > 0)) { break; } /* If not valid, start fresh with next field */ exit_flag = FALSE; offset_name_start = offset + 1; offset_name_end = 0; offset_value_start = offset + 1; offset_value_end = offset + 1; offset++; } offset++; } if (name_length == 0) { *field_name = NULL; } else { *field_name = bb_xstrndup(&package_buffer[offset_name_start], name_length); } if (value_length > 0) { *field_value = bb_xstrndup(&package_buffer[offset_value_start], value_length); } else { *field_value = NULL; } return(next_offset); }
extern char get_header_ar(archive_handle_t *archive_handle) { file_header_t *typed = archive_handle->file_header; union { char raw[60]; struct { char name[16]; char date[12]; char uid[6]; char gid[6]; char mode[8]; char size[10]; char magic[2]; } formated; } ar; #ifdef CONFIG_FEATURE_AR_LONG_FILENAMES static char *ar_long_names; static unsigned int ar_long_name_size; #endif /* dont use bb_xread as we want to handle the error ourself */ if (read(archive_handle->src_fd, ar.raw, 60) != 60) { /* End Of File */ return(EXIT_FAILURE); } /* Some ar entries have a trailing '\n' after the previous data entry */ if (ar.raw[0] == '\n') { /* fix up the header, we started reading 1 byte too early */ memmove(ar.raw, &ar.raw[1], 59); ar.raw[59] = bb_xread_char(archive_handle->src_fd); archive_handle->offset++; } archive_handle->offset += 60; /* align the headers based on the header magic */ if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) { bb_error_msg_and_die("Invalid ar header"); } typed->mode = strtol(ar.formated.mode, NULL, 8); typed->mtime = atoi(ar.formated.date); typed->uid = atoi(ar.formated.uid); typed->gid = atoi(ar.formated.gid); typed->size = atoi(ar.formated.size); /* long filenames have '/' as the first character */ if (ar.formated.name[0] == '/') { #ifdef CONFIG_FEATURE_AR_LONG_FILENAMES if (ar.formated.name[1] == '/') { /* If the second char is a '/' then this entries data section * stores long filename for multiple entries, they are stored * in static variable long_names for use in future entries */ ar_long_name_size = typed->size; ar_long_names = xmalloc(ar_long_name_size); bb_xread_all(archive_handle->src_fd, ar_long_names, ar_long_name_size); archive_handle->offset += ar_long_name_size; /* This ar entries data section only contained filenames for other records * they are stored in the static ar_long_names for future reference */ return (get_header_ar(archive_handle)); /* Return next header */ } else if (ar.formated.name[1] == ' ') { /* This is the index of symbols in the file for compilers */ data_skip(archive_handle); archive_handle->offset += typed->size; return (get_header_ar(archive_handle)); /* Return next header */ } else { /* The number after the '/' indicates the offset in the ar data section (saved in variable long_name) that conatains the real filename */ const unsigned int long_offset = atoi(&ar.formated.name[1]); if (long_offset >= ar_long_name_size) { bb_error_msg_and_die("Cant resolve long filename"); } typed->name = bb_xstrdup(ar_long_names + long_offset); } #else bb_error_msg_and_die("long filenames not supported"); #endif } else { /* short filenames */ typed->name = bb_xstrndup(ar.formated.name, 16); } typed->name[strcspn(typed->name, " /")] = '\0'; if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { archive_handle->action_header(typed); if (archive_handle->sub_archive) { while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS); } else { archive_handle->action_data(archive_handle); } } else { data_skip(archive_handle); } archive_handle->offset += typed->size; /* Set the file pointer to the correct spot, we may have been reading a compressed file */ lseek(archive_handle->src_fd, archive_handle->offset, SEEK_SET); return(EXIT_SUCCESS); }
int nfsmount(const char *spec, const char *node, int *flags, char **extra_opts, char **mount_opts, int running_bg) { static char *prev_bg_host; char hostdir[1024]; CLIENT *mclient; char *hostname; char *pathname; char *old_opts; char *mounthost=NULL; char new_opts[1024]; struct timeval total_timeout; enum clnt_stat clnt_stat; static struct nfs_mount_data data; char *opt, *opteq; int val; struct hostent *hp; struct sockaddr_in server_addr; struct sockaddr_in mount_server_addr; struct pmap* pm_mnt; int msock, fsock; struct timeval retry_timeout; union { struct fhstatus nfsv2; struct mountres3 nfsv3; } status; struct stat statbuf; char *s; int port; int mountport; int proto; int bg; int soft; int intr; int posix; int nocto; int noac; int nolock; int retry; int tcp; int mountprog; int mountvers; int nfsprog; int nfsvers; int retval; time_t t; time_t prevt; time_t timeout; find_kernel_nfs_mount_version(); retval = EX_FAIL; msock = fsock = -1; mclient = NULL; if (strlen(spec) >= sizeof(hostdir)) { bb_error_msg("excessively long host:dir argument"); goto fail; } strcpy(hostdir, spec); if ((s = strchr(hostdir, ':'))) { hostname = hostdir; pathname = s + 1; *s = '\0'; /* Ignore all but first hostname in replicated mounts until they can be fully supported. ([email protected]) */ if ((s = strchr(hostdir, ','))) { *s = '\0'; bb_error_msg("warning: multiple hostnames not supported"); } } else { bb_error_msg("directory to mount not in host:dir format"); goto fail; } server_addr.sin_family = AF_INET; #ifdef HAVE_inet_aton if (!inet_aton(hostname, &server_addr.sin_addr)) #endif { if ((hp = gethostbyname(hostname)) == NULL) { bb_herror_msg("%s", hostname); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { bb_error_msg("got bad hp->h_length"); hp->h_length = sizeof(struct in_addr); } memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } } memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); /* add IP address to mtab options for use when unmounting */ s = inet_ntoa(server_addr.sin_addr); old_opts = *extra_opts; if (!old_opts) old_opts = ""; if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { bb_error_msg("excessively long option argument"); goto fail; } sprintf(new_opts, "%s%saddr=%s", old_opts, *old_opts ? "," : "", s); *extra_opts = bb_xstrdup(new_opts); /* Set default options. * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to * let the kernel decide. * timeo is filled in after we know whether it'll be TCP or UDP. */ memset(&data, 0, sizeof(data)); data.retrans = 3; data.acregmin = 3; data.acregmax = 60; data.acdirmin = 30; data.acdirmax = 60; #if NFS_MOUNT_VERSION >= 2 data.namlen = NAME_MAX; #endif bg = 0; soft = 0; intr = 0; posix = 0; nocto = 0; nolock = 0; noac = 0; retry = 10000; /* 10000 minutes ~ 1 week */ tcp = 0; mountprog = MOUNTPROG; mountvers = 0; port = 0; mountport = 0; nfsprog = NFS_PROGRAM; nfsvers = 0; /* parse options */ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { if ((opteq = strchr(opt, '='))) { val = atoi(opteq + 1); *opteq = '\0'; if (!strcmp(opt, "rsize")) data.rsize = val; else if (!strcmp(opt, "wsize")) data.wsize = val; else if (!strcmp(opt, "timeo")) data.timeo = val; else if (!strcmp(opt, "retrans")) data.retrans = val; else if (!strcmp(opt, "acregmin")) data.acregmin = val; else if (!strcmp(opt, "acregmax")) data.acregmax = val; else if (!strcmp(opt, "acdirmin")) data.acdirmin = val; else if (!strcmp(opt, "acdirmax")) data.acdirmax = val; else if (!strcmp(opt, "actimeo")) { data.acregmin = val; data.acregmax = val; data.acdirmin = val; data.acdirmax = val; } else if (!strcmp(opt, "retry")) retry = val; else if (!strcmp(opt, "port")) port = val; else if (!strcmp(opt, "mountport")) mountport = val; else if (!strcmp(opt, "mounthost")) mounthost=bb_xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,")); else if (!strcmp(opt, "mountprog")) mountprog = val; else if (!strcmp(opt, "mountvers")) mountvers = val; else if (!strcmp(opt, "nfsprog")) nfsprog = val; else if (!strcmp(opt, "nfsvers") || !strcmp(opt, "vers")) nfsvers = val; else if (!strcmp(opt, "proto")) { if (!strncmp(opteq+1, "tcp", 3)) tcp = 1; else if (!strncmp(opteq+1, "udp", 3)) tcp = 0; else printf(_("Warning: Unrecognized proto= option.\n")); } else if (!strcmp(opt, "namlen")) { #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.namlen = val; else #endif printf(_("Warning: Option namlen is not supported.\n")); } else if (!strcmp(opt, "addr")) /* ignore */; else { printf(_("unknown nfs mount parameter: " "%s=%d\n"), opt, val); goto fail; } } else { val = 1; if (!strncmp(opt, "no", 2)) { val = 0; opt += 2; } if (!strcmp(opt, "bg")) bg = val; else if (!strcmp(opt, "fg")) bg = !val; else if (!strcmp(opt, "soft")) soft = val; else if (!strcmp(opt, "hard")) soft = !val; else if (!strcmp(opt, "intr")) intr = val; else if (!strcmp(opt, "posix")) posix = val; else if (!strcmp(opt, "cto")) nocto = !val; else if (!strcmp(opt, "ac")) noac = !val; else if (!strcmp(opt, "tcp")) tcp = val; else if (!strcmp(opt, "udp")) tcp = !val; else if (!strcmp(opt, "lock")) { if (nfs_mount_version >= 3) nolock = !val; else printf(_("Warning: option nolock is not supported.\n")); } else { printf(_("unknown nfs mount option: " "%s%s\n"), val ? "" : "no", opt); goto fail; } } } proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP; data.flags = (soft ? NFS_MOUNT_SOFT : 0) | (intr ? NFS_MOUNT_INTR : 0) | (posix ? NFS_MOUNT_POSIX : 0) | (nocto ? NFS_MOUNT_NOCTO : 0) | (noac ? NFS_MOUNT_NOAC : 0); #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.flags |= (tcp ? NFS_MOUNT_TCP : 0); #endif #if NFS_MOUNT_VERSION >= 3 if (nfs_mount_version >= 3) data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); #endif if (nfsvers > MAX_NFSPROT) { bb_error_msg("NFSv%d not supported!", nfsvers); return 0; } if (mountvers > MAX_NFSPROT) { bb_error_msg("NFSv%d not supported!", nfsvers); return 0; } if (nfsvers && !mountvers) mountvers = (nfsvers < 3) ? 1 : nfsvers; if (nfsvers && nfsvers < mountvers) { mountvers = nfsvers; } /* Adjust options if none specified */ if (!data.timeo) data.timeo = tcp ? 70 : 7; #ifdef NFS_MOUNT_DEBUG printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", data.rsize, data.wsize, data.timeo, data.retrans); printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", port, bg, retry, data.flags); printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", mountprog, mountvers, nfsprog, nfsvers); printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", (data.flags & NFS_MOUNT_SOFT) != 0, (data.flags & NFS_MOUNT_INTR) != 0, (data.flags & NFS_MOUNT_POSIX) != 0, (data.flags & NFS_MOUNT_NOCTO) != 0, (data.flags & NFS_MOUNT_NOAC) != 0); #if NFS_MOUNT_VERSION >= 2 printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0); #endif #endif data.version = nfs_mount_version; *mount_opts = (char *) &data; if (*flags & MS_REMOUNT) return 0; /* * If the previous mount operation on the same host was * backgrounded, and the "bg" for this mount is also set, * give up immediately, to avoid the initial timeout. */ if (bg && !running_bg && prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { if (retry > 0) retval = EX_BG; return retval; } /* create mount deamon client */ /* See if the nfs host = mount host. */ if (mounthost) { if (mounthost[0] >= '0' && mounthost[0] <= '9') { mount_server_addr.sin_family = AF_INET; mount_server_addr.sin_addr.s_addr = inet_addr(hostname); } else { if ((hp = gethostbyname(mounthost)) == NULL) { bb_herror_msg("%s", mounthost); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { bb_error_msg("got bad hp->h_length?"); hp->h_length = sizeof(struct in_addr); } mount_server_addr.sin_family = AF_INET; memcpy(&mount_server_addr.sin_addr, hp->h_addr, hp->h_length); } } } /* * The following loop implements the mount retries. On the first * call, "running_bg" is 0. When the mount times out, and the * "bg" option is set, the exit status EX_BG will be returned. * For a backgrounded mount, there will be a second call by the * child process with "running_bg" set to 1. * * The case where the mount point is not present and the "bg" * option is set, is treated as a timeout. This is done to * support nested mounts. * * The "retry" count specified by the user is the number of * minutes to retry before giving up. * * Only the first error message will be displayed. */ retry_timeout.tv_sec = 3; retry_timeout.tv_usec = 0; total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; timeout = time(NULL) + 60 * retry; prevt = 0; t = 30; val = 1; for (;;) { if (bg && stat(node, &statbuf) == -1) { if (running_bg) { sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ val *= 2; if (val > 30) val = 30; } } else { /* be careful not to use too many CPU cycles */ if (t - prevt < 30) sleep(30); pm_mnt = get_mountport(&mount_server_addr, mountprog, mountvers, proto, mountport); /* contact the mount daemon via TCP */ mount_server_addr.sin_port = htons(pm_mnt->pm_port); msock = RPC_ANYSOCK; switch (pm_mnt->pm_prot) { case IPPROTO_UDP: mclient = clntudp_create(&mount_server_addr, pm_mnt->pm_prog, pm_mnt->pm_vers, retry_timeout, &msock); if (mclient) break; mount_server_addr.sin_port = htons(pm_mnt->pm_port); msock = RPC_ANYSOCK; case IPPROTO_TCP: mclient = clnttcp_create(&mount_server_addr, pm_mnt->pm_prog, pm_mnt->pm_vers, &msock, 0, 0); break; default: mclient = 0; } if (mclient) { /* try to mount hostname:pathname */ mclient->cl_auth = authunix_create_default(); /* make pointers in xdr_mountres3 NULL so * that xdr_array allocates memory for us */ memset(&status, 0, sizeof(status)); if (pm_mnt->pm_vers == 3) clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &pathname, (xdrproc_t) xdr_mountres3, (caddr_t) &status, total_timeout); else clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &pathname, (xdrproc_t) xdr_fhstatus, (caddr_t) &status, total_timeout); if (clnt_stat == RPC_SUCCESS) break; /* we're done */ if (errno != ECONNREFUSED) { clnt_perror(mclient, "mount"); goto fail; /* don't retry */ } if (!running_bg && prevt == 0) clnt_perror(mclient, "mount"); auth_destroy(mclient->cl_auth); clnt_destroy(mclient); mclient = 0; close(msock); } else { if (!running_bg && prevt == 0) clnt_pcreateerror("mount"); } prevt = t; } if (!bg) goto fail; if (!running_bg) { prev_bg_host = bb_xstrdup(hostname); if (retry > 0) retval = EX_BG; goto fail; } t = time(NULL); if (t >= timeout) goto fail; } nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers; if (nfsvers == 2) { if (status.nfsv2.fhs_status != 0) { bb_error_msg("%s:%s failed, reason given by server: %s", hostname, pathname, nfs_strerror(status.nfsv2.fhs_status)); goto fail; } memcpy(data.root.data, (char *) status.nfsv2.fhstatus_u.fhs_fhandle, NFS_FHSIZE); #if NFS_MOUNT_VERSION >= 4 data.root.size = NFS_FHSIZE; memcpy(data.old_root.data, (char *) status.nfsv2.fhstatus_u.fhs_fhandle, NFS_FHSIZE); #endif } else { #if NFS_MOUNT_VERSION >= 4 fhandle3 *my_fhandle; if (status.nfsv3.fhs_status != 0) { bb_error_msg("%s:%s failed, reason given by server: %s", hostname, pathname, nfs_strerror(status.nfsv3.fhs_status)); goto fail; } my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle; memset(data.old_root.data, 0, NFS_FHSIZE); memset(&data.root, 0, sizeof(data.root)); data.root.size = my_fhandle->fhandle3_len; memcpy(data.root.data, (char *) my_fhandle->fhandle3_val, my_fhandle->fhandle3_len); data.flags |= NFS_MOUNT_VER3; #endif } /* create nfs socket for kernel */ if (tcp) { if (nfs_mount_version < 3) { printf(_("NFS over TCP is not supported.\n")); goto fail; } fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fsock < 0) { perror(_("nfs socket")); goto fail; } if (bindresvport(fsock, 0) < 0) { perror(_("nfs bindresvport")); goto fail; } if (port == 0) { server_addr.sin_port = PMAPPORT; port = pmap_getport(&server_addr, nfsprog, nfsvers, tcp ? IPPROTO_TCP : IPPROTO_UDP); if (port == 0) port = NFS_PORT; #ifdef NFS_MOUNT_DEBUG else printf(_("used portmapper to find NFS port\n")); #endif } #ifdef NFS_MOUNT_DEBUG printf(_("using port %d for nfs deamon\n"), port); #endif server_addr.sin_port = htons(port); /* * connect() the socket for kernels 1.3.10 and below only, * to avoid problems with multihomed hosts. * --Swen */ if (get_kernel_revision() <= 66314 && connect(fsock, (struct sockaddr *) &server_addr, sizeof (server_addr)) < 0) { perror(_("nfs connect")); goto fail; } /* prepare data structure for kernel */ data.fd = fsock; memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); strncpy(data.hostname, hostname, sizeof(data.hostname)); /* clean up */ auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); return 0; /* abort */ fail: if (msock != -1) { if (mclient) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); } close(msock); } if (fsock != -1) close(fsock); return retval; }
static char *get_key(char *str, struct sort_key *key, int flags) { int start=0,end,len,i,j; /* Special case whole string, so we don't have to make a copy */ if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3] && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str; /* Find start of key on first pass, end on second pass*/ len=strlen(str); for(j=0;j<2;j++) { if(!key->range[2*j]) end=len; /* Loop through fields */ else { end=0; for(i=1;i<key->range[2*j]+j;i++) { /* Skip leading blanks or first separator */ if(str[end]) { if(key_separator) { if(str[end]==key_separator) end++; } else if(isspace(str[end])) while(isspace(str[end])) end++; } /* Skip body of key */ for(;str[end];end++) { if(key_separator) { if(str[end]==key_separator) break; } else if(isspace(str[end])) break; } } } if(!j) start=end; } /* Key with explicit separator starts after separator */ if(key_separator && str[start]==key_separator) start++; /* Strip leading whitespace if necessary */ if(flags&FLAG_b) while(isspace(str[start])) start++; /* Strip trailing whitespace if necessary */ if(flags&FLAG_bb) while(end>start && isspace(str[end-1])) end--; /* Handle offsets on start and end */ if(key->range[3]) { end+=key->range[3]-1; if(end>len) end=len; } if(key->range[1]) { start+=key->range[1]-1; if(start>len) start=len; } /* Make the copy */ if(end<start) end=start; str=bb_xstrndup(str+start,end-start); /* Handle -d */ if(flags&FLAG_d) { for(start=end=0;str[end];end++) if(isspace(str[end]) || isalnum(str[end])) str[start++]=str[end]; str[start]=0; } /* Handle -i */ if(flags&FLAG_i) { for(start=end=0;str[end];end++) if(isprint(str[end])) str[start++]=str[end]; str[start]=0; } /* Handle -f */ if(flags*FLAG_f) for(i=0;str[i];i++) str[i]=toupper(str[i]); return str; }
/* * This function builds a list of dependency rules from /lib/modules/`uname -r`\modules.dep. * It then fills every modules and aliases with their default options, found by parsing * modprobe.conf (or modules.conf, or conf.modules). */ static struct dep_t *build_dep ( void ) { int fd; struct utsname un; struct dep_t *first = 0; struct dep_t *current = 0; char buffer[2048]; char *filename; int continuation_line = 0; int k_version; k_version = 0; if ( uname ( &un )) bb_error_msg_and_die("can't determine kernel version"); if (un.release[0] == '2') { k_version = un.release[2] - '0'; } filename = bb_xasprintf("/lib/modules/%s/modules.dep", un.release ); fd = open ( filename, O_RDONLY ); if (ENABLE_FEATURE_CLEAN_UP) free(filename); if (fd < 0) { /* Ok, that didn't work. Fall back to looking in /lib/modules */ if (( fd = open ( "/lib/modules/modules.dep", O_RDONLY )) < 0 ) { return 0; } } while ( reads ( fd, buffer, sizeof( buffer ))) { int l = strlen ( buffer ); char *p = 0; while ( l > 0 && isspace ( buffer [l-1] )) { buffer [l-1] = 0; l--; } if ( l == 0 ) { continuation_line = 0; continue; } /* Is this a new module dep description? */ if ( !continuation_line ) { /* find the dep beginning */ char *col = strchr ( buffer, ':' ); char *dot = col; if ( col ) { /* This line is a dep description */ char *mods; char *modpath; char *mod; /* Find the beginning of the module file name */ *col = 0; mods = strrchr ( buffer, '/' ); if ( !mods ) mods = buffer; /* no path for this module */ else mods++; /* there was a path for this module... */ /* find the path of the module */ modpath = strchr ( buffer, '/' ); /* ... and this is the path */ if ( !modpath ) modpath = buffer; /* module with no path */ /* find the end of the module name in the file name */ if ( ENABLE_FEATURE_2_6_MODULES && (k_version > 4) && ( *(col-3) == '.' ) && ( *(col-2) == 'k' ) && ( *(col-1) == 'o' ) ) dot = col - 3; else if (( *(col-2) == '.' ) && ( *(col-1) == 'o' )) dot = col - 2; mod = bb_xstrndup ( mods, dot - mods ); /* enqueue new module */ if ( !current ) { first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t )); } else { current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t )); current = current-> m_next; } current-> m_name = mod; current-> m_path = bb_xstrdup(modpath); current-> m_options = NULL; current-> m_isalias = 0; current-> m_depcnt = 0; current-> m_deparr = 0; current-> m_next = 0; p = col + 1; } else /* this line is not a dep description */ p = 0; } else /* It's a dep description continuation */ p = buffer; while ( p && *p && isblank(*p)) p++; /* p points to the first dependable module; if NULL, no dependable module */ if ( p && *p ) { char *end = &buffer [l-1]; char *deps; char *dep; char *next; int ext = 0; while ( isblank ( *end ) || ( *end == '\\' )) end--; do { /* search the end of the dependency */ next = strchr (p, ' ' ); if (next) { *next = 0; next--; } else next = end; /* find the beginning of the module file name */ deps = strrchr ( p, '/' ); if ( !deps || ( deps < p )) { deps = p; while ( isblank ( *deps )) deps++; } else deps++; /* find the end of the module name in the file name */ if ( ENABLE_FEATURE_2_6_MODULES && (k_version > 4) && ( *(next-2) == '.' ) && ( *(next-1) == 'k' ) && ( *next == 'o' ) ) ext = 3; else if (( *(next-1) == '.' ) && ( *next == 'o' )) ext = 2; /* Cope with blank lines */ if ((next-deps-ext+1) <= 0) continue; dep = bb_xstrndup ( deps, next - deps - ext + 1 ); /* Add the new dependable module name */ current-> m_depcnt++; current-> m_deparr = (char **) xrealloc ( current-> m_deparr, sizeof ( char *) * current-> m_depcnt ); current-> m_deparr [current-> m_depcnt - 1] = dep; p = next + 2; } while (next < end); } /* is there other dependable module(s) ? */ if ( buffer [l-1] == '\\' ) continuation_line = 1; else continuation_line = 0; } close ( fd ); /* * First parse system-specific options and aliases * as they take precedence over the kernel ones. */ if (!ENABLE_FEATURE_2_6_MODULES || ( fd = open ( "/etc/modprobe.conf", O_RDONLY )) < 0 ) if (( fd = open ( "/etc/modules.conf", O_RDONLY )) < 0 ) fd = open ( "/etc/conf.modules", O_RDONLY ); if (fd >= 0) { include_conf (&first, ¤t, buffer, sizeof(buffer), fd); close(fd); } /* Only 2.6 has a modules.alias file */ if (ENABLE_FEATURE_2_6_MODULES) { /* Parse kernel-declared aliases */ filename = bb_xasprintf("/lib/modules/%s/modules.alias", un.release); if ((fd = open ( filename, O_RDONLY )) < 0) { /* Ok, that didn't work. Fall back to looking in /lib/modules */ fd = open ( "/lib/modules/modules.alias", O_RDONLY ); } if (ENABLE_FEATURE_CLEAN_UP) free(filename); if (fd >= 0) { include_conf (&first, ¤t, buffer, sizeof(buffer), fd); close(fd); } } return first; }
int find_main(int argc, char **argv) { int dereference = FALSE; int i, firstopt, status = EXIT_SUCCESS; for (firstopt = 1; firstopt < argc; firstopt++) { if (argv[firstopt][0] == '-') break; } /* Parse any options */ for (i = firstopt; i < argc; i++) { if (strcmp(argv[i], "-follow") == 0) dereference = TRUE; else if (strcmp(argv[i], "-print") == 0) { ; } else if (strcmp(argv[i], "-name") == 0) { if (++i == argc) bb_error_msg_and_die(msg_req_arg, "-name"); pattern = argv[i]; #ifdef CONFIG_FEATURE_FIND_TYPE } else if (strcmp(argv[i], "-type") == 0) { if (++i == argc) bb_error_msg_and_die(msg_req_arg, "-type"); type_mask = find_type(argv[i]); #endif #ifdef CONFIG_FEATURE_FIND_PERM } else if (strcmp(argv[i], "-perm") == 0) { char *end; if (++i == argc) bb_error_msg_and_die(msg_req_arg, "-perm"); perm_mask = strtol(argv[i], &end, 8); if ((end[0] != '\0') || (perm_mask > 07777)) bb_error_msg_and_die(msg_invalid_arg, argv[i], "-perm"); if ((perm_char = argv[i][0]) == '-') perm_mask = -perm_mask; #endif #ifdef CONFIG_FEATURE_FIND_MTIME } else if (strcmp(argv[i], "-mtime") == 0) { char *end; if (++i == argc) bb_error_msg_and_die(msg_req_arg, "-mtime"); mtime_days = strtol(argv[i], &end, 10); if (end[0] != '\0') bb_error_msg_and_die(msg_invalid_arg, argv[i], "-mtime"); if ((mtime_char = argv[i][0]) == '-') mtime_days = -mtime_days; #endif #ifdef CONFIG_FEATURE_FIND_XDEV } else if (strcmp(argv[i], "-xdev") == 0) { struct stat stbuf; xdev_count = ( firstopt - 1 ) ? ( firstopt - 1 ) : 1; xdev_dev = xmalloc ( xdev_count * sizeof( dev_t )); if ( firstopt == 1 ) { if ( stat ( ".", &stbuf ) < 0 ) bb_error_msg_and_die("could not stat '.'" ); xdev_dev [0] = stbuf. st_dev; } else { for (i = 1; i < firstopt; i++) { if ( stat ( argv [i], &stbuf ) < 0 ) bb_error_msg_and_die("could not stat '%s'", argv [i] ); xdev_dev [i-1] = stbuf. st_dev; } } #endif #ifdef CONFIG_FEATURE_FIND_NEWER } else if (strcmp(argv[i], "-newer") == 0) { struct stat stat_newer; if (++i == argc) bb_error_msg_and_die(msg_req_arg, "-newer"); if (stat (argv[i], &stat_newer) != 0) bb_error_msg_and_die("file %s not found", argv[i]); newer_mtime = stat_newer.st_mtime; #endif #ifdef CONFIG_FEATURE_FIND_INUM } else if (strcmp(argv[i], "-inum") == 0) { char *end; if (++i == argc) bb_error_msg_and_die(msg_req_arg, "-inum"); inode_num = strtol(argv[i], &end, 10); if (end[0] != '\0') bb_error_msg_and_die(msg_invalid_arg, argv[i], "-inum"); #endif #ifdef CONFIG_FEATURE_FIND_EXEC } else if (strcmp(argv[i], "-exec") == 0) { int b_pos; char *cmd_string = ""; while (i++) { if (i == argc) bb_error_msg_and_die(msg_req_arg, "-exec"); if (*argv[i] == ';') break; cmd_string = bb_xasprintf("%s %s", cmd_string, argv[i]); } if (*cmd_string == 0) bb_error_msg_and_die(msg_req_arg, "-exec"); cmd_string++; exec_str = xmalloc(sizeof(char *)); while ((b_pos = strstr(cmd_string, "{}") - cmd_string), (b_pos >= 0)) { num_matches++; exec_str = xrealloc(exec_str, (num_matches + 1) * sizeof(char *)); exec_str[num_matches - 1] = bb_xstrndup(cmd_string, b_pos); cmd_string += b_pos + 2; } exec_str[num_matches] = bb_xstrdup(cmd_string); exec_opt = 1; #endif } else bb_show_usage(); } if (firstopt == 1) { if (! recursive_action(".", TRUE, dereference, FALSE, fileAction, fileAction, NULL)) status = EXIT_FAILURE; } else { for (i = 1; i < firstopt; i++) { if (! recursive_action(argv[i], TRUE, dereference, FALSE, fileAction, fileAction, NULL)) status = EXIT_FAILURE; } } return status; }