/* Copy files from source_dir to fs */ static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino, const char *source_dir, ext2_ino_t root, struct hdlinks_s *hdlinks) { const char *name; DIR *dh; struct dirent *dent; struct stat st; char ln_target[PATH_MAX]; unsigned int save_inode; ext2_ino_t ino; errcode_t retval; int read_cnt; int hdlink; if (chdir(source_dir) < 0) { com_err(__func__, errno, _("while changing working directory to \"%s\""), source_dir); return errno; } if (!(dh = opendir("."))) { com_err(__func__, errno, _("while opening directory \"%s\""), source_dir); return errno; } while ((dent = readdir(dh))) { if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, ".."))) continue; lstat(dent->d_name, &st); name = dent->d_name; /* Check for hardlinks */ save_inode = 0; if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && st.st_nlink > 1) { hdlink = is_hardlink(hdlinks, st.st_dev, st.st_ino); if (hdlink >= 0) { retval = add_link(fs, parent_ino, hdlinks->hdl[hdlink].dst_ino, name); if (retval) { com_err(__func__, retval, "while linking %s", name); return retval; } continue; } else save_inode = 1; } switch(st.st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: retval = do_mknod_internal(fs, parent_ino, name, &st); if (retval) { com_err(__func__, retval, _("while creating special file " "\"%s\""), name); return retval; } break; case S_IFSOCK: /* FIXME: there is no make socket function atm. */ com_err(__func__, 0, _("ignoring socket file \"%s\""), name); continue; case S_IFLNK: read_cnt = readlink(name, ln_target, sizeof(ln_target)); if (read_cnt == -1) { com_err(__func__, errno, _("while trying to readlink \"%s\""), name); return errno; } ln_target[read_cnt] = '\0'; retval = do_symlink_internal(fs, parent_ino, name, ln_target, root); if (retval) { com_err(__func__, retval, _("while writing symlink\"%s\""), name); return retval; } break; case S_IFREG: retval = do_write_internal(fs, parent_ino, name, name, root); if (retval) { com_err(__func__, retval, _("while writing file \"%s\""), name); return retval; } break; case S_IFDIR: retval = do_mkdir_internal(fs, parent_ino, name, &st, root); if (retval) { com_err(__func__, retval, _("while making dir \"%s\""), name); return retval; } retval = ext2fs_namei(fs, root, parent_ino, name, &ino); if (retval) { com_err(name, retval, 0); return retval; } /* Populate the dir recursively*/ retval = __populate_fs(fs, ino, name, root, hdlinks); if (retval) { com_err(__func__, retval, _("while adding dir \"%s\""), name); return retval; } if (chdir("..")) { com_err(__func__, errno, _("during cd ..")); return errno; } break; default: com_err(__func__, 0, _("ignoring entry \"%s\""), name); } retval = ext2fs_namei(fs, root, parent_ino, name, &ino); if (retval) { com_err(name, retval, 0); return retval; } retval = set_inode_extra(fs, parent_ino, ino, &st); if (retval) { com_err(__func__, retval, _("while setting inode for \"%s\""), name); return retval; } /* Save the hardlink ino */ if (save_inode) { /* * Check whether need more memory, and we don't need * free() since the lifespan will be over after the fs * populated. */ if (hdlinks->count == hdlinks->size) { void *p = realloc(hdlinks->hdl, (hdlinks->size + HDLINK_CNT) * sizeof(struct hdlink_s)); if (p == NULL) { com_err(name, errno, _("Not enough memory")); return errno; } hdlinks->hdl = p; hdlinks->size += HDLINK_CNT; } hdlinks->hdl[hdlinks->count].src_dev = st.st_dev; hdlinks->hdl[hdlinks->count].src_ino = st.st_ino; hdlinks->hdl[hdlinks->count].dst_ino = ino; hdlinks->count++; } } closedir(dh); return retval; }
int processdir(int level, const char *base, const char *dirname, struct stat *sb, struct filenode *dir, struct filenode *root, int curroffset) { DIR *dirfd; struct dirent *dp; struct filenode *n, *link; struct excludes *pe; if (level <= 1) { /* Ok, to make sure . and .. are handled correctly * we add them first. Note also that we alloc them * first to get to know the real name */ link = newnode(base, ".", curroffset); if (!lstat(link->realname, sb)) { setnode(link, sb->st_dev, sb->st_ino, sb->st_mode); append(&dir->dirlist, link); /* special case for root node - '..'s in subdirs should link to * '.' of root node, not root node itself. */ dir->dirlist.owner = link; curroffset = alignnode(link, curroffset, 0) + spaceneeded(link); n = newnode(base, "..", curroffset); if (!lstat(n->realname, sb)) { setnode(n, sb->st_dev, sb->st_ino, sb->st_mode); append(&dir->dirlist, n); n->orig_link = link; curroffset = alignnode(n, curroffset, 0) + spaceneeded(n); } } } dirfd = opendir(dir->realname); while((dp = readdir(dirfd))) { /* don't process main . and .. twice */ if (level <= 1 && (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) continue; n = newnode(base, dp->d_name, curroffset); /* Process exclude list. */ for (pe = excludelist; pe; pe = pe->next) { if (!nodematch(pe->pattern, n)) { freenode(n); break; } } if (pe) continue; if (lstat(n->realname, sb)) { fprintf(stderr, "ignoring '%s' (lstat failed)\n", n->realname); freenode(n); continue; } /* Handle special names */ if ( n->name[0] == '@' ) { if (S_ISLNK(sb->st_mode)) { /* this is a link to follow at build time */ n->name = n->name + 1; /* strip off the leading @ */ memset(bigbuf, 0, sizeof(bigbuf)); readlink(n->realname, bigbuf, sizeof(bigbuf)); n->realname = strdup(bigbuf); if (lstat(n->realname, sb)) { fprintf(stderr, "ignoring '%s' (lstat failed)\n", n->realname); freenode(n); continue; } } else if (S_ISREG(sb->st_mode) && sb->st_size == 0) { /* * special file @name,[bcp..],major,minor */ char devname[32]; char type; int major; int minor; if (sscanf(n->name, "@%[a-zA-Z0-9],%c,%d,%d", devname, &type, &major, &minor) == 4 ) { strcpy(n->name, devname); sb->st_rdev = makedev(major, minor); sb->st_mode &= ~S_IFMT; switch (type) { case 'c': case 'u': sb->st_mode |= S_IFCHR; break; case 'b': sb->st_mode |= S_IFBLK; break; case 'p': sb->st_mode |= S_IFIFO; break; default: fprintf(stderr, "Invalid special device type '%c' " "for file %s\n", type, n->realname); freenode(n); continue; } } } } setnode(n, sb->st_dev, sb->st_ino, sb->st_mode); /* Skip unreadable files/dirs */ if (!S_ISLNK(n->modes) && access(n->realname, R_OK)) { fprintf(stderr, "ignoring '%s' (access failed)\n", n->realname); freenode(n); continue; } /* Look up old links */ if ( strcmp(n->name, ".") == 0 ) { append(&dir->dirlist, n); link = n->parent; } else if (strcmp(n->name, "..") == 0) { append(&dir->dirlist, n); link = n->parent->parent; } else { link = findnode(root, n->ondev, n->onino); append(&dir->dirlist, n); } if (link) { n->orig_link = link; curroffset = alignnode(n, curroffset, 0) + spaceneeded(n); continue; } if (S_ISREG(sb->st_mode)) { curroffset = alignnode(n, curroffset, spaceneeded(n)); n->size = sb->st_size; } else curroffset = alignnode(n, curroffset, 0); if (S_ISLNK(sb->st_mode)) { n->size = sb->st_size; } curroffset += spaceneeded(n); if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode)) { n->devnode = sb->st_rdev; } if (S_ISDIR(sb->st_mode)) { if (!strcmp(n->name, "..")) { curroffset = processdir(level+1, dir->realname, dp->d_name, sb, dir, root, curroffset); } else { curroffset = processdir(level+1, n->realname, dp->d_name, sb, n, root, curroffset); } } } closedir(dirfd); return curroffset; }
int daemon_listen(DRIVER_CTX *DTX) { struct sockaddr_in local_addr, remote_addr; THREAD_CTX *TTX = NULL; fd_set master, read_fds; pthread_attr_t attr; struct timeval tv; int fdmax, yes = 1; int domain = 0; /* listening on domain socket? */ int listener; /* listener fd */ int i; int port = 24, queue = 32; /* default port and queue size */ signal(SIGPIPE, SIG_IGN); signal(SIGINT, process_signal); signal(SIGTERM, process_signal); signal(SIGHUP, process_signal); if (_ds_read_attribute(agent_config, "ServerPort")) port = atoi(_ds_read_attribute(agent_config, "ServerPort")); if (_ds_read_attribute(agent_config, "ServerQueueSize")) queue = atoi(_ds_read_attribute(agent_config, "ServerQueueSize")); if (_ds_read_attribute(agent_config, "ServerDomainSocketPath")) domain = 1; /* initialize */ FD_ZERO(&master); FD_ZERO(&read_fds); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); /* Bind (domain socket) */ if (domain) { struct sockaddr_un saun; char *address = strdup(_ds_read_attribute(agent_config, "ServerDomainSocketPath")); mode_t mask; int len; mask = umask (000); if (_ds_match_attribute(agent_config, "ServerDomainSymlink", "on")) { /* treat ServerDomainSymlink as a symlink path */ char* old_address = address; address = malloc(sizeof(char) * (strlen(address) + 8)); sprintf(address, "%s.%d", old_address, getpid()); free(old_address); /* address now points to the actual socket, ending in pid */ } listener = socket(AF_UNIX, SOCK_STREAM, 0); if (listener == -1) { LOG(LOG_CRIT, ERR_DAEMON_SOCKET, strerror(errno)); umask (mask); return(EFAILURE); } memset(&saun, 0, sizeof(struct sockaddr_un)); saun.sun_family = AF_UNIX; strcpy(saun.sun_path, address); unlink(address); len = sizeof(saun.sun_family) + strlen(saun.sun_path) + 1; LOGDEBUG(INFO_DAEMON_DOMAINSOCK, address); if (bind(listener, (struct sockaddr *) &saun, len)<0) { close(listener); LOG(LOG_CRIT, INFO_DAEMON_DOMAINSOCK, address, strerror(errno)); umask (mask); return EFAILURE; } if (_ds_match_attribute(agent_config, "ServerDomainSymlink", "on")) { /* install symlink for the domain socket */ char *link_address = _ds_read_attribute(agent_config, "ServerDomainSocketPath"); /* to atomically replace the socket symlink, make the symlink elsewhere then move it */ char* new_link_address = malloc(sizeof(char) * (strlen(link_address) + 4)); sprintf(new_link_address, "%s.new", link_address); symlink(address, new_link_address); rename(new_link_address, link_address); free(new_link_address); } umask (mask); free(address); /* Bind to a TCP socket */ } else { listener = socket(AF_INET, SOCK_STREAM, 0); if (listener == -1) { LOG(LOG_CRIT, ERR_DAEMON_SOCKET, strerror(errno)); return(EFAILURE); } if (setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { close(listener); LOG(LOG_CRIT, ERR_DAEMON_SOCKOPT, "SO_REUSEADDR", strerror(errno)); return(EFAILURE); } memset(&local_addr, 0, sizeof(struct sockaddr_in)); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(port); local_addr.sin_addr.s_addr = INADDR_ANY; LOGDEBUG(INFO_DAEMON_BIND, port); if (bind(listener, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) == -1) { close(listener); LOG(LOG_CRIT, ERR_DAEMON_BIND, port, strerror(errno)); return(EFAILURE); } } /* Listen */ if (listen(listener, queue) == -1) { close(listener); LOG(LOG_CRIT, ERR_DAEMON_LISTEN, strerror(errno)); return(EFAILURE); } FD_SET(listener, &master); fdmax = listener; /* Process new connections (until death or reload) */ for(;;) { read_fds = master; tv.tv_sec = 2; tv.tv_usec = 0; if (__daemon_run == 0) { close(listener); char* address = _ds_read_attribute(agent_config, "ServerDomainSocketPath"); if (address) { if (_ds_match_attribute(agent_config, "ServerDomainSymlink", "on")) { /* unlink the actual domain socket */ char* real_address = malloc(sizeof(char) * (strlen(address) + 8)); sprintf(real_address, "%s.%d", address, getpid()); unlink (real_address); /* remove the symlink only if we still own it */ char link_target[256]; int ret = readlink(address, link_target, sizeof(link_target)-1); if (ret >= 0) { /* readlink doesn't null-terminate */ link_target[ret] = '\0'; if (!strcmp(link_target, real_address)) { unlink (address); } } free(real_address); } else unlink (address); } return 0; } if (select(fdmax+1, &read_fds, NULL, NULL, &tv)>0) { /* Process read-ready connections */ for(i=0;i<=fdmax;i++) { if (FD_ISSET(i, &read_fds)) { /* Accept new connections */ if (i == listener) { int newfd; int addrlen = sizeof(remote_addr); if ((newfd = accept(listener, (struct sockaddr *)&remote_addr, (socklen_t *) &addrlen)) == -1) { LOG(LOG_WARNING, ERR_DAEMON_ACCEPT, strerror(errno)); continue; #ifdef DEBUG } else if (!domain) { char buff[32]; LOGDEBUG("connection id %d from %s.", newfd, inet_ntoa_r(remote_addr.sin_addr, buff, sizeof(buff))); #endif } fcntl(newfd, F_SETFL, O_RDWR); setsockopt(newfd,SOL_SOCKET,TCP_NODELAY,&yes,sizeof(int)); /* * Since processing time varies, each new connection gets its own * thread, so we create a new thread context and send it on its way * */ TTX = calloc(1, sizeof(THREAD_CTX)); if (TTX == NULL) { LOG(LOG_CRIT, ERR_MEM_ALLOC); close(newfd); continue; } else { TTX->sockfd = newfd; TTX->DTX = DTX; memcpy(&TTX->remote_addr, &remote_addr, sizeof(remote_addr)); increment_thread_count(); if (pthread_create(&TTX->thread, &attr, process_connection, (void *) TTX)) { decrement_thread_count(); LOG(LOG_CRIT, ERR_DAEMON_THREAD, strerror(errno)); close(TTX->sockfd); free(TTX); continue; } } } /* if i == listener */ } /* if FD_SET else */ } /* for(i.. */ } /* if (select)... */ } /* for(;;) */ /* Shutdown - we should never get here, but who knows */ close(listener); pthread_attr_destroy(&attr); return 0; }
static int copy_internal (const char *src_path, const char *dst_path, int new_dst, dev_t device, struct dir_list *ancestors, const struct cp_options *x, int command_line_arg, int *copy_into_self, int *rename_succeeded) { struct stat src_sb; struct stat dst_sb; mode_t src_mode; mode_t src_type; char *earlier_file = NULL; char *dst_backup = NULL; int backup_succeeded = 0; int delayed_fail; int copied_as_regular = 0; int ran_chown = 0; int preserve_metadata; if (x->move_mode && rename_succeeded) *rename_succeeded = 0; *copy_into_self = 0; if ((*(x->xstat)) (src_path, &src_sb)) { error (0, errno, _("cannot stat %s"), quote (src_path)); return 1; } src_type = src_sb.st_mode; src_mode = src_sb.st_mode; if (S_ISDIR (src_type) && !x->recursive) { error (0, 0, _("omitting directory %s"), quote (src_path)); return 1; } /* Detect the case in which the same source file appears more than once on the command line and no backup option has been selected. If so, simply warn and don't copy it the second time. This check is enabled only if x->src_info is non-NULL. */ if (command_line_arg) { if ( ! S_ISDIR (src_sb.st_mode) && x->backup_type == none && seen_file (x->src_info, src_path, &src_sb)) { error (0, 0, _("warning: source file %s specified more than once"), quote (src_path)); return 0; } record_file (x->src_info, src_path, &src_sb); } if (!new_dst) { if ((*(x->xstat)) (dst_path, &dst_sb)) { if (errno != ENOENT) { error (0, errno, _("cannot stat %s"), quote (dst_path)); return 1; } else { new_dst = 1; } } else { int return_now; int ok = same_file_ok (src_path, &src_sb, dst_path, &dst_sb, x, &return_now); if (return_now) return 0; if (! ok) { error (0, 0, _("%s and %s are the same file"), quote_n (0, src_path), quote_n (1, dst_path)); return 1; } if (!S_ISDIR (dst_sb.st_mode)) { if (S_ISDIR (src_type)) { error (0, 0, _("cannot overwrite non-directory %s with directory %s"), quote_n (0, dst_path), quote_n (1, src_path)); return 1; } /* Don't let the user destroy their data, even if they try hard: This mv command must fail (likewise for cp): rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c Otherwise, the contents of b/f would be lost. In the case of `cp', b/f would be lost if the user simulated a move using cp and rm. Note that it works fine if you use --backup=numbered. */ if (command_line_arg && x->backup_type != numbered && seen_file (x->dest_info, dst_path, &dst_sb)) { error (0, 0, _("will not overwrite just-created %s with %s"), quote_n (0, dst_path), quote_n (1, src_path)); return 1; } } if (!S_ISDIR (src_type)) { if (S_ISDIR (dst_sb.st_mode)) { error (0, 0, _("cannot overwrite directory %s with non-directory"), quote (dst_path)); return 1; } if (x->update && MTIME_CMP (src_sb, dst_sb) <= 0) { /* We're using --update and the source file is older than the destination file, so there is no need to copy or move. */ /* Pretend the rename succeeded, so the caller (mv) doesn't end up removing the source file. */ if (rename_succeeded) *rename_succeeded = 1; return 0; } } /* When there is an existing destination file, we may end up returning early, and hence not copying/moving the file. This may be due to an interactive `negative' reply to the prompt about the existing file. It may also be due to the use of the --reply=no option. */ if (!S_ISDIR (src_type)) { /* cp and mv treat -i and -f differently. */ if (x->move_mode) { if ((x->interactive == I_ALWAYS_NO && UNWRITABLE (dst_path, dst_sb.st_mode)) || ((x->interactive == I_ASK_USER || (x->interactive == I_UNSPECIFIED && x->stdin_tty && UNWRITABLE (dst_path, dst_sb.st_mode))) && (overwrite_prompt (dst_path, &dst_sb), 1) && ! yesno ())) { /* Pretend the rename succeeded, so the caller (mv) doesn't end up removing the source file. */ if (rename_succeeded) *rename_succeeded = 1; return 0; } } else { if (x->interactive == I_ALWAYS_NO || (x->interactive == I_ASK_USER && (overwrite_prompt (dst_path, &dst_sb), 1) && ! yesno ())) { return 0; } } } if (x->move_mode) { /* In move_mode, DEST may not be an existing directory. */ if (S_ISDIR (dst_sb.st_mode)) { error (0, 0, _("cannot overwrite directory %s"), quote (dst_path)); return 1; } /* Don't allow user to move a directory onto a non-directory. */ if (S_ISDIR (src_sb.st_mode) && !S_ISDIR (dst_sb.st_mode)) { error (0, 0, _("cannot move directory onto non-directory: %s -> %s"), quote_n (0, src_path), quote_n (0, dst_path)); return 1; } } if (x->backup_type != none && !S_ISDIR (dst_sb.st_mode)) { char *tmp_backup = find_backup_file_name (dst_path, x->backup_type); if (tmp_backup == NULL) xalloc_die (); /* Detect (and fail) when creating the backup file would destroy the source file. Before, running the commands cd /tmp; rm -f a a~; : > a; echo A > a~; cp --b=simple a~ a would leave two zero-length files: a and a~. */ /* FIXME: but simply change e.g., the final a~ to `./a~' and the source will still be destroyed. */ if (STREQ (tmp_backup, src_path)) { const char *fmt; fmt = (x->move_mode ? _("backing up %s would destroy source; %s not moved") : _("backing up %s would destroy source; %s not copied")); error (0, 0, fmt, quote_n (0, dst_path), quote_n (1, src_path)); free (tmp_backup); return 1; } dst_backup = (char *) alloca (strlen (tmp_backup) + 1); strcpy (dst_backup, tmp_backup); free (tmp_backup); if (rename (dst_path, dst_backup)) { if (errno != ENOENT) { error (0, errno, _("cannot backup %s"), quote (dst_path)); return 1; } else { dst_backup = NULL; } } else { backup_succeeded = 1; } new_dst = 1; } else if (! S_ISDIR (dst_sb.st_mode) && (x->unlink_dest_before_opening || (x->xstat == lstat && ! S_ISREG (src_sb.st_mode)))) { if (unlink (dst_path) && errno != ENOENT) { error (0, errno, _("cannot remove %s"), quote (dst_path)); return 1; } new_dst = 1; } } } /* If the source is a directory, we don't always create the destination directory. So --verbose should not announce anything until we're sure we'll create a directory. */ if (x->verbose && !S_ISDIR (src_type)) { printf ("%s -> %s", quote_n (0, src_path), quote_n (1, dst_path)); if (backup_succeeded) printf (_(" (backup: %s)"), quote (dst_backup)); putchar ('\n'); } /* Associate the destination path with the source device and inode so that if we encounter a matching dev/ino pair in the source tree we can arrange to create a hard link between the corresponding names in the destination tree. Sometimes, when preserving links, we have to record dev/ino even though st_nlink == 1: - when using -H and processing a command line argument; that command line argument could be a symlink pointing to another command line argument. With `cp -H --preserve=link', we hard-link those two destination files. - likewise for -L except that it applies to all files, not just command line arguments. Also record directory dev/ino when using --recursive. We'll use that info to detect this problem: cp -R dir dir. FIXME-maybe: ideally, directory info would be recorded in a separate hash table, since such entries are useful only while a single command line hierarchy is being copied -- so that separate table could be cleared between command line args. Using the same hash table to preserve hard links means that it may not be cleared. */ if ((x->preserve_links && (1 < src_sb.st_nlink || (command_line_arg && x->dereference == DEREF_COMMAND_LINE_ARGUMENTS) || x->dereference == DEREF_ALWAYS)) || (x->recursive && S_ISDIR (src_type))) { earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev); } /* Did we copy this inode somewhere else (in this command line argument) and therefore this is a second hard link to the inode? */ if (earlier_file) { /* Avoid damaging the destination filesystem by refusing to preserve hard-linked directories (which are found at least in Netapp snapshot directories). */ if (S_ISDIR (src_type)) { /* If src_path and earlier_file refer to the same directory entry, then warn about copying a directory into itself. */ if (same_name (src_path, earlier_file)) { error (0, 0, _("cannot copy a directory, %s, into itself, %s"), quote_n (0, top_level_src_path), quote_n (1, top_level_dst_path)); *copy_into_self = 1; } else { error (0, 0, _("will not create hard link %s to directory %s"), quote_n (0, dst_path), quote_n (1, earlier_file)); } goto un_backup; } { int link_failed; link_failed = link (earlier_file, dst_path); /* If the link failed because of an existing destination, remove that file and then call link again. */ if (link_failed && errno == EEXIST) { if (unlink (dst_path)) { error (0, errno, _("cannot remove %s"), quote (dst_path)); goto un_backup; } link_failed = link (earlier_file, dst_path); } if (link_failed) { error (0, errno, _("cannot create hard link %s to %s"), quote_n (0, dst_path), quote_n (1, earlier_file)); goto un_backup; } return 0; } } if (x->move_mode) { if (rename (src_path, dst_path) == 0) { if (x->verbose && S_ISDIR (src_type)) printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path)); if (rename_succeeded) *rename_succeeded = 1; if (command_line_arg) { /* Record destination dev/ino/filename, so that if we are asked to overwrite that file again, we can detect it and fail. */ /* It's fine to use the _source_ stat buffer (src_sb) to get the _destination_ dev/ino, since the rename above can't have changed those, and `mv' always uses lstat. We could limit it further by operating only on non-directories. */ record_file (x->dest_info, dst_path, &src_sb); } return 0; } /* FIXME: someday, consider what to do when moving a directory into itself but when source and destination are on different devices. */ /* This happens when attempting to rename a directory to a subdirectory of itself. */ if (errno == EINVAL /* When src_path is on an NFS file system, some types of clients, e.g., SunOS4.1.4 and IRIX-5.3, set errno to EIO instead. Testing for this here risks misinterpreting a real I/O error as an attempt to move a directory into itself, so FIXME: consider not doing this. */ || errno == EIO /* And with SunOS-4.1.4 client and OpenBSD-2.3 server, we get ENOTEMPTY. */ || errno == ENOTEMPTY) { /* FIXME: this is a little fragile in that it relies on rename(2) failing with a specific errno value. Expect problems on non-POSIX systems. */ error (0, 0, _("cannot move %s to a subdirectory of itself, %s"), quote_n (0, top_level_src_path), quote_n (1, top_level_dst_path)); /* Note that there is no need to call forget_created here, (compare with the other calls in this file) since the destination directory didn't exist before. */ *copy_into_self = 1; /* FIXME-cleanup: Don't return zero here; adjust mv.c accordingly. The only caller that uses this code (mv.c) ends up setting its exit status to nonzero when copy_into_self is nonzero. */ return 0; } /* WARNING: there probably exist systems for which an inter-device rename fails with a value of errno not handled here. If/as those are reported, add them to the condition below. If this happens to you, please do the following and send the output to the bug-reporting address (e.g., in the output of cp --help): touch k; perl -e 'rename "k","/tmp/k" or print "$!(",$!+0,")\n"' where your current directory is on one partion and /tmp is the other. Also, please try to find the E* errno macro name corresponding to the diagnostic and parenthesized integer, and include that in your e-mail. One way to do that is to run a command like this find /usr/include/. -type f \ | xargs grep 'define.*\<E[A-Z]*\>.*\<18\>' /dev/null where you'd replace `18' with the integer in parentheses that was output from the perl one-liner above. If necessary, of course, change `/tmp' to some other directory. */ if (errno != EXDEV) { /* There are many ways this can happen due to a race condition. When something happens between the initial xstat and the subsequent rename, we can get many different types of errors. For example, if the destination is initially a non-directory or non-existent, but it is created as a directory, the rename fails. If two `mv' commands try to rename the same file at about the same time, one will succeed and the other will fail. If the permissions on the directory containing the source or destination file are made too restrictive, the rename will fail. Etc. */ error (0, errno, _("cannot move %s to %s"), quote_n (0, src_path), quote_n (1, dst_path)); forget_created (src_sb.st_ino, src_sb.st_dev); return 1; } /* The rename attempt has failed. Remove any existing destination file so that a cross-device `mv' acts as if it were really using the rename syscall. */ if (unlink (dst_path) && errno != ENOENT) { error (0, errno, _("inter-device move failed: %s to %s; unable to remove target"), quote_n (0, src_path), quote_n (1, dst_path)); forget_created (src_sb.st_ino, src_sb.st_dev); return 1; } new_dst = 1; } delayed_fail = 0; /* In certain modes (cp's --symbolic-link), and for certain file types (symlinks and hard links) it doesn't make sense to preserve metadata, or it's possible to preserve only some of it. In such cases, set this variable to zero. */ preserve_metadata = 1; if (S_ISDIR (src_type)) { struct dir_list *dir; /* If this directory has been copied before during the recursion, there is a symbolic link to an ancestor directory of the symbolic link. It is impossible to continue to copy this, unless we've got an infinite disk. */ if (is_ancestor (&src_sb, ancestors)) { error (0, 0, _("cannot copy cyclic symbolic link %s"), quote (src_path)); goto un_backup; } /* Insert the current directory in the list of parents. */ dir = (struct dir_list *) alloca (sizeof (struct dir_list)); dir->parent = ancestors; dir->ino = src_sb.st_ino; dir->dev = src_sb.st_dev; if (new_dst || !S_ISDIR (dst_sb.st_mode)) { /* Create the new directory writable and searchable, so we can create new entries in it. */ if (mkdir (dst_path, (src_mode & x->umask_kill) | S_IRWXU)) { error (0, errno, _("cannot create directory %s"), quote (dst_path)); goto un_backup; } /* Insert the created directory's inode and device numbers into the search structure, so that we can avoid copying it again. */ if (remember_created (dst_path)) goto un_backup; if (x->verbose) printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path)); } /* Are we crossing a file system boundary? */ if (x->one_file_system && device != 0 && device != src_sb.st_dev) return 0; /* Copy the contents of the directory. */ if (copy_dir (src_path, dst_path, new_dst, &src_sb, dir, x, copy_into_self)) { /* Don't just return here -- otherwise, the failure to read a single file in a source directory would cause the containing destination directory not to have owner/perms set properly. */ delayed_fail = 1; } } #ifdef S_ISLNK else if (x->symbolic_link) { preserve_metadata = 0; if (*src_path != '/') { /* Check that DST_PATH denotes a file in the current directory. */ struct stat dot_sb; struct stat dst_parent_sb; char *dst_parent; int in_current_dir; dst_parent = dir_name (dst_path); in_current_dir = (STREQ (".", dst_parent) /* If either stat call fails, it's ok not to report the failure and say dst_path is in the current directory. Other things will fail later. */ || stat (".", &dot_sb) || stat (dst_parent, &dst_parent_sb) || SAME_INODE (dot_sb, dst_parent_sb)); free (dst_parent); if (! in_current_dir) { error (0, 0, _("%s: can make relative symbolic links only in current directory"), quote (dst_path)); goto un_backup; } } if (symlink (src_path, dst_path)) { error (0, errno, _("cannot create symbolic link %s to %s"), quote_n (0, dst_path), quote_n (1, src_path)); goto un_backup; } } #endif else if (x->hard_link) { preserve_metadata = 0; if (link (src_path, dst_path)) { error (0, errno, _("cannot create link %s"), quote (dst_path)); goto un_backup; } } else if (S_ISREG (src_type) || (x->copy_as_regular && !S_ISDIR (src_type) #ifdef S_ISLNK && !S_ISLNK (src_type) #endif )) { copied_as_regular = 1; /* POSIX says the permission bits of the source file must be used as the 3rd argument in the open call, but that's not consistent with historical practice. */ if (copy_reg (src_path, dst_path, x, get_dest_mode (x, src_mode), &new_dst, &src_sb)) goto un_backup; } else #ifdef S_ISFIFO if (S_ISFIFO (src_type)) { if (mkfifo (dst_path, get_dest_mode (x, src_mode))) { error (0, errno, _("cannot create fifo %s"), quote (dst_path)); goto un_backup; } } else #endif if (S_ISBLK (src_type) || S_ISCHR (src_type) #ifdef S_ISSOCK || S_ISSOCK (src_type) #endif ) { if (mknod (dst_path, get_dest_mode (x, src_mode), src_sb.st_rdev)) { error (0, errno, _("cannot create special file %s"), quote (dst_path)); goto un_backup; } } else #ifdef S_ISLNK if (S_ISLNK (src_type)) { char *src_link_val = xreadlink (src_path); if (src_link_val == NULL) { error (0, errno, _("cannot read symbolic link %s"), quote (src_path)); goto un_backup; } if (!symlink (src_link_val, dst_path)) free (src_link_val); else { int saved_errno = errno; int same_link = 0; if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode)) { /* See if the destination is already the desired symlink. */ size_t src_link_len = strlen (src_link_val); char *dest_link_val = (char *) alloca (src_link_len + 1); int dest_link_len = readlink (dst_path, dest_link_val, src_link_len + 1); if ((size_t) dest_link_len == src_link_len && strncmp (dest_link_val, src_link_val, src_link_len) == 0) same_link = 1; } free (src_link_val); if (! same_link) { error (0, saved_errno, _("cannot create symbolic link %s"), quote (dst_path)); goto un_backup; } } /* There's no need to preserve timestamps or permissions. */ preserve_metadata = 0; if (x->preserve_ownership) { /* Preserve the owner and group of the just-`copied' symbolic link, if possible. */ # if HAVE_LCHOWN if (DO_CHOWN (lchown, dst_path, src_sb.st_uid, src_sb.st_gid)) { error (0, errno, _("failed to preserve ownership for %s"), dst_path); goto un_backup; } # else /* Can't preserve ownership of symlinks. FIXME: maybe give a warning or even error for symlinks in directories with the sticky bit set -- there, not preserving owner/group is a potential security problem. */ # endif } } else #endif { error (0, 0, _("%s has unknown file type"), quote (src_path)); goto un_backup; } if (command_line_arg) record_file (x->dest_info, dst_path, NULL); if ( ! preserve_metadata) return 0; /* POSIX says that `cp -p' must restore the following: - permission bits - setuid, setgid bits - owner and group If it fails to restore any of those, we may give a warning but the destination must not be removed. FIXME: implement the above. */ /* Adjust the times (and if possible, ownership) for the copy. chown turns off set[ug]id bits for non-root, so do the chmod last. */ if (x->preserve_timestamps) { struct utimbuf utb; /* There's currently no interface to set file timestamps with better than 1-second resolution, so discard any fractional part of the source timestamp. */ utb.actime = src_sb.st_atime; utb.modtime = src_sb.st_mtime; if (utime (dst_path, &utb)) { error (0, errno, _("preserving times for %s"), quote (dst_path)); if (x->require_preserve) return 1; } } /* Avoid calling chown if we know it's not necessary. */ if (x->preserve_ownership && (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb))) { ran_chown = 1; if (DO_CHOWN (chown, dst_path, src_sb.st_uid, src_sb.st_gid)) { error (0, errno, _("failed to preserve ownership for %s"), quote (dst_path)); if (x->require_preserve) return 1; } } #if HAVE_STRUCT_STAT_ST_AUTHOR /* Preserve the st_author field. */ { file_t file = file_name_lookup (dst_path, 0, 0); if (file_chauthor (file, src_sb.st_author)) error (0, errno, _("failed to preserve authorship for %s"), quote (dst_path)); mach_port_deallocate (mach_task_self (), file); } #endif /* Permissions of newly-created regular files were set upon `open' in copy_reg. But don't return early if there were any special bits and we had to run chown, because the chown must have reset those bits. */ if ((new_dst && copied_as_regular) && !(ran_chown && (src_mode & ~S_IRWXUGO))) return delayed_fail; if ((x->preserve_mode || new_dst) && (x->copy_as_regular || S_ISREG (src_type) || S_ISDIR (src_type))) { if (chmod (dst_path, get_dest_mode (x, src_mode))) { error (0, errno, _("setting permissions for %s"), quote (dst_path)); if (x->set_mode || x->require_preserve) return 1; } } return delayed_fail; un_backup: /* We have failed to create the destination file. If we've just added a dev/ino entry via the remember_copied call above (i.e., unless we've just failed to create a hard link), remove the entry associating the source dev/ino with the destination file name, so we don't try to `preserve' a link to a file we didn't create. */ if (earlier_file == NULL) forget_created (src_sb.st_ino, src_sb.st_dev); if (dst_backup) { if (rename (dst_backup, dst_path)) error (0, errno, _("cannot un-backup %s"), quote (dst_path)); else { if (x->verbose) printf (_("%s -> %s (unbackup)\n"), quote_n (0, dst_backup), quote_n (1, dst_path)); } } return 1; }
int rpmfiConfigConflictIndex(rpmfi fi, int ix) { char * fn = NULL; rpmfileAttrs flags = rpmfiFFlagsIndex(fi, ix); char buffer[1024]; rpmFileTypes newWhat, diskWhat; struct stat sb; int rc = 0; /* Non-configs are not config conflicts. */ if (!(flags & RPMFILE_CONFIG)) return 0; /* Only links and regular files can be %config, this is kinda moot */ /* XXX: Why are we returning 1 here? */ newWhat = rpmfiWhatis(rpmfiFModeIndex(fi, ix)); if (newWhat != LINK && newWhat != REG) return 1; /* If it's not on disk, there's nothing to be saved */ fn = rpmfiFNIndex(fi, ix); if (lstat(fn, &sb)) goto exit; /* * Preserve legacy behavior: an existing %ghost %config is considered * "modified" but unlike regular %config, its never removed and * never backed up. Whether this actually makes sense is a whole * another question, but this is very long-standing behavior that * people might be depending on. The resulting FA_ALTNAME etc action * is special-cased in FSM to avoid actually creating backups on ghosts. */ if (flags & RPMFILE_GHOST) { rc = 1; goto exit; } /* Files of different types obviously are not identical */ diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode); if (diskWhat != newWhat) { rc = 1; goto exit; } /* Files of different sizes obviously are not identical */ if (rpmfiFSizeIndex(fi, ix) != sb.st_size) { rc = 1; goto exit; } memset(buffer, 0, sizeof(buffer)); if (newWhat == REG) { int algo; size_t diglen; const unsigned char *ndigest = rpmfiFDigestIndex(fi,ix, &algo, &diglen); if (rpmDoDigest(algo, fn, 0, (unsigned char *)buffer, NULL)) goto exit; /* assume file has been removed */ if (ndigest && memcmp(ndigest, buffer, diglen) == 0) goto exit; /* unmodified config file */ } else /* newWhat == LINK */ { const char * nFLink; ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1); if (link_len == -1) goto exit; /* assume file has been removed */ buffer[link_len] = '\0'; nFLink = rpmfiFLinkIndex(fi, ix); if (nFLink && rstreq(nFLink, buffer)) goto exit; /* unmodified config file */ } rc = 1; exit: free(fn); return rc; }
char * chroot_canon (const char *chroot, const char *name) { char *rpath; char *dest; char *extra_buf = NULL; char *rpath_root; const char *start; const char *end; const char *rpath_limit; int num_links = 0; size_t chroot_len = strlen (chroot); if (chroot_len < 1) { __set_errno (EINVAL); return NULL; } rpath = malloc (chroot_len + PATH_MAX); if (rpath == NULL) return NULL; rpath_limit = rpath + chroot_len + PATH_MAX; rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1; if (*rpath_root != '/') *++rpath_root = '/'; dest = rpath_root + 1; for (start = end = name; *start; start = end) { struct stat64 st; int n; /* Skip sequence of multiple path-separators. */ while (*start == '/') ++start; /* Find end of path component. */ for (end = start; *end && *end != '/'; ++end) /* Nothing. */; if (end - start == 0) break; else if (end - start == 1 && start[0] == '.') /* nothing */; else if (end - start == 2 && start[0] == '.' && start[1] == '.') { /* Back up to previous component, ignore if at root already. */ if (dest > rpath_root + 1) while ((--dest)[-1] != '/'); } else { size_t new_size; if (dest[-1] != '/') *dest++ = '/'; if (dest + (end - start) >= rpath_limit) { ptrdiff_t dest_offset = dest - rpath; char *new_rpath; new_size = rpath_limit - rpath; if (end - start + 1 > PATH_MAX) new_size += end - start + 1; else new_size += PATH_MAX; new_rpath = (char *) realloc (rpath, new_size); if (new_rpath == NULL) goto error; rpath = new_rpath; rpath_limit = rpath + new_size; dest = rpath + dest_offset; } dest = mempcpy (dest, start, end - start); *dest = '\0'; if (lstat64 (rpath, &st) < 0) { if (*end == '\0') goto done; goto error; } if (S_ISLNK (st.st_mode)) { char *buf = alloca (PATH_MAX); size_t len; if (++num_links > MAXSYMLINKS) { __set_errno (ELOOP); goto error; } n = readlink (rpath, buf, PATH_MAX); if (n < 0) { if (*end == '\0') goto done; goto error; } buf[n] = '\0'; if (!extra_buf) extra_buf = alloca (PATH_MAX); len = strlen (end); if ((long int) (n + len) >= PATH_MAX) { __set_errno (ENAMETOOLONG); goto error; } /* Careful here, end may be a pointer into extra_buf... */ memmove (&extra_buf[n], end, len + 1); name = end = memcpy (extra_buf, buf, n); if (buf[0] == '/') dest = rpath_root + 1; /* It's an absolute symlink */ else /* Back up to previous component, ignore if at root already: */ if (dest > rpath_root + 1) while ((--dest)[-1] != '/'); } } } done: if (dest > rpath_root + 1 && dest[-1] == '/') --dest; *dest = '\0'; return rpath; error: free (rpath); return NULL; }
LLDir_Linux::LLDir_Linux() { mDirDelimiter = "/"; mCurrentDirIndex = -1; mCurrentDirCount = -1; mDirp = NULL; char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ if (getcwd(tmp_str, LL_MAX_PATH) == NULL) { strcpy(tmp_str, "/tmp"); llwarns << "Could not get current directory; changing to " << tmp_str << llendl; if (chdir(tmp_str) == -1) { llerrs << "Could not change directory to " << tmp_str << llendl; } } mExecutableFilename = ""; mExecutablePathAndName = ""; mExecutableDir = tmp_str; mWorkingDir = tmp_str; mAppRODataDir = tmp_str; mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; mLindenUserDir = tmp_str; char path [32]; /* Flawfinder: ignore */ // *NOTE: /proc/%d/exe doesn't work on FreeBSD. But that's ok, // because this is the linux implementation. snprintf (path, sizeof(path), "/proc/%d/exe", (int) getpid ()); int rc = readlink (path, tmp_str, sizeof (tmp_str)-1); /* Flawfinder: ignore */ if ( (rc != -1) && (rc <= ((int) sizeof (tmp_str)-1)) ) { tmp_str[rc] = '\0'; //readlink() doesn't 0-terminate the buffer mExecutablePathAndName = tmp_str; char *path_end; if ((path_end = strrchr(tmp_str,'/'))) { *path_end = '\0'; mExecutableDir = tmp_str; mWorkingDir = tmp_str; mExecutableFilename = path_end+1; } else { mExecutableFilename = tmp_str; } } mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; #ifdef APP_RO_DATA_DIR const char* appRODataDir = APP_RO_DATA_DIR; if(appRODataDir[0] == '/') { // We have a full path to the data directory. mAppRODataDir = appRODataDir; } else if(appRODataDir[0] != '\0') { // We have a relative path to the data directory. Search // for it in each potential install prefix containing the // executable. for(std::string prefix = getDirName(mExecutableDir); !prefix.empty(); prefix = getDirName(prefix)) { std::string dir = prefix + "/" + appRODataDir; if(fileExists(dir + "/app_settings")) { mAppRODataDir = dir; break; } } } #endif // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. mTempDir = "/tmp"; }
//static QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data) { #if defined(__GLIBC__) && !defined(PATH_MAX) #define PATH_CHUNK_SIZE 256 char *s = 0; int len = -1; int size = PATH_CHUNK_SIZE; while (1) { s = (char *) ::realloc(s, size); Q_CHECK_PTR(s); len = ::readlink(link.nativeFilePath().constData(), s, size); if (len < 0) { ::free(s); break; } if (len < size) { break; } size *= 2; } #else char s[PATH_MAX+1]; int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX); #endif if (len > 0) { QString ret; if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) fillMetaData(link, data, QFileSystemMetaData::DirectoryType); if (data.isDirectory() && s[0] != '/') { QDir parent(link.filePath()); parent.cdUp(); ret = parent.path(); if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/'))) ret += QLatin1Char('/'); } s[len] = '\0'; ret += QFile::decodeName(QByteArray(s)); #if defined(__GLIBC__) && !defined(PATH_MAX) ::free(s); #endif if (!ret.startsWith(QLatin1Char('/'))) { if (link.filePath().startsWith(QLatin1Char('/'))) { ret.prepend(link.filePath().left(link.filePath().lastIndexOf(QLatin1Char('/'))) + QLatin1Char('/')); } else { ret.prepend(QDir::currentPath() + QLatin1Char('/')); } } ret = QDir::cleanPath(ret); if (ret.size() > 1 && ret.endsWith(QLatin1Char('/'))) ret.chop(1); return QFileSystemEntry(ret); } #if defined(Q_OS_DARWIN) { QCFString path = CFStringCreateWithFileSystemRepresentation(0, QFile::encodeName(QDir::cleanPath(link.filePath())).data()); if (!path) return QFileSystemEntry(); QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, data.hasFlags(QFileSystemMetaData::DirectoryType)); if (!url) return QFileSystemEntry(); QCFType<CFDataRef> bookmarkData = CFURLCreateBookmarkDataFromFile(0, url, NULL); if (!bookmarkData) return QFileSystemEntry(); QCFType<CFURLRef> resolvedUrl = CFURLCreateByResolvingBookmarkData(0, bookmarkData, (CFURLBookmarkResolutionOptions)(kCFBookmarkResolutionWithoutUIMask | kCFBookmarkResolutionWithoutMountingMask), NULL, NULL, NULL, NULL); if (!resolvedUrl) return QFileSystemEntry(); QCFString cfstr(CFURLCopyFileSystemPath(resolvedUrl, kCFURLPOSIXPathStyle)); if (!cfstr) return QFileSystemEntry(); return QFileSystemEntry(QCFString::toQString(cfstr)); } #endif return QFileSystemEntry(); }
/** @internal * Find the canonical filename of the executable. Returns the filename * (which must be freed) or NULL on error. If the parameter 'error' is * not NULL, the error code will be stored there, if an error occured. */ static char * _br_find_exe (BrInitError *error) { #ifndef ENABLE_BINRELOC if (error) *error = BR_INIT_ERROR_DISABLED; return NULL; #elif defined(sun) || defined(__sun) char *path; path = getexecname(); return strdup(path); #elif defined(__APPLE__) && defined(__MACH__) char path[MAXPATHLEN+1]; uint32_t path_len = MAXPATHLEN; // SPI first appeared in Mac OS X 10.2 _NSGetExecutablePath(path, &path_len); return strdup(path); #else char *path, *path2, *line, *result; size_t buf_size; ssize_t size; struct stat stat_buf; FILE *f; /* Read from /proc/self/exe (symlink) */ if (sizeof (path) > SSIZE_MAX) buf_size = SSIZE_MAX - 1; else buf_size = PATH_MAX - 1; path = (char *) malloc (buf_size); if (path == NULL) { /* Cannot allocate memory. */ if (error) *error = BR_INIT_ERROR_NOMEM; return NULL; } path2 = (char *) malloc (buf_size); if (path2 == NULL) { /* Cannot allocate memory. */ if (error) *error = BR_INIT_ERROR_NOMEM; free (path); return NULL; } #ifdef __FreeBSD__ strncpy (path2, "/proc/self/file", buf_size - 1); #else strncpy (path2, "/proc/self/exe", buf_size - 1); #endif while (1) { int i; size = readlink (path2, path, buf_size - 1); if (size == -1) { /* Error. */ free (path2); break; } /* readlink() success. */ path[size] = '\0'; /* Check whether the symlink's target is also a symlink. * We want to get the final target. */ i = stat (path, &stat_buf); if (i == -1) { /* Error. */ free (path2); break; } /* stat() success. */ if (!S_ISLNK (stat_buf.st_mode)) { /* path is not a symlink. Done. */ free (path2); return path; } /* path is a symlink. Continue loop and resolve this. */ strncpy (path, path2, buf_size - 1); } #if defined(__FreeBSD__) { char *name, *start, *end; char *buffer = NULL, *temp; struct stat finfo; name = (char*) getprogname(); start = end = getenv("PATH"); while (*end) { end = strchr (start, ':'); if (!end) end = strchr (start, '\0'); /* Resize `buffer' for path component, '/', name and a '\0' */ temp = realloc (buffer, end - start + 1 + strlen (name) + 1); if (temp) { buffer = temp; strncpy (buffer, start, end - start); *(buffer + (end - start)) = '/'; strcpy (buffer + (end - start) + 1, name); if ((stat(buffer, &finfo)==0) && (!S_ISDIR (finfo.st_mode))) { path = strdup(buffer); free (buffer); return path; } } /* else... ignore the failure; `buffer' is still valid anyway. */ start = end + 1; } /* Path search failed */ free (buffer); if (error) *error = BR_INIT_ERROR_DISABLED; return NULL; } #endif /* readlink() or stat() failed; this can happen when the program is * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ buf_size = PATH_MAX + 128; line = (char *) realloc (path, buf_size); if (line == NULL) { /* Cannot allocate memory. */ free (path); if (error) *error = BR_INIT_ERROR_NOMEM; return NULL; } f = fopen ("/proc/self/maps", "r"); if (f == NULL) { free (line); if (error) *error = BR_INIT_ERROR_OPEN_MAPS; return NULL; } /* The first entry should be the executable name. */ result = fgets (line, (int) buf_size, f); if (result == NULL) { fclose (f); free (line); if (error) *error = BR_INIT_ERROR_READ_MAPS; return NULL; } /* Get rid of newline character. */ buf_size = strlen (line); if (buf_size <= 0) { /* Huh? An empty string? */ fclose (f); free (line); if (error) *error = BR_INIT_ERROR_INVALID_MAPS; return NULL; } if (line[buf_size - 1] == 10) line[buf_size - 1] = 0; /* Extract the filename; it is always an absolute path. */ path = strchr (line, '/'); /* Sanity check. */ if (strstr (line, " r-xp ") == NULL || path == NULL) { fclose (f); free (line); if (error) *error = BR_INIT_ERROR_INVALID_MAPS; return NULL; } path = strdup (path); free (line); fclose (f); return path; #endif /* ENABLE_BINRELOC */ }
static int copy_single_file(const char *from, const char *to) { FILE *from_stream, *to_stream; struct stat st; char buf[4096]; size_t len; if (check_the_same(from, to)) { fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); return RecursiveOp_Callback_Error; } if (lstat(from, &st)) { perror("lstat"); return RecursiveOp_Callback_Error; } if (S_ISLNK(st.st_mode)) { /* symbolic links should be copied in special way */ char *link_buffer; int need_free; ssize_t link_len; /* get large enough buffer to read link content */ if (st.st_size < sizeof(buf)) { link_buffer = buf; need_free = 0; } else { link_buffer = MEM_callocN(st.st_size + 2, "copy_single_file link_buffer"); need_free = 1; } link_len = readlink(from, link_buffer, st.st_size + 1); if (link_len < 0) { perror("readlink"); if (need_free) MEM_freeN(link_buffer); return RecursiveOp_Callback_Error; } link_buffer[link_len] = 0; if (symlink(link_buffer, to)) { perror("symlink"); if (need_free) MEM_freeN(link_buffer); return RecursiveOp_Callback_Error; } if (need_free) MEM_freeN(link_buffer); return RecursiveOp_Callback_OK; } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { /* copy special type of file */ if (mknod(to, st.st_mode, st.st_rdev)) { perror("mknod"); return RecursiveOp_Callback_Error; } if (set_permissions(to, &st)) return RecursiveOp_Callback_Error; return RecursiveOp_Callback_OK; } else if (!S_ISREG(st.st_mode)) { fprintf(stderr, "Copying of this kind of files isn't supported yet\n"); return RecursiveOp_Callback_Error; } from_stream = fopen(from, "rb"); if (!from_stream) { perror("fopen"); return RecursiveOp_Callback_Error; } to_stream = fopen(to, "wb"); if (!to_stream) { perror("fopen"); fclose(from_stream); return RecursiveOp_Callback_Error; } while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) { fwrite(buf, 1, len, to_stream); } fclose(to_stream); fclose(from_stream); if (set_permissions(to, &st)) return RecursiveOp_Callback_Error; return RecursiveOp_Callback_OK; }
/* * Connects to i3 to find out the currently running version. Useful since it * might be different from the version compiled into this binary (maybe the * user didn’t correctly install i3 or forgot te restart it). * * The output looks like this: * Running i3 version: 4.2-202-gb8e782c (2012-08-12, branch "next") (pid 14804) * * The i3 binary you just called: /home/michael/i3/i3 * The i3 binary you are running: /home/michael/i3/i3 * */ void display_running_version(void) { char *socket_path = root_atom_contents("I3_SOCKET_PATH", conn, conn_screen); if (socket_path == NULL) exit(EXIT_SUCCESS); char *pid_from_atom = root_atom_contents("I3_PID", conn, conn_screen); if (pid_from_atom == NULL) { /* If I3_PID is not set, the running version is older than 4.2-200. */ printf("\nRunning version: < 4.2-200\n"); exit(EXIT_SUCCESS); } /* Inform the user of what we are doing. While a single IPC request is * really fast normally, in case i3 hangs, this will not terminate. */ printf("(Getting version from running i3, press ctrl-c to abort…)"); fflush(stdout); /* TODO: refactor this with the code for sending commands */ int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); if (sockfd == -1) err(EXIT_FAILURE, "Could not create socket"); struct sockaddr_un addr; memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_LOCAL; strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) err(EXIT_FAILURE, "Could not connect to i3"); if (ipc_send_message(sockfd, 0, I3_IPC_MESSAGE_TYPE_GET_VERSION, (uint8_t *)"") == -1) err(EXIT_FAILURE, "IPC: write()"); uint32_t reply_length; uint32_t reply_type; uint8_t *reply; int ret; if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) { if (ret == -1) err(EXIT_FAILURE, "IPC: read()"); exit(EXIT_FAILURE); } if (reply_type != I3_IPC_MESSAGE_TYPE_GET_VERSION) errx(EXIT_FAILURE, "Got reply type %d, but expected %d (GET_VERSION)", reply_type, I3_IPC_MESSAGE_TYPE_GET_VERSION); yajl_handle handle = yajl_alloc(&version_callbacks, NULL, NULL); yajl_status state = yajl_parse(handle, (const unsigned char *)reply, (int)reply_length); if (state != yajl_status_ok) errx(EXIT_FAILURE, "Could not parse my own reply. That's weird. reply is %.*s", (int)reply_length, reply); printf("\rRunning i3 version: %s (pid %s)\n", human_readable_version, pid_from_atom); if (loaded_config_file_name) { struct stat sb; time_t now; char mtime[64]; printf("Loaded i3 config: %s", loaded_config_file_name); if (stat(loaded_config_file_name, &sb) == -1) { printf("\n"); ELOG("Cannot stat config file \"%s\"\n", loaded_config_file_name); } else { strftime(mtime, sizeof(mtime), "%c", localtime(&(sb.st_mtime))); time(&now); printf(" (Last modified: %s, %.f seconds ago)\n", mtime, difftime(now, sb.st_mtime)); } } #ifdef __linux__ size_t destpath_size = 1024; ssize_t linksize; char *exepath; char *destpath = smalloc(destpath_size); sasprintf(&exepath, "/proc/%d/exe", getpid()); while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) { destpath_size = destpath_size * 2; destpath = srealloc(destpath, destpath_size); } if (linksize == -1) err(EXIT_FAILURE, "readlink(%s)", exepath); /* readlink() does not NULL-terminate strings, so we have to. */ destpath[linksize] = '\0'; printf("\n"); printf("The i3 binary you just called: %s\n", destpath); free(exepath); sasprintf(&exepath, "/proc/%s/exe", pid_from_atom); while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) { destpath_size = destpath_size * 2; destpath = srealloc(destpath, destpath_size); } if (linksize == -1) err(EXIT_FAILURE, "readlink(%s)", exepath); /* readlink() does not NULL-terminate strings, so we have to. */ destpath[linksize] = '\0'; /* Check if "(deleted)" is the readlink result. If so, the running version * does not match the file on disk. */ if (strstr(destpath, "(deleted)") != NULL) printf("RUNNING BINARY DIFFERENT FROM BINARY ON DISK!\n"); /* Since readlink() might put a "(deleted)" somewhere in the buffer and * stripping that out seems hackish and ugly, we read the process’s argv[0] * instead. */ free(exepath); sasprintf(&exepath, "/proc/%s/cmdline", pid_from_atom); int fd; if ((fd = open(exepath, O_RDONLY)) == -1) err(EXIT_FAILURE, "open(%s)", exepath); if (read(fd, destpath, sizeof(destpath)) == -1) err(EXIT_FAILURE, "read(%s)", exepath); close(fd); printf("The i3 binary you are running: %s\n", destpath); free(exepath); free(destpath); #endif yajl_free(handle); }
int next_file(ARCHD *arcn) { int cnt; time_t atime; time_t mtime; /* * ftree_sel() might have set the ftree_skip flag if the user has the * -n option and a file was selected from this file arg tree. (-n says * only one member is matched for each pattern) ftree_skip being 1 * forces us to go to the next arg now. */ if (ftree_skip) { /* * clear and go to next arg */ ftree_skip = 0; if (ftree_arg() < 0) return(-1); } /* * loop until we get a valid file to process */ for(;;) { if ((ftent = fts_read(ftsp)) == NULL) { /* * out of files in this tree, go to next arg, if none * we are done */ if (ftree_arg() < 0) return(-1); continue; } /* * handle each type of fts_read() flag */ switch(ftent->fts_info) { case FTS_D: case FTS_DEFAULT: case FTS_F: case FTS_SL: case FTS_SLNONE: /* * these are all ok */ break; case FTS_DP: /* * already saw this directory. If the user wants file * access times reset, we use this to restore the * access time for this directory since this is the * last time we will see it in this file subtree * remember to force the time (this is -t on a read * directory, not a created directory). */ # ifdef NET2_FTS if (!tflag || (get_atdir(ftent->fts_statb.st_dev, ftent->fts_statb.st_ino, &mtime, &atime) < 0)) # else if (!tflag || (get_atdir(ftent->fts_statp->st_dev, ftent->fts_statp->st_ino, &mtime, &atime) < 0)) # endif continue; set_ftime(ftent->fts_path, mtime, atime, 1); continue; case FTS_DC: /* * fts claims a file system cycle */ paxwarn(1,"File system cycle found at %s",ftent->fts_path); continue; case FTS_DNR: # ifdef NET2_FTS syswarn(1, errno, # else syswarn(1, ftent->fts_errno, # endif "Unable to read directory %s", ftent->fts_path); continue; case FTS_ERR: # ifdef NET2_FTS syswarn(1, errno, # else syswarn(1, ftent->fts_errno, # endif "File system traversal error"); continue; case FTS_NS: case FTS_NSOK: # ifdef NET2_FTS syswarn(1, errno, # else syswarn(1, ftent->fts_errno, # endif "Unable to access %s", ftent->fts_path); continue; } /* * ok got a file tree node to process. copy info into arcn * structure (initialize as required) */ arcn->skip = 0; arcn->pad = 0; arcn->ln_nlen = 0; arcn->ln_name[0] = '\0'; # ifdef NET2_FTS arcn->sb = ftent->fts_statb; # else arcn->sb = *(ftent->fts_statp); # endif /* * file type based set up and copy into the arcn struct * SIDE NOTE: * we try to reset the access time on all files and directories * we may read when the -t flag is specified. files are reset * when we close them after copying. we reset the directories * when we are done with their file tree (we also clean up at * end in case we cut short a file tree traversal). However * there is no way to reset access times on symlinks. */ switch(S_IFMT & arcn->sb.st_mode) { case S_IFDIR: arcn->type = PAX_DIR; if (!tflag) break; add_atdir(ftent->fts_path, arcn->sb.st_dev, arcn->sb.st_ino, arcn->sb.st_mtime, arcn->sb.st_atime); break; case S_IFCHR: arcn->type = PAX_CHR; break; case S_IFBLK: arcn->type = PAX_BLK; break; case S_IFREG: /* * only regular files with have data to store on the * archive. all others will store a zero length skip. * the skip field is used by pax for actual data it has * to read (or skip over). */ arcn->type = PAX_REG; arcn->skip = arcn->sb.st_size; break; case S_IFLNK: arcn->type = PAX_SLK; /* * have to read the symlink path from the file */ if ((cnt = readlink(ftent->fts_path, arcn->ln_name, PAXPATHLEN - 1)) < 0) { syswarn(1, errno, "Unable to read symlink %s", ftent->fts_path); continue; } /* * set link name length, watch out readlink does not * always NUL terminate the link path */ arcn->ln_name[cnt] = '\0'; arcn->ln_nlen = cnt; break; case S_IFSOCK: /* * under BSD storing a socket is senseless but we will * let the format specific write function make the * decision of what to do with it. */ arcn->type = PAX_SCK; break; case S_IFIFO: arcn->type = PAX_FIF; break; } break; } /* * copy file name, set file name length */ arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, sizeof(arcn->name) - 1); arcn->name[arcn->nlen] = '\0'; arcn->org_name = ftent->fts_path; return(0); }
void knh_System_initPath(CTX ctx, knh_System_t *o) { knh_DictMap_t *sysprops = DP(o)->props; knh_path_t phbuf, *ph = knh_path_open(ctx, NULL, ".", &phbuf); knh_bytes_t home = {{NULL}, 0}, user = {{NULL}, 0}; // current working directory knh_ospath(ctx, ph); KNH_SETv(ctx, ctx->share->rootns->rpath, knh_path_newString(ctx, ph, 0)); home.text = (const char*)knh_getenv("KONOHAHOME"); #if defined(K_KONOHAHOME) if(home.text == NULL) { home.text = K_KONOHAHOME; } #endif if(home.text != NULL) { home.len = knh_strlen(home.text); SETPROP("konoha.home.path", new_T(home.text)); } #if defined(K_USING_WINDOWS) { char buf[FILEPATH_BUFSIZ]; int bufsiz = FILEPATH_BUFSIZ; HMODULE h = LoadLibrary(NULL); GetModuleFileNameA(h, buf, bufsiz); ph = knh_path_open_(ctx, NULL, B(buf), &phbuf); SETPROP("konoha.bin.path", knh_path_newString(ctx, ph, 0)); if(homepath == NULL) { knh_String_t *s; GetModuleFileNameA(h, buf, bufsiz); knh_path_reduce(ctx, ph, '/'); s = knh_path_newString(ctx, ph); SETPROP("konoha.home.path", UPCAST(s)); home = S_tobytes(shome); } } #elif defined(K_USING_LINUX_) // @url(http://shinh.skr.jp/binary/b2con.html) // http://doc.trolltech.com/3.3/qapplication.html#applicationDirPath { char buf[FILEPATH_BUFSIZ]; int bufsiz = FILEPATH_BUFSIZ; size_t size = readlink("/proc/self/exe", buf, bufsiz); ph = knh_path_open_(ctx, NULL, new_bytes2(buf, size), &phbuf); SETPROP("konoha.bin.path", knh_path_newString(ctx, ph, 0)); if(home.text == NULL) { knh_String_t *s; knh_path_reduce(ctx, ph, '/'); knh_path_reduce(ctx, ph, '/'); knh_path_append(ctx, ph, 1/*isSep*/, "konoha"); s = knh_path_newString(ctx, ph, 0/*hasScheme*/); SETPROP("konoha.home.path", UPCAST(s)); home = S_tobytes(s); } } #elif defined(K_USING_MACOSX_) ph = knh_path_open(ctx, NULL, _dyld_get_image_name(0), &phbuf); knh_ospath(ctx, ph); SETPROP("konoha.bin.path", knh_path_newString(ctx, ph, 0/*hasScheme*/)); if(home.text == NULL) { knh_String_t *s; knh_path_reduce(ctx, ph, '/'); knh_path_reduce(ctx, ph, '/'); knh_path_append(ctx, ph, 1/*isSep*/, "konoha"); s = knh_path_newString(ctx, ph, 0/*hasScheme*/); SETPROP("konoha.home.path", UPCAST(s)); home = S_tobytes(s); } #else home = STEXT("/opt/konoha"); SETPROP("konoha.home.path", new_T("/opt/konoha")); #endif DBG_ASSERT(home.utext != NULL); /* $konoha.package.path {$konoha.home.path}/package */ knh_path_reset(ctx, ph, NULL, home); knh_path_append(ctx, ph, 1/*sep*/, "package"); knh_path_append(ctx, ph, 1/*sep*/, LIBK_VERSION); SETPROP("konoha.package.path", knh_path_newString(ctx, ph, 0/*hasScheme*/)); /* $konoha.script.path {$konoha.home.path}/script */ knh_path_reset(ctx, ph, NULL, home); knh_path_append(ctx, ph, 1/*sep*/, "script"); knh_path_append(ctx, ph, 1/*sep*/, LIBK_VERSION); SETPROP("konoha.script.path", knh_path_newString(ctx, ph, 0/*hasScheme*/)); #if defined(K_USING_WINDOWS) user.text = knh_getenv("USERPROFILE"); #else user.text = knh_getenv("HOME"); #endif if(user.text != NULL) { /* $user.path */ user.len = knh_strlen(user.text); knh_path_reset(ctx, ph, NULL, user); knh_path_append(ctx, ph, 1/*sep*/, K_KONOHAFOLDER); SETPROP("user.path", knh_path_newString(ctx, ph, 0)); knh_ospath(ctx, ph); knh_path_mkdir(ctx, ph); knh_path_reset(ctx, ph, NULL, user); /* user.package.path */ knh_path_append(ctx, ph, 1/*sep*/, K_KONOHAFOLDER); knh_path_append(ctx, ph, 1/*sep*/, "package"); knh_path_append(ctx, ph, 1/*sep*/, LIBK_VERSION); SETPROP("user.package.path", knh_path_newString(ctx, ph, 0)); } knh_path_close(ctx, ph); }
int getLocationsViafstab() { FILE* fp; char line[512]; int ret = 0; // In this case, we'll first get the partitions we care about (with labels) fp = fopen("/etc/recovery.fstab", "rt"); if (fp == NULL) { LOGE("=> Unable to open /etc/recovery.fstab\n"); return -1; } while (fgets(line, sizeof(line), fp) != NULL) { char mount[32], fstype[32], device[256]; char* pDevice = device; if (line[0] != '/') continue; sscanf(line + 1, "%s %s %s", mount, fstype, device); // Attempt to flip mounts until we find the block device char realDevice[256]; memset(realDevice, 0, sizeof(realDevice)); while (readlink(device, realDevice, sizeof(realDevice)) > 0) { strcpy(device, realDevice); memset(realDevice, 0, sizeof(realDevice)); } if (device[0] != '/') pDevice = NULL; setLocationData(mount, pDevice, pDevice, fstype, 0); } fclose(fp); // We can ignore the results of this call. But if it works, it at least helps get details getSizesViaPartitions(); // Now, let's retrieve base partition sizes if (isEMMCdevice) { fp = __popen("fdisk -l /dev/block/mmcblk0","r"); if (fp == NULL) { LOGE("=> Unable to retrieve partition sizes via fdisk\n"); return -1; } while (fgets(line, sizeof(line), fp) != NULL) { char isBoot[64], device[64], blocks[2][16], *pSizeBlock; unsigned long long size = 0; if (line[0] != '/') continue; sscanf(line, "%s %s %*s %s %s", device, isBoot, blocks[0], blocks[1]); if (isBoot[0] == '*') pSizeBlock = blocks[1]; else pSizeBlock = blocks[0]; // If the block size isn't accurate, don't record it. if (pSizeBlock[strlen(pSizeBlock)-1] == '+') pSizeBlock = NULL; // This could be NULL if we decided the size wasn't accurate if (pSizeBlock) { size = ((unsigned long long) atol(pSizeBlock)) * 1024ULL; } if (size && (setLocationData(NULL, device, NULL, NULL, size) == 0)) { // LOGI(" Mount %s size: %d\n", device, size); } } fclose(fp); } return ret; }
int main(int argc, char* argv[]) { #ifdef HAVE_EXECINFO_H signal(SIGSEGV, crash_sig); signal(SIGABRT, crash_sig); signal(SIGPIPE, SIG_IGN); #endif #ifdef WIN32 HANDLE localfd; WSADATA wsa; enum_device_t devs[MAX_DEVICE_COUNT]; #else int localfd; #endif char cmd[1024]; int remotefd; library_conf_t conf; int opt; struct in_addr a; struct option long_options[] = { { "conf", 1, NULL, 'c' }, { NULL, 0, NULL, 0 } }; char short_options[512] = {0}; longopt2shortopt(long_options, sizeof(long_options) / sizeof(struct option), short_options); #ifdef HAVE_SYSLOG_H openlog(argv[0], LOG_PERROR | LOG_CONS | LOG_PID, LOG_LOCAL0); #endif qtun = calloc(sizeof(*qtun), 1); #ifdef WIN32 remotefd = -1; localfd = INVALID_HANDLE_VALUE; #else localfd = remotefd = -1; #endif { char path[MAX_PATH] = {0}; #ifdef WIN32 strcpy(path, argv[0]); #elif defined(__APPLE__) char tmp_path[sizeof(path)] = {0}; uint32_t len = sizeof(path); if (_NSGetExecutablePath(tmp_path, &len) == -1) { perror("_NSGetExecutablePath"); return 1; } if (readlink(tmp_path, path, sizeof(path)) == -1) { if (errno == EINVAL) strcpy(path, tmp_path); else { perror("readlink"); return 1; } } #else if (readlink("/proc/self/exe", path, sizeof(path)) == -1) { perror("readlink"); return 1; } #endif init_path(path); } conf_init(&conf); while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (opt) { case 'c': { char* path = realpath(optarg, NULL); if (path == NULL) { perror("realpath"); return 1; } strcpy(conf.conf_file, path); free(path); } break; default: fprintf(stderr, "param error\n"); return 1; } } #ifdef WIN32 { size_t count = enum_devices(devs); if (count == 0) { fprintf(stderr, "have no QTun Virtual Adapter\n"); return 1; } else if (count == 1) { strcpy(conf.dev_symbol, devs[0].dev_path); strcpy(conf.dev_name, devs[0].dev_name); } else { size_t i; char str[20] = { 0 }; int n = -1; printf("Have Adapters:\n"); for (i = 0; i < count; ++i) { printf("%lu: %s\n", i + 1, devs[i].dev_name); } printf("Choose One[1]: "); while (n == -1) { if (str[0] == '\n' && str[1] == 0) n = 1; else { if (!is_int(str, sizeof(str))) continue; n = atoi(str); if (n < 1 || n > (int)count) { fprintf(stderr, "Invalid Number must >= 1 and <= %lu\n", count); n = -1; continue; } } } strcpy(conf.dev_symbol, devs[n].dev_path); strcpy(conf.dev_name, devs[n].dev_name); } } #endif init_lua(); show_logo(); script_load_config(qtun->lua, &conf, conf.conf_file); #ifdef WIN32 if (strlen(conf.dev_symbol) == 0) { fprintf(stderr, "Missing param [-e] or [--device]\n"); return 1; } #endif #ifdef WIN32 localfd = tun_open(conf.dev_symbol); if (localfd == INVALID_HANDLE_VALUE) return 1; fprintf(stdout, "%s opened\n", conf.dev_name); #else memset(qtun->dev_name, 0, IFNAMSIZ); localfd = tun_open(qtun->dev_name); if (localfd == -1) return 1; syslog(LOG_INFO, "%s opened\n", qtun->dev_name); #endif a.s_addr = conf.localip; #ifdef WIN32 WSAStartup(MAKEWORD(2, 2), &wsa); #endif if (strlen(conf.server) == 0) { if (conf.netmask == 0 || conf.netmask > 31) { #ifdef WIN32 WSACleanup(); #endif fprintf(stderr, "netmask must > 0 and <= 31\n"); return 1; } library_init(conf); if (conf.localip == 0) { fprintf(stderr, "localip is zero\n"); return 1; } if (strlen(conf.signature_file) == 0) { fprintf(stderr, "missing signature file\n"); return 1; } qtun->is_server = 1; remotefd = bind_and_listen(conf.server_port); if (remotefd == -1) { #ifdef WIN32 WSACleanup(); #endif return 1; } #ifdef WIN32 { a.s_addr = conf.localip; sprintf(cmd, "netsh interface ip set address name=\"%s\" static %s %s", conf.dev_name, inet_ntoa(a), STR_LEN2MASK(conf.netmask)); SYSTEM_EXIT(cmd); } #elif defined(__APPLE__) { sprintf(cmd, "ifconfig %s %s/%u up", qtun->dev_name, inet_ntoa(a), conf.netmask); SYSTEM_EXIT(cmd); a.s_addr = conf.localip & LEN2MASK(conf.netmask); sprintf(cmd, "route add -net %s/%u %s", inet_ntoa(a), conf.netmask, inet_ntoa(a)); SYSTEM_EXIT(cmd); } #else { sprintf(cmd, "ifconfig %s %s/%u up", qtun->dev_name, inet_ntoa(a), conf.netmask); SYSTEM_EXIT(cmd); a.s_addr = conf.localip & LEN2MASK(conf.netmask); sprintf(cmd, "route add -net %s/%u dev %s", inet_ntoa(a), conf.netmask, qtun->dev_name); SYSTEM_EXIT(cmd); } #endif server_loop(remotefd, localfd); } else { #ifdef unix unsigned char mask; #endif int inited = 0; library_init(conf); qtun->is_server = 0; while (1) { remotefd = connect_server(conf.server, conf.server_port); if (remotefd == -1) { SLEEP(5); continue; } a.s_addr = qtun->localip; if (qtun->localip == 0) { fprintf(stderr, "localip is zero\n"); return 1; } if (strlen(conf.signature_file) == 0) { fprintf(stderr, "missing signature file\n"); return 1; } if (!inited) { #ifdef WIN32 { sprintf(cmd, "netsh interface ip set address name=\"%s\" static %s %s", conf.dev_name, inet_ntoa(a), STR_LEN2MASK(conf.netmask)); SYSTEM_EXIT(cmd); } #elif defined(__APPLE__) { char ip1[16], ip2[16]; a.s_addr = qtun->localip; strcpy(ip1, inet_ntoa(a)); a.s_addr = qtun->client.local_ip; strcpy(ip2, inet_ntoa(a)); sprintf(cmd, "ifconfig %s inet %s %s up", qtun->dev_name, ip1, ip2); SYSTEM_EXIT(cmd); mask = netmask(); a.s_addr = qtun->localip & LEN2MASK(mask); sprintf(cmd, "route add -net %s/%u %s", inet_ntoa(a), mask, ip2); SYSTEM_EXIT(cmd); } #else { sprintf(cmd, "ifconfig %s %s up", qtun->dev_name, inet_ntoa(a)); SYSTEM_EXIT(cmd); mask = netmask(); a.s_addr = qtun->localip & LEN2MASK(mask); sprintf(cmd, "route add -net %s/%u dev %s", inet_ntoa(a), mask, qtun->dev_name); SYSTEM_EXIT(cmd); } #endif inited = 1; } client_loop(remotefd, localfd); close(remotefd); SYSLOG(LOG_WARNING, "retry"); } } #ifdef WIN32 WSACleanup(); #endif #ifdef HAVE_SYSLOG_H closelog(); #endif library_free(); return 0; }
/* This is the routine that constructs the filesystem image. */ int mkfs(FILE *fs, const char *path, int ino, int parent, int depth) { struct dirent *dir_entry; DIR *dir; struct stat st; struct jffs_file f; int name_len; int pos = 0; int new_ino = ino; char *filename; int path_len = strlen(path); __u16 chksum; if (verbose >= 2) { fprintf(stderr, "***mkfs(): path: \"%s\"\r\n", path); } if (!(dir = opendir(path))) { perror("opendir"); fprintf(stderr, "mkfs(): opendir() failed! (%s)\n", path); exit(1); } while ((dir_entry = readdir(dir))) { if (verbose >= 2) { fprintf(stderr, "mkfs(): name: %s\n", dir_entry->d_name); } name_len = strlen(dir_entry->d_name); if (((name_len == 1) && (dir_entry->d_name[0] == '.')) || ((name_len == 2) && (dir_entry->d_name[0] == '.') && (dir_entry->d_name[1] == '.'))) { continue; } if (!(filename = (char *)alloca(path_len + name_len + 1))) { fprintf(stderr, "mkfs(): Allocation failed!\n"); exit(0); } strcpy(filename, path); strcat(filename, dir_entry->d_name); if (verbose >= 2) { fprintf(stderr, "mkfs(): filename: %s\n", filename); } if (lstat(filename, &st) < 0) { perror("lstat"); exit(1); } if (verbose >= 2) { fprintf(stderr, "mkfs(): filename: \"%s\", ino: %d, parent: %d\n", filename, new_ino, parent); } f.inode.magic = JFFS_MAGIC; f.inode.ino = new_ino; f.inode.pino = parent; f.inode.version = 1; f.inode.mode = st.st_mode; f.inode.uid = st.st_uid; f.inode.gid = st.st_gid; f.inode.atime = st.st_atime; f.inode.mtime = st.st_mtime; f.inode.ctime = st.st_ctime; f.inode.dsize = 0; f.inode.rsize = 0; f.inode.nsize = name_len; /*f.inode.nlink = st.st_nlink;*/ f.inode.nlink = 1; f.inode.spare = 0; f.inode.rename = 0; f.inode.deleted = 0; f.inode.accurate = 0; f.inode.dchksum = 0; f.inode.nchksum = 0; f.inode.chksum = 0; if (dir_entry->d_name) { f.name = strdup(dir_entry->d_name); } else { f.name = 0; } repeat: f.inode.offset = pos; f.data = 0; f.inode.accurate = 0; if (S_ISREG(st.st_mode) && st.st_size) { if (st.st_size - pos < MAX_CHUNK_SIZE) { f.inode.dsize = st.st_size - pos; } else { f.inode.dsize = MAX_CHUNK_SIZE; } read_data(&f, path, pos); pos += f.inode.dsize; } else if (S_ISLNK(st.st_mode)) { int linklen; unsigned char *linkdata = (unsigned char *)malloc(1000); if (!linkdata) { fprintf(stderr, "mkfs(): malloc() failed! (linkdata)\n"); exit(1); } if ((linklen = readlink(filename, linkdata, 1000)) < 0) { free(linkdata); fprintf(stderr, "mkfs(): readlink() failed! f.name = \"%s\"\n", f.name); exit(1); } f.inode.dsize = linklen; f.data = linkdata; f.data[linklen] = '\0'; } else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) { f.inode.dsize = sizeof(st.st_rdev) / 4; } f.inode.chksum = 0; if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) { f.inode.dchksum = jffs_checksum((void *)f.data, f.inode.dsize); } else { f.inode.dchksum = jffs_checksum((void *)&st.st_rdev, sizeof(st.st_rdev) / 4); } f.inode.nchksum = jffs_checksum((void *)f.name, f.inode.nsize); jffs_swap_inode(&f.inode); chksum = jffs_checksum((void *)&f.inode, sizeof(struct jffs_raw_inode)); jffs_swap_inode(&f.inode); f.inode.chksum = chksum; f.inode.accurate = 0xff; write_file(&f, fs, st); if (S_ISREG(st.st_mode) && st.st_size) { if (pos < st.st_size) { f.inode.version++; goto repeat; } } new_ino++; pos = 0; if (verbose >= 1) { jffs_print_trace(f.name, depth); } if (verbose >= 2) { jffs_print_raw_inode(&f.inode); } if (S_ISDIR(st.st_mode)) { char *new_path; if (!(new_path = (char *)alloca(strlen(path) + name_len + 1 + 1))) { fprintf(stderr, "mkfs(): alloca() failed! (new_path)\n"); exit(1); } strcpy(new_path, path); strncat(new_path, f.name, f.inode.nsize); strcat(new_path, "/"); if (verbose >= 2) { fprintf(stderr, "mkfs(): new_path: \"%s\"\n", new_path); } new_ino = mkfs(fs, new_path, new_ino, new_ino - 1, depth + 1); } if (f.name) { free(f.name); } if (f.data) { free(f.data); } } closedir(dir); return new_ino; }
/* * Return the real path (i.e., absolute path, with symlinks resolved * and extra slashes removed) equivalent to the specified path. (If * you want an absolute path but don't mind links, use * absolute_path().) The return value is a pointer to a static * buffer. * * The input and all intermediate paths must be shorter than MAX_PATH. * The directory part of path (i.e., everything up to the last * dir_sep) must denote a valid, existing directory, but the last * component need not exist. If die_on_error is set, then die with an * informative error message if there is a problem. Otherwise, return * NULL on errors (without generating any output). * * If path is our buffer, then return path, as it's already what the * user wants. */ static const char *real_path_internal(const char *path, int die_on_error) { static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1]; char *retval = NULL; /* * If we have to temporarily chdir(), store the original CWD * here so that we can chdir() back to it at the end of the * function: */ char cwd[1024] = ""; int buf_index = 1; int depth = MAXDEPTH; char *last_elem = NULL; struct stat st; /* We've already done it */ if (path == buf || path == next_buf) return path; if (!*path) { if (die_on_error) die("The empty string is not a valid path"); else goto error_out; } if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) { if (die_on_error) die("Too long path: %.*s", 60, path); else goto error_out; } while (depth--) { if (!is_directory(buf)) { char *last_slash = find_last_dir_sep(buf); if (last_slash) { last_elem = xstrdup(last_slash + 1); last_slash[1] = '\0'; } else { last_elem = xstrdup(buf); *buf = '\0'; } } if (*buf) { if (!*cwd && !getcwd(cwd, sizeof(cwd))) { if (die_on_error) die_errno("Could not get current working directory"); else goto error_out; } if (chdir(buf)) { if (die_on_error) die_errno("Could not switch to '%s'", buf); else goto error_out; } } if (!getcwd(buf, PATH_MAX)) { if (die_on_error) die_errno("Could not get current working directory"); else goto error_out; } if (last_elem) { size_t len = strlen(buf); if (len + strlen(last_elem) + 2 > PATH_MAX) { if (die_on_error) die("Too long path name: '%s/%s'", buf, last_elem); else goto error_out; } if (len && !is_dir_sep(buf[len-1])) buf[len++] = '/'; strcpy(buf + len, last_elem); free(last_elem); last_elem = NULL; } if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) { ssize_t len = readlink(buf, next_buf, PATH_MAX); if (len < 0) { if (die_on_error) die_errno("Invalid symlink '%s'", buf); else goto error_out; } if (PATH_MAX <= len) { if (die_on_error) die("symbolic link too long: %s", buf); else goto error_out; } next_buf[len] = '\0'; buf = next_buf; buf_index = 1 - buf_index; next_buf = bufs[buf_index]; } else break; } retval = buf; error_out: free(last_elem); if (*cwd && chdir(cwd)) die_errno ("Could not change back to '%s'", cwd); return retval; }
int getlock(char *name, struct passwd *pw) { struct stat sb, fsb; int lfd=-1; char buf[8*1024]; int tries = 0; (void)snprintf(lpath, sizeof lpath, "%s/%s.lock", _PATH_MAILDIR, name); if (stat(_PATH_MAILDIR, &sb) != -1 && (sb.st_mode & S_IWOTH) == S_IWOTH) { /* * We have a writeable spool, deal with it as * securely as possible. */ time_t ctim = -1; seteuid(pw->pw_uid); if (lstat(lpath, &sb) != -1) ctim = sb.st_ctime; while (1) { /* * Deal with existing user.lock files * or directories or symbolic links that * should not be here. */ if (readlink(lpath, buf, sizeof buf-1) != -1) { if (lstat(lpath, &sb) != -1 && S_ISLNK(sb.st_mode)) { seteuid(sb.st_uid); unlink(lpath); seteuid(pw->pw_uid); } goto again; } if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK, S_IRUSR|S_IWUSR)) != -1) break; again: if (tries > 10) { merr(NOTFATAL, "%s: %s", lpath, strerror(errno)); seteuid(0); return(-1); } if (tries > 9 && (lfd = open(lpath, O_WRONLY|O_EXLOCK, 0)) != -1) { if (fstat(lfd, &fsb) != -1 && lstat(lpath, &sb) != -1) { if (fsb.st_dev == sb.st_dev && fsb.st_ino == sb.st_ino && ctim == fsb.st_ctime ) { seteuid(fsb.st_uid); baditem(lpath); seteuid(pw->pw_uid); } } } sleep(1U << tries); tries++; continue; } seteuid(0); } else { /* * Only root can write the spool directory. */ while (1) { if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL, S_IRUSR|S_IWUSR)) != -1) break; if (tries > 9) { merr(NOTFATAL, "%s: %s", lpath, strerror(errno)); return(-1); } sleep(1U << tries); tries++; } } return(lfd); }
int getdirlist(session_t *pses, int opt) { DIR *dir = opendir("."); if(dir == NULL) return -1; struct dirent *dt; struct stat stbuf; while((dt = readdir(dir)) != NULL) { if(lstat(dt->d_name, &stbuf) < 0) { //文件查看失败 continue; } //过滤一些文件夹 if(dt->d_name[0] == '.') continue; char sendbuf[1024] = {0}; int index = 0; //是否获取详细信息 if(opt == 1) { //获取文件属性 char perms[] = "----------"; mode_t mode = stbuf.st_mode; switch(mode & S_IFMT) { case S_IFREG: perms[0] = '-'; break; case S_IFDIR: perms[0] = 'd'; break; case S_IFLNK: perms[0] = 'l'; break; case S_IFIFO: perms[0] = 'p'; break; case S_IFSOCK: perms[0] = 's'; break; case S_IFCHR: perms[0] = 'c'; break; case S_IFBLK: perms[0] = 'b'; break; default: perms[0] = '?'; break; } if(mode & S_IRUSR) { perms[1] = 'r'; } if(mode & S_IWUSR) { perms[2] = 'w'; } if(mode & S_IXUSR) { perms[3] = 'x'; } if(mode & S_IRGRP) { perms[4] = 'r'; } if(mode & S_IWGRP) { perms[5] = 'w'; } if(mode & S_IXGRP) { perms[6] = 'x'; } if(mode & S_IROTH) { perms[7] = 'r'; } if(mode & S_IWOTH) { perms[8] = 'w'; } if(mode & S_IXOTH) { perms[9] = 'x'; } //特殊权限位 if(mode & S_ISUID) { perms[3] = (perms[3] == 'x') ? 's' : 'S'; } if(mode & S_ISGID) { perms[6] = (perms[3] == 'x') ? 's' : 'S'; } if(mode & S_ISVTX) { perms[9] = (perms[3] == 'x') ? 't' : 'T'; } //硬连接数,文件大小 index += sprintf(sendbuf, "%s ",perms); index += sprintf(sendbuf + index, "%2d %4d %4d",(int)stbuf.st_nlink, stbuf.st_uid, stbuf.st_gid); index += sprintf(sendbuf + index, "%8lu ", (unsigned long)stbuf.st_size); //格式化文件时间 const char *p_data_format = "%b %e %H:%M"; struct timeval tv; gettimeofday(&tv, NULL); //获取当前系统时间 time_t local_time = tv.tv_sec; if((stbuf.st_mtime > local_time) || ((local_time - stbuf.st_mtime) > 60*60*24*182)) { p_data_format = "%b %e %Y"; } char datebuf[64] = {0}; struct tm *p_tm = localtime(&local_time); strftime(datebuf, sizeof(datebuf), p_data_format, p_tm); index += sprintf(sendbuf + index, "%s ", datebuf); } //获取文件名 if(S_ISLNK(stbuf.st_mode)) //判断是否是连接文件 { char temp[1024] = {0}; readlink(dt->d_name, temp, sizeof(temp)); sprintf(sendbuf + index, "%s -> %s\r\n", dt->d_name,temp); } else { sprintf(sendbuf + index, "%s\r\n", dt->d_name); } //发送给客户端 if(writen(pses->data_fd, sendbuf, strlen(sendbuf)) < 0) handle_error("writen"); } closedir(dir); return 0; }
static int get_dev_mtd(const char *fdt_flash_path, char **mtd_path) { struct dirent **namelist; char fdt_node_path[PATH_MAX]; int count, i, rc, fd; bool done; if (!fdt_flash_path) return -1; fd = open(fdt_flash_path, O_RDONLY); if (fd == -1) { fprintf(stderr, "Couldn't open '%s' FDT attribute to determine which flash device to use\n", fdt_flash_path); fprintf(stderr, "Is your skiboot new enough to expose the flash through the device tree?\n"); hint_root(); return -1; } rc = read(fd, fdt_node_path, sizeof(fdt_node_path)); close(fd); if (rc == -1) { fprintf(stderr, "Couldn't read flash FDT node from '%s'\n", fdt_flash_path); hint_root(); return -1; } count = scandir(SYSFS_MTD_PATH, &namelist, NULL, alphasort); if (count == -1) { fprintf(stderr, "Couldn't scan '%s' for MTD\n", SYSFS_MTD_PATH); hint_root(); return -1; } rc = 0; done = false; for (i = 0; i < count; i++) { struct dirent *dirent; char *dev_path; char fdt_node_path_tmp[PATH_MAX]; dirent = namelist[i]; /* * The call to asprintf must happen last as when it succeeds it * will allocate dev_path */ if (dirent->d_name[0] == '.' || rc || done || asprintf(&dev_path, "%s/%s/device/of_node", SYSFS_MTD_PATH, dirent->d_name) < 0) { free(namelist[i]); continue; } rc = readlink(dev_path, fdt_node_path_tmp, sizeof(fdt_node_path_tmp) - 1); free(dev_path); if (rc == -1) { /* * This might fail because it could not exist if the system has flash * devices that present as mtd but don't have corresponding FDT * nodes, just continue silently. */ free(namelist[i]); /* Should still try the next dir so reset rc */ rc = 0; continue; } fdt_node_path_tmp[rc] = '\0'; if (strstr(fdt_node_path_tmp, fdt_node_path)) { uint32_t flags, size; /* * size and flags could perhaps have be gotten another way but this * method is super unlikely to fail so it will do. */ /* Check to see if device is writeable */ rc = get_dev_attr(dirent->d_name, "flags", &flags); if (rc) { free(namelist[i]); continue; } /* Get the size of the mtd device while we're at it */ rc = get_dev_attr(dirent->d_name, "size", &size); if (rc) { free(namelist[i]); continue; } rc = asprintf(&dev_path, "/dev/%s", dirent->d_name); if (rc < 0) { free(namelist[i]); continue; } rc = 0; *mtd_path = dev_path; done = true; } free(namelist[i]); } free(namelist); if (!done) { fprintf(stderr, "Couldn't find '%s' corresponding MTD\n", fdt_flash_path); fprintf(stderr, "Is your kernel new enough to expose MTD?\n"); } /* explicit negative value so as to not return a libflash code */ return done ? rc : -1; }
static void add_sound_files(GtkWidget *vbox, DIR *dp) { int i = 1, len; struct dirent *ep; struct stat st; char *file, *p; enable_sound_button = gtk_check_button_new_with_label("Enable sound"); g_signal_connect (G_OBJECT (enable_sound_button), "toggled", G_CALLBACK (enable_sound_button_toggled), NULL); gtk_box_pack_start (GTK_BOX (vbox), enable_sound_button, FALSE, FALSE, 10); cur_file_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(cur_file_label), 0.0, 0.5); GtkWidget *hbox = gtk_hbox_new(FALSE, 0); file_list = gtk_combo_box_new_text(); change_button = gtk_button_new_with_label("Change"); gtk_widget_set_sensitive(change_button, FALSE); g_signal_connect (G_OBJECT (change_button), "clicked", G_CALLBACK (change_button_clicked), NULL); gtk_combo_box_append_text (GTK_COMBO_BOX(file_list), "-- please select --"); gtk_combo_box_set_active (GTK_COMBO_BOX(file_list), 0); char buf[256], buf1[256]; /* sound.py */ while ((ep = readdir (dp))) { if (ep->d_type != DT_LNK && ep->d_type != DT_REG) continue; p = strstr(ep->d_name, ".py"); if (! p || strlen(p) != 3) continue; file = ep->d_name; snprintf(buf, sizeof(buf), "%s/%s", OMGPS_SOUND_TOP_DIR, file); if (ep->d_type == DT_LNK) { len = readlink(buf, buf1, sizeof(buf1)); if (len <= 0 || len == sizeof(buf1)) continue; buf1[len] = '\0'; if (stat(buf1, &st) != 0 || ! S_ISREG(st.st_mode)) continue; } else if (ep->d_type != DT_REG) { continue; } gtk_combo_box_append_text (GTK_COMBO_BOX(file_list), file); snprintf(buf1, sizeof(buf), "%s/%s", g_context.config_dir, file); symlink(buf, buf1); gboolean is = (g_cfg->last_sound_file && strcmp(g_cfg->last_sound_file, file) == 0); if (is) { gtk_label_set_text(GTK_LABEL(cur_file_label), file); gtk_combo_box_set_active (GTK_COMBO_BOX(file_list), i); last_idx = i; } ++i; } closedir (dp); /* NOTE: gtk_combo_box_append_text() triggers "changed" event */ g_signal_connect (G_OBJECT (file_list), "changed", G_CALLBACK (file_list_changed), NULL); GtkWidget *hbox0 = gtk_hbox_new(FALSE, 0); GtkWidget *label0 = gtk_label_new("Current file: "); gtk_misc_set_alignment(GTK_MISC(label0), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (hbox0), label0, FALSE, FALSE, 3); gtk_box_pack_start (GTK_BOX (hbox0), cur_file_label, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), file_list, TRUE, TRUE, 3); gtk_box_pack_start(GTK_BOX(hbox), change_button, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox0, FALSE, FALSE, 5); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5); }
static u32 build_default_directory_structure(const char *dir_path, struct selabel_handle *sehnd) { u32 inode; u32 root_inode; struct dentry dentries = { .filename = "lost+found", .file_type = EXT4_FT_DIR, .mode = S_IRWXU, .uid = 0, .gid = 0, .mtime = 0, }; root_inode = make_directory(0, 1, &dentries, 1); inode = make_directory(root_inode, 0, NULL, 0); *dentries.inode = inode; inode_set_permissions(inode, dentries.mode, dentries.uid, dentries.gid, dentries.mtime); #ifndef USE_MINGW if (sehnd) { char *path = NULL; char *secontext = NULL; asprintf(&path, "%slost+found", dir_path); if (selabel_lookup(sehnd, &secontext, path, S_IFDIR) < 0) { error("cannot lookup security context for %s", path); } else { inode_set_selinux(inode, secontext); freecon(secontext); } free(path); } #endif return root_inode; } #ifndef USE_MINGW /* Read a local directory and create the same tree in the generated filesystem. Calls itself recursively with each directory in the given directory. full_path is an absolute or relative path, with a trailing slash, to the directory on disk that should be copied, or NULL if this is a directory that does not exist on disk (e.g. lost+found). dir_path is an absolute path, with trailing slash, to the same directory if the image were mounted at the specified mount point */ static u32 build_directory_structure(const char *full_path, const char *dir_path, const char *target_out_path, u32 dir_inode, fs_config_func_t fs_config_func, struct selabel_handle *sehnd, int verbose, time_t fixed_time) { int entries = 0; struct dentry *dentries; struct dirent **namelist = NULL; struct stat stat; int ret; int i; u32 inode; u32 entry_inode; u32 dirs = 0; bool needs_lost_and_found = false; if (full_path) { entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort); if (entries < 0) { #ifdef __GLIBC__ /* The scandir function implemented in glibc has a bug that makes it erroneously fail with ENOMEM under certain circumstances. As a workaround we can retry the scandir call with the same arguments. GLIBC BZ: https://sourceware.org/bugzilla/show_bug.cgi?id=17804 */ if (errno == ENOMEM) entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort); #endif if (entries < 0) { error_errno("scandir"); return EXT4_ALLOCATE_FAILED; } } } if (dir_inode == 0) { /* root directory, check if lost+found already exists */ for (i = 0; i < entries; i++) if (strcmp(namelist[i]->d_name, "lost+found") == 0) break; if (i == entries) needs_lost_and_found = true; } dentries = calloc(entries, sizeof(struct dentry)); if (dentries == NULL) critical_error_errno("malloc"); for (i = 0; i < entries; i++) { dentries[i].filename = strdup(namelist[i]->d_name); if (dentries[i].filename == NULL) critical_error_errno("strdup"); asprintf(&dentries[i].path, "%s%s", dir_path, namelist[i]->d_name); asprintf(&dentries[i].full_path, "%s%s", full_path, namelist[i]->d_name); free(namelist[i]); ret = lstat(dentries[i].full_path, &stat); if (ret < 0) { error_errno("lstat"); i--; entries--; continue; } dentries[i].size = stat.st_size; dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); if (fixed_time == -1) { dentries[i].mtime = stat.st_mtime; } else { dentries[i].mtime = fixed_time; } uint64_t capabilities; if (fs_config_func != NULL) { #ifdef ANDROID unsigned int mode = 0; unsigned int uid = 0; unsigned int gid = 0; int dir = S_ISDIR(stat.st_mode); fs_config_func(dentries[i].path, dir, target_out_path, &uid, &gid, &mode, &capabilities); dentries[i].mode = mode; dentries[i].uid = uid; dentries[i].gid = gid; dentries[i].capabilities = capabilities; #else error("can't set android permissions - built without android support"); #endif } #ifndef USE_MINGW if (sehnd) { if (selabel_lookup(sehnd, &dentries[i].secon, dentries[i].path, stat.st_mode) < 0) { error("cannot lookup security context for %s", dentries[i].path); } if (dentries[i].secon && verbose) printf("Labeling %s as %s\n", dentries[i].path, dentries[i].secon); } #endif if (S_ISREG(stat.st_mode)) { dentries[i].file_type = EXT4_FT_REG_FILE; } else if (S_ISDIR(stat.st_mode)) { dentries[i].file_type = EXT4_FT_DIR; dirs++; } else if (S_ISCHR(stat.st_mode)) { dentries[i].file_type = EXT4_FT_CHRDEV; } else if (S_ISBLK(stat.st_mode)) { dentries[i].file_type = EXT4_FT_BLKDEV; } else if (S_ISFIFO(stat.st_mode)) { dentries[i].file_type = EXT4_FT_FIFO; } else if (S_ISSOCK(stat.st_mode)) { dentries[i].file_type = EXT4_FT_SOCK; } else if (S_ISLNK(stat.st_mode)) { dentries[i].file_type = EXT4_FT_SYMLINK; dentries[i].link = calloc(info.block_size, 1); readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1); } else { error("unknown file type on %s", dentries[i].path); i--; entries--; } } free(namelist); if (needs_lost_and_found) { /* insert a lost+found directory at the beginning of the dentries */ struct dentry *tmp = calloc(entries + 1, sizeof(struct dentry)); memset(tmp, 0, sizeof(struct dentry)); memcpy(tmp + 1, dentries, entries * sizeof(struct dentry)); dentries = tmp; dentries[0].filename = strdup("lost+found"); asprintf(&dentries[0].path, "%slost+found", dir_path); dentries[0].full_path = NULL; dentries[0].size = 0; dentries[0].mode = S_IRWXU; dentries[0].file_type = EXT4_FT_DIR; dentries[0].uid = 0; dentries[0].gid = 0; if (sehnd) { if (selabel_lookup(sehnd, &dentries[0].secon, dentries[0].path, dentries[0].mode) < 0) error("cannot lookup security context for %s", dentries[0].path); } entries++; dirs++; } inode = make_directory(dir_inode, entries, dentries, dirs); for (i = 0; i < entries; i++) { if (dentries[i].file_type == EXT4_FT_REG_FILE) { entry_inode = make_file(dentries[i].full_path, dentries[i].size); } else if (dentries[i].file_type == EXT4_FT_DIR) { char *subdir_full_path = NULL; char *subdir_dir_path; if (dentries[i].full_path) { ret = asprintf(&subdir_full_path, "%s/", dentries[i].full_path); if (ret < 0) critical_error_errno("asprintf"); } ret = asprintf(&subdir_dir_path, "%s/", dentries[i].path); if (ret < 0) critical_error_errno("asprintf"); entry_inode = build_directory_structure(subdir_full_path, subdir_dir_path, target_out_path, inode, fs_config_func, sehnd, verbose, fixed_time); free(subdir_full_path); free(subdir_dir_path); } else if (dentries[i].file_type == EXT4_FT_SYMLINK) { entry_inode = make_link(dentries[i].link); } else { error("unknown file type on %s", dentries[i].path); entry_inode = 0; } *dentries[i].inode = entry_inode; ret = inode_set_permissions(entry_inode, dentries[i].mode, dentries[i].uid, dentries[i].gid, dentries[i].mtime); if (ret) error("failed to set permissions on %s\n", dentries[i].path); /* * It's important to call inode_set_selinux() before * inode_set_capabilities(). Extended attributes need to * be stored sorted order, and we guarantee this by making * the calls in the proper order. * Please see xattr_assert_sane() in contents.c */ ret = inode_set_selinux(entry_inode, dentries[i].secon); if (ret) error("failed to set SELinux context on %s\n", dentries[i].path); ret = inode_set_capabilities(entry_inode, dentries[i].capabilities); if (ret) error("failed to set capability on %s\n", dentries[i].path); free(dentries[i].path); free(dentries[i].full_path); free(dentries[i].link); free((void *)dentries[i].filename); free(dentries[i].secon); } free(dentries); return inode; }
rpmFileAction rpmfiDecideFateIndex(rpmfi ofi, int oix, rpmfi nfi, int nix, int skipMissing) { char * fn = rpmfiFNIndex(nfi, nix); rpmfileAttrs newFlags = rpmfiFFlagsIndex(nfi, nix); char buffer[1024]; rpmFileTypes dbWhat, newWhat, diskWhat; struct stat sb; int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE; int action = FA_CREATE; /* assume we can create */ /* If the new file is a ghost, leave whatever might be on disk alone. */ if (newFlags & RPMFILE_GHOST) { action = FA_SKIP; goto exit; } if (lstat(fn, &sb)) { /* * The file doesn't exist on the disk. Create it unless the new * package has marked it as missingok, or allfiles is requested. */ if (skipMissing && (newFlags & RPMFILE_MISSINGOK)) { rpmlog(RPMLOG_DEBUG, "%s skipped due to missingok flag\n", fn); action = FA_SKIP; goto exit; } else { goto exit; } } diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode); dbWhat = rpmfiWhatis(rpmfiFModeIndex(ofi, oix)); newWhat = rpmfiWhatis(rpmfiFModeIndex(nfi, nix)); /* * This order matters - we'd prefer to CREATE the file if at all * possible in case something else (like the timestamp) has changed. * Only regular files and symlinks might need a backup, everything * else falls through here with FA_CREATE. */ memset(buffer, 0, sizeof(buffer)); if (dbWhat == REG) { int oalgo, nalgo; size_t odiglen, ndiglen; const unsigned char * odigest, * ndigest; /* See if the file on disk is identical to the one in old pkg */ odigest = rpmfiFDigestIndex(ofi, oix, &oalgo, &odiglen); if (diskWhat == REG) { if (rpmDoDigest(oalgo, fn, 0, (unsigned char *)buffer, NULL)) goto exit; /* assume file has been removed */ if (odigest && memcmp(odigest, buffer, odiglen) == 0) goto exit; /* unmodified config file, replace. */ } /* See if the file on disk is identical to the one in new pkg */ ndigest = rpmfiFDigestIndex(nfi, nix, &nalgo, &ndiglen); if (diskWhat == REG && newWhat == REG) { /* hash algo changed in new, recalculate digest */ if (oalgo != nalgo) if (rpmDoDigest(nalgo, fn, 0, (unsigned char *)buffer, NULL)) goto exit; /* assume file has been removed */ if (ndigest && memcmp(ndigest, buffer, ndiglen) == 0) goto exit; /* file identical in new, replace. */ } /* If file can be determined identical in old and new pkg, let it be */ if (newWhat == REG && oalgo == nalgo && odiglen == ndiglen) { if (odigest && ndigest && memcmp(odigest, ndigest, odiglen) == 0) { action = FA_SKIP; /* identical file, dont bother */ goto exit; } } /* ...but otherwise a backup will be needed */ action = save; } else if (dbWhat == LINK) { const char * oFLink, * nFLink; /* See if the link on disk is identical to the one in old pkg */ oFLink = rpmfiFLinkIndex(ofi, oix); if (diskWhat == LINK) { ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1); if (link_len == -1) goto exit; /* assume file has been removed */ buffer[link_len] = '\0'; if (oFLink && rstreq(oFLink, buffer)) goto exit; /* unmodified config file, replace. */ } /* See if the link on disk is identical to the one in new pkg */ nFLink = rpmfiFLinkIndex(nfi, nix); if (diskWhat == LINK && newWhat == LINK) { if (nFLink && rstreq(nFLink, buffer)) goto exit; /* unmodified config file, replace. */ } /* If link is identical in old and new pkg, let it be */ if (newWhat == LINK && oFLink && nFLink && rstreq(oFLink, nFLink)) { action = FA_SKIP; /* identical file, don't bother. */ goto exit; } /* ...but otherwise a backup will be needed */ action = save; } exit: free(fn); return action; }
/** * Get the location of the application directory. * On OSX this is the .app bundle resource directory. * On Windows this is the directory the executable was launched from. * On Linux/BSD it's the executable's directory * @return NULL if it could not be determined */ char *Bgetappdir(void) { char *dir = NULL; #ifdef _WIN32 TCHAR appdir[MAX_PATH]; if (GetModuleFileName(NULL, appdir, MAX_PATH) > 0) { // trim off the filename char *slash = strrchr(appdir, '\\'); if (slash) slash[0] = 0; dir = strdup(appdir); } #elif defined __APPLE__ CFBundleRef mainBundle; CFURLRef resUrl, fullUrl; CFStringRef str; const char *s; mainBundle = CFBundleGetMainBundle(); if (!mainBundle) { return NULL; } resUrl = CFBundleCopyResourcesDirectoryURL(mainBundle); if (!resUrl) { return NULL; } fullUrl = CFURLCopyAbsoluteURL(resUrl); if (fullUrl) { CFRelease(resUrl); resUrl = fullUrl; } str = CFURLCopyFileSystemPath(resUrl, kCFURLPOSIXPathStyle); CFRelease(resUrl); if (!str) { return NULL; } s = CFStringGetCStringPtr(str, CFStringGetSystemEncoding()); if (s) { dir = strdup(s); } CFRelease(str); #elif defined(__linux) || defined(__NetBSD__) || defined(__OpenBSD__) char buf[PATH_MAX] = {0}; char buf2[PATH_MAX] = {0}; # ifdef __linux snprintf(buf, sizeof(buf), "/proc/%d/exe", getpid()); # else // the BSDs.. except for FreeBSD which has a sysctl snprintf(buf, sizeof(buf), "/proc/%d/file", getpid()); # endif int len = readlink(buf, buf2, sizeof(buf2)); if (len != -1) { // remove executable name with dirname(3) // on Linux, dirname() will modify buf2 (cutting off executable name) and return it // on FreeBSD it seems to use some internal buffer instead.. anyway, just strdup() dir = strdup(dirname(buf2)); } #elif defined(__FreeBSD__) // the sysctl should also work when /proc/ is not mounted (which seems to // be common on FreeBSD), so use it.. char buf[PATH_MAX] = {0}; int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; size_t len = sizeof(buf)-1; int ret = sysctl(name, sizeof(name)/sizeof(name[0]), buf, &len, NULL, 0); if(ret == 0 && buf[0] != '\0') { // again, remove executable name with dirname() // on FreeBSD dirname() seems to use some internal buffer dir = strdup(dirname(buf)); } #endif return dir; }
void dumpnode(struct filenode *node, FILE *f) { struct romfh ri; struct filenode *p; ri.nextfh = 0; ri.spec = 0; ri.size = htonl(node->size); ri.checksum = htonl(0x55555555); if (node->pad) dumpzero(node->pad, f); if (node->next && node->next->next) ri.nextfh = htonl(node->next->offset); if ((node->modes & 0111) && (S_ISDIR(node->modes) || S_ISREG(node->modes))) ri.nextfh |= htonl(ROMFH_EXEC); if (node->orig_link) { ri.nextfh |= htonl(ROMFH_HRD); /* Don't allow hardlinks to convey attributes */ ri.nextfh &= ~htonl(ROMFH_EXEC); ri.spec = htonl(node->orig_link->offset); dumpri(&ri, node, f); } else if (S_ISDIR(node->modes)) { ri.nextfh |= htonl(ROMFH_DIR); if (listisempty(&node->dirlist)) { ri.spec = htonl(node->offset); } else { ri.spec = htonl(node->dirlist.head->offset); } dumpri(&ri, node, f); } else if (S_ISLNK(node->modes)) { ri.nextfh |= htonl(ROMFH_LNK); dumpri(&ri, node, f); memset(bigbuf, 0, sizeof(bigbuf)); readlink(node->realname, bigbuf, node->size); dumpdataa(bigbuf, node->size, f); } else if (S_ISREG(node->modes)) { int offset, len, fd, max, avail; ri.nextfh |= htonl(ROMFH_REG); dumpri(&ri, node, f); offset = 0; max = node->size; /* XXX warn about size mismatch */ fd = open(node->realname, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (fd) { while(offset < max) { avail = max-offset < sizeof(bigbuf) ? max-offset : sizeof(bigbuf); len = read(fd, bigbuf, avail); if (len <= 0) break; dumpdata(bigbuf, len, f); offset+=len; } close(fd); } max = (max+15)&~15; while (offset < max) { avail = max-offset < sizeof(bigbuf) ? max-offset : sizeof(bigbuf); memset(bigbuf, 0, avail); dumpdata(bigbuf, avail, f); offset+=avail; } } else if (S_ISCHR(node->modes)) { ri.nextfh |= htonl(ROMFH_CHR); ri.spec = htonl(major(node->devnode)<<16|minor(node->devnode)); dumpri(&ri, node, f); } else if (S_ISBLK(node->modes)) { ri.nextfh |= htonl(ROMFH_BLK); ri.spec = htonl(major(node->devnode)<<16|minor(node->devnode)); dumpri(&ri, node, f); } else if (S_ISFIFO(node->modes)) { ri.nextfh |= htonl(ROMFH_FIF); dumpri(&ri, node, f); } else if (S_ISSOCK(node->modes)) { ri.nextfh |= htonl(ROMFH_SCK); dumpri(&ri, node, f); } p = node->dirlist.head; while (p->next) { dumpnode(p, f); p = p->next; } }
static void symlink_SCCS (char* s_path, char* d_path) { struct stat dst_stat_buf; char symlink_buf[MAXPATHLEN + 1]; int count; if (access (d_path, F_OK)) /* Does d_path exit? */ { if (errno != ENOENT) { if (!quiet_flag) { fprintf (stderr, "%s: error: can't check accessability of %s: %s\n", pname, d_path, sys_errlist[errno]); fprintf (stderr, "%s: input %s will be ignored\n", pname, s_path); } return; } } else /* d_path exists. What is it? */ { if (lstat (d_path, &dst_stat_buf) == -1) { if (!quiet_flag) { fprintf (stderr, "%s: error: unable to get status of %s: %s\n", pname, d_path, sys_errlist[errno]); fprintf (stderr, "%s: input %s will be ignored\n", pname, s_path); } return; } if (S_ISLNK(dst_stat_buf.st_mode)) /* d_path is a symbolic link */ { if ((count = readlink (d_path, symlink_buf, MAXPATHLEN)) == -1) { fprintf (stderr, "%s: error: can't read symlink %s: %s\n", pname, d_path, sys_errlist[errno]); fprintf (stderr, "%s: input file %s will be ignored\n", pname, s_path); return; } symlink_buf[count] = '\0'; if (!strcmp(s_path, symlink_buf)) /* symlink = s_path. Done */ { return; } else /* symlink != s_path */ { if (force_flag) { if (remove_item (s_path, d_path) != 0) return; } else { if (!quiet_flag) { fprintf (stderr, "%s: error: Symbolic link %s already exists \ but does not point to %s\n", pname, d_path, s_path); fprintf (stderr, "%s: input s %s will be ignored\n", pname, s_path); } return; } } } else /* d_path is NOT a symbolic link */ { if (force_flag) { if (remove_item (s_path, d_path)) return; } else { if (!quiet_flag) { fprintf (stderr, "%s: error: output already exists: %s\n", pname, d_path); fprintf (stderr, "%s: input %s will be ignored\n", pname, s_path); } return; } } } if (symlink (s_path, d_path)) { if (!quiet_flag) fprintf (stderr, "%s: error: can't symlink %s to %s: %s\n", pname, s_path, d_path, sys_errlist[errno]); } else { if (verbose_flag) fprintf (stderr, "%s: created symlink %s -> %s\n", pname, d_path, s_path); } }
int sl_trustfile(const char *fname, uid_t *okusers, uid_t *badusers) { char * fexp = NULL; /* file name fully expanded */ register char *p; /* used to hold name to be checked */ struct stat stbuf; /* used to check file permissions */ char c; /* used to hold temp char */ int errgrp = 0; SL_ENTER(_("sl_trustfile")); if (fname == NULL) SL_IRETURN(SL_EBADFILE, _("sl_trustfile")); fexp = calloc(1, MAXFILENAME ); if (!fexp) SL_IRETURN(SL_EMEM, _("sl_trustfile")); p = fexp; /* * next expand to the full file name * getfname sets sl_errno as appropriate */ #ifdef TRUST_MAIN sl_errno = getfname(fname, fexp, MAXFILENAME); if (sl_errno != 0) { free(fexp); return sl_errno; } #else if (SL_ISERROR(getfname(fname, fexp, MAXFILENAME))) { free(fexp); SL_IRETURN(sl_errno, _("sl_trustfile")); } #endif if (okusers == NULL && badusers == NULL) { okusers = rootonly; rootonly[EUIDSLOT] = tf_euid; } /* * now loop through the path a component at a time * note we have to special-case root */ while(*p) { /* * get next component */ while(*p && *p != '/') p++; /* save where you are */ if (p == fexp) { /* keep the / if it's the root dir */ c = p[1]; p[1] = '\0'; } else { /* clobber the / if it isn't the root dir */ c = *p; *p = '\0'; } /* * now get the information */ if (retry_lstat(FIL__, __LINE__, fexp, &stbuf) < 0) { (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: ESTAT: stat(%s) failed,\n", fexp); fprintf(stderr, "maybe the file does not exist\n"); fprintf(stderr, "---------------------------------------------\n"); #endif free(fexp); SL_IRETURN(SL_ESTAT, _("sl_trustfile")); } #ifdef S_IFLNK /* * if it's a symbolic link, recurse */ if ((stbuf.st_mode & S_IFLNK) == S_IFLNK) { /* * this is tricky * if the symlink is to an absolute path * name, just call trustfile on it; but * if it's a relative path name, it's * interpreted WRT the current working * directory AND NOT THE FILE NAME!!!!! * so, we simply put /../ at the end of * the file name, then append the symlink * contents; trustfile will canonicalize * this, and the /../ we added "undoes" * the name of the symlink to put us in * the current working directory, at * which point the symlink contents (appended * to the CWD) are interpreted correctly. * got it? */ char * csym; /* contents of symlink file */ char * full; /* "full" name of symlink */ char *b; /* used to copy stuff around */ const char *t; /* used to copy stuff around */ int lsym; /* num chars in symlink ref */ int i; /* trustworthy or not? */ const char * t_const; char *end; /* * get what the symbolic link points to * * The original code does not check the return code of readlink(), * and has an off-by-one error * (MAXFILENAME instead of MAXFILENAME-1) * R.W. Tue May 29 22:05:16 CEST 2001 */ csym = calloc(1, MAXFILENAME ); if (!csym) { free(fexp); SL_IRETURN(SL_EMEM, _("sl_trustfile")); } lsym = readlink(fexp, csym, MAXFILENAME-1); if (lsym >= 0) csym[lsym] = '\0'; else { #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADNAME: readlink(%s) failed\n", fexp); fprintf(stderr, "---------------------------------------------\n"); #endif free(csym); free(fexp); SL_IRETURN(SL_EBADNAME, _("sl_trustfile")); } full = calloc(1, MAXFILENAME ); if (!full) { free(csym); free(fexp); SL_IRETURN(SL_EMEM, _("sl_trustfile")); } /* * relative or absolute referent? */ if (csym[0] != '/') { /* pointer to one above last element */ end = &full[MAXFILENAME-1]; ++end; /* initialize pointers */ b = full; /* copy in base path */ t = fexp; while(*t && b < end) *b++ = *t++; /* smack on the /../ */ t_const = "/../"; t = (const char *)t_const; while(*t && b < end) *b++ = *t++; /* append the symlink referent */ t = csym; while(*t && b < end) *b++ = *t++; /* see if we're too big */ if (*t || b == end) { /* yes -- error */ (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: ETRUNC: normalized path too long (%s)\n", fexp); fprintf(stderr, "---------------------------------------------\n"); #endif free(full); free(csym); free(fexp); SL_IRETURN(SL_ETRUNC, _("sl_trustfile")); } *b = '\0'; } else { /* absolute -- just copy */ /* overflow can't occur as the arrays */ /* are the same size */ (void) strcpy(full, csym); /* known to fit */ } /* * now check out this file and its ancestors */ if ((i = sl_trustfile(full, okusers, badusers)) != SL_ENONE) { free(full); free(csym); free(fexp); SL_IRETURN(i, _("sl_trustfile")); } /* * okay, this part is valid ... let's check the rest * put the / back */ if (p == fexp) { /* special case for root */ p[1] = c; p++; } else { /* ordinary case for everything else */ *p = c; if (*p) p++; } free(full); free(csym); continue; } #endif #ifdef TRUST_DEBUG fprintf(stderr, "\ntrustfile: checking path=%s\n", fexp); #endif /* * if the owner is not trusted then -- as the owner can * change protection modes -- he/she can write to the * file regardless of permissions, so bomb */ if (((okusers != NULL && S_FALSE == isin((uid_t)stbuf.st_uid,okusers))|| (badusers != NULL && S_TRUE == isin((uid_t)stbuf.st_uid,badusers)))) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADUID %s (owner not trusted)\n", fexp); fprintf(stderr, "The owner of this file/directory is not in samhains\n"); fprintf(stderr, "list of trusted users.\n"); fprintf(stderr, "Please run ./configure again with the option\n"); fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; tf_baduid = (uid_t) stbuf.st_uid; free(fexp); SL_IRETURN(SL_EBADUID, _("sl_trustfile")); } /* * if a group member can write but the * member is not trusted, bomb; but if * sticky bit semantics are honored, it's * okay */ /* Thu Mar 29 21:10:28 CEST 2001 Rainer Wichmann * replace !isingrp() with onlytrustedingrp(), as isingrp() * will return at the first trusted user, even if there are additional * (untrusted) users in the group */ if (((stbuf.st_mode & S_IWGRP) == S_IWGRP) && ((okusers != NULL && !onlytrustedingrp((gid_t)stbuf.st_gid,okusers,&errgrp))|| (badusers != NULL && isingrp((gid_t)stbuf.st_gid, badusers,&errgrp))) #ifdef STICKY && ((stbuf.st_mode&S_IFDIR) != S_IFDIR || (stbuf.st_mode&S_ISVTX) != S_ISVTX) #endif ) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADGID %ld %s (group member not trusted)\n", (UID_CAST)stbuf.st_gid, fexp); fprintf(stderr, "This file/directory is group writeable, and one of the group members\n"); fprintf(stderr, "is not in samhains list of trusted users.\n"); fprintf(stderr, "Please run ./configure again with the option\n"); fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; tf_badgid = (gid_t) stbuf.st_gid; free(fexp); SL_IRETURN((errgrp == ERANGE) ? SL_ERANGE : SL_EBADGID, _("sl_trustfile")); } /* * if other can write, bomb; but if the sticky * bit semantics are honored, it's okay */ if (((stbuf.st_mode & S_IWOTH) == S_IWOTH) #ifdef STICKY && ((stbuf.st_mode&S_IFDIR) != S_IFDIR || (stbuf.st_mode&S_ISVTX) != S_ISVTX) #endif ) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADOTH (world writeable): %s\n", fexp); fprintf(stderr, "This file/directory is world writeable.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; free(fexp); SL_IRETURN(SL_EBADOTH, _("sl_trustfile")); } /* * put the / back */ if (p == fexp) { /* special case for root */ p[1] = c; p++; } else { /* ordinary case for everything else */ *p = c; if (*p) p++; } } /* * yes, it can be trusted */ (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; free(fexp); SL_IRETURN(SL_ENONE, _("sl_trustfile")); }
/* NOTE: Caller must free the pointer, if not NULL */ char * hb_fsLinkRead( const char * pszFile ) { char * pszLink = NULL; if( pszFile ) { hb_vmUnlock(); #if defined( HB_OS_WIN ) && ! defined( HB_OS_WIN_CE ) { typedef DWORD ( WINAPI * _HB_GETFINALPATHNAMEBYHANDLE )( HANDLE, LPTSTR, DWORD, DWORD ); static _HB_GETFINALPATHNAMEBYHANDLE s_pGetFinalPathNameByHandle = NULL; #ifndef VOLUME_NAME_DOS #define VOLUME_NAME_DOS 0x0 #endif #ifndef VOLUME_NAME_GUID #define VOLUME_NAME_GUID 0x1 #endif #ifndef VOLUME_NAME_NT #define VOLUME_NAME_NT 0x2 #endif #ifndef VOLUME_NAME_NONE #define VOLUME_NAME_NONE 0x4 #endif #ifndef FILE_NAME_NORMALIZED #define FILE_NAME_NORMALIZED 0x0 #endif #ifndef FILE_NAME_OPENED #define FILE_NAME_OPENED 0x8 #endif if( ! s_pGetFinalPathNameByHandle ) { HMODULE hModule = GetModuleHandle( TEXT( "kernel32.dll" ) ); if( hModule ) s_pGetFinalPathNameByHandle = ( _HB_GETFINALPATHNAMEBYHANDLE ) HB_WINAPI_GETPROCADDRESST( hModule, "GetFinalPathNameByHandle" ); } if( s_pGetFinalPathNameByHandle ) { LPCTSTR lpFileName; LPTSTR lpFileNameFree; HANDLE hFile; DWORD dwAttr; HB_BOOL fDir; lpFileName = HB_FSNAMECONV( pszFile, &lpFileNameFree ); dwAttr = GetFileAttributes( lpFileName ); fDir = ( dwAttr != INVALID_FILE_ATTRIBUTES ) && ( dwAttr & FILE_ATTRIBUTE_DIRECTORY ); hFile = CreateFile( lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, fDir ? ( FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS ) : FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { hb_fsSetIOError( HB_FALSE, 0 ); hb_fsSetFError( hb_fsError() ); } else { DWORD size; TCHAR lpLink[ HB_PATH_MAX ]; size = s_pGetFinalPathNameByHandle( hFile, lpLink, HB_PATH_MAX, VOLUME_NAME_DOS ); if( size < HB_PATH_MAX ) { if( size > 0 ) { lpLink[ size ] = TEXT( '\0' ); pszLink = HB_OSSTRDUP( lpLink ); } hb_fsSetIOError( HB_TRUE, 0 ); hb_fsSetFError( hb_fsError() ); } else hb_fsSetFError( 1 ); } if( lpFileNameFree ) hb_xfree( lpFileNameFree ); } else hb_fsSetFError( 1 ); } #elif defined( HB_OS_UNIX ) { char * pszFileFree; size_t size; pszFile = hb_fsNameConv( pszFile, &pszFileFree ); pszLink = ( char * ) hb_xgrab( HB_PATH_MAX + 1 ); size = readlink( pszFile, pszLink, HB_PATH_MAX ); hb_fsSetIOError( size != ( size_t ) -1, 0 ); hb_fsSetFError( hb_fsError() ); if( size == ( size_t ) -1 ) { hb_xfree( pszLink ); pszLink = NULL; } else { pszLink[ size ] = '\0'; /* Convert from OS codepage */ pszLink = ( char * ) hb_osDecodeCP( pszLink, NULL, NULL ); } if( pszFileFree ) hb_xfree( pszFileFree ); } #else { hb_fsSetFError( 1 ); } #endif hb_vmLock(); } else hb_fsSetFError( 2 ); return pszLink; }
/** * Locate the Premake executable, and push its full path to the Lua stack. * Based on: * http://sourceforge.net/tracker/index.php?func=detail&aid=3351583&group_id=71616&atid=531880 * http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c * http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe */ int premake_locate_executable(lua_State* L, const char* argv0) { char buffer[PATH_MAX]; const char* path = NULL; #if PLATFORM_WINDOWS DWORD len = GetModuleFileName(NULL, buffer, PATH_MAX); if (len > 0) path = buffer; #endif #if PLATFORM_MACOSX CFURLRef bundleURL = CFBundleCopyExecutableURL(CFBundleGetMainBundle()); CFStringRef pathRef = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); if (CFStringGetCString(pathRef, buffer, PATH_MAX - 1, kCFStringEncodingUTF8)) path = buffer; #endif #if PLATFORM_LINUX int len = readlink("/proc/self/exe", buffer, PATH_MAX); if (len > 0) path = buffer; #endif #if PLATFORM_BSD int len = readlink("/proc/curproc/file", buffer, PATH_MAX); if (len < 0) len = readlink("/proc/curproc/exe", buffer, PATH_MAX); if (len > 0) path = buffer; #endif #if PLATFORM_SOLARIS int len = readlink("/proc/self/path/a.out", buffer, PATH_MAX); if (len > 0) path = buffer; #endif /* As a fallback, search the PATH with argv[0] */ if (!path) { lua_pushcfunction(L, os_pathsearch); lua_pushstring(L, argv0); lua_pushstring(L, getenv("PATH")); if (lua_pcall(L, 2, 1, 0) == OKAY && !lua_isnil(L, -1)) { lua_pushstring(L, "/"); lua_pushstring(L, argv0); lua_concat(L, 3); path = lua_tostring(L, -1); } } /* If all else fails, use argv[0] as-is and hope for the best */ if (!path) { /* make it absolute, if needed */ os_getcwd(L); lua_pushstring(L, "/"); lua_pushstring(L, argv0); if (!path_isabsolute(L)) { lua_concat(L, 3); } else { lua_pop(L, 1); } path = lua_tostring(L, -1); } lua_pushstring(L, path); return 1; }
int getService() { struct dirent **proclist; char procname[80]; char input[80]; char procEntry[1024]; int procFd; int proccount; int i, j, length; int pid = 0, ppid = 0, tgid = 0; int svccount = 0; int execount; /* Let's get our blob */ proccount = scandir("/proc/", &proclist, proc_select, alphasort); /* get all proc dirs */ if ((services = (svc_entry**)malloc(proccount * sizeof(svc_entry *))) == NULL) { return 0; } for (i = 0; i <proccount; i++ ) { snprintf(procname, 80, "/proc/%s/fd/0", proclist[i]->d_name); if (readlink(procname, input, 80) <= 0) { free(proclist[i]); continue; } if ((strncmp(input, "/dev/null", 9) != 0) && (strncmp(input, "/dev/console", 12) != 0)) { free(proclist[i]); continue; } /*This is a service */ snprintf(procname, 80, "/proc/%s/status", proclist[i]->d_name); DEBUGMSGTL(("rec:log","service proc status %s\n",procname)); if ((procFd = open(procname, O_RDONLY)) == -1) { free(proclist[i]); continue; } if (read(procFd, procEntry, 1024) == -1) { free(proclist[i]); close(procFd); continue; } for (j = 0; j < MAX_PROC_ITEMS; j++) { values[j] = strstr(procEntry, proc_items[j]); if (values[j] != NULL ) { values[j] += (strlen(proc_items[j]) + 1); } } if (values[PROC_PPID] != NULL) { if ((ppid = atoi(values[PROC_PPID])) != 1) { free(proclist[i]); close(procFd); continue; } } /* Not daemonized so continue */ if (values[PROC_PID] != NULL) pid = atoi(values[PROC_PID]); DEBUGMSGTL(("rec:log","service proc pid = %d \n", pid)); if (values[PROC_TGID] != NULL) tgid = atoi(values[PROC_TGID]); DEBUGMSGTL(("rec:log","service proc tgid = %d \n", tgid)); if (tgid != pid) { close(procFd); free(proclist[i]); continue; } length = index(values[PROC_NAME], 0x0a) - values[PROC_NAME]; if ((services[svccount] = (svc_entry*)malloc(sizeof(svc_entry))) == NULL) { close(procFd); free(proclist[i]); continue; } memset(services[svccount], 0, sizeof(svc_entry)); services[svccount]-> pid = pid; services[svccount]-> ppid = ppid; services[svccount]-> tgid = tgid; services[svccount]->name = malloc(length + 1); memset(services[svccount]->name, 0, length + 1); strncpy(services[svccount]->name, values[PROC_NAME], length); DEBUGMSGTL(("rec:log","service proc name %s\n", services[svccount]->name)); /* not a thread */ services[svccount]->filename = malloc(256); memset(services[svccount]->filename, 0, 256); snprintf(procname, 80, "/proc/%s/exe", proclist[i]->d_name); if ((execount = readlink(procname, services[svccount]->filename, 256)) == -1) { free(proclist[i]); close(procFd); if (services[svccount]->filename != NULL ) free(services[svccount]->filename); if (services[svccount]->name != NULL ) free(services[svccount]->name); free(services[svccount]); continue; } DEBUGMSGTL(("rec:log","service file name %s\n", services[svccount]->filename)); svccount++; free(proclist[i]); close(procFd); } free(proclist); return svccount; }