Commit 75667a28 authored by jan.koester's avatar jan.koester
Browse files

head fixed

parent 0e162cc0
Loading
Loading
Loading
Loading
+50 −0
Changes for commands/text/head.cpp: 50 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -29,6 +29,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <fcntl.h>

#include "shell.h"
#include "textutil.h"
@@ -95,6 +100,51 @@ namespace fresh { namespace cmd {
            bool first=true;
            for(auto &f: files){
                std::string data;
                if(!allBut){
                    // first N lines/bytes: stream and stop early (so
                    // "yes | head" ends), leaving a seekable input
                    // positioned right after what was printed
                    int fd=f=="-" ? 0 : open(f.c_str(),O_RDONLY);
                    if(fd<0){
                        out.flush();
                        std::cerr << "head: cannot open '" << f << "' for reading: " << strerror(errno) << std::endl;
                        status=1;
                        continue;
                    }
                    if(showHeaders){
                        out << (first ? "" : "\n") << "==> " << (f=="-" ? "standard input" : f) << " <==\n";
                    }
                    first=false;
                    long long left=count;
                    char buf[65536];
                    while(left>0){
                        ssize_t r=::read(fd,buf,sizeof buf);
                        if(r<0){
                            if(errno==EINTR) continue;
                            out.flush();
                            std::cerr << "head: error reading '" << f << "': " << strerror(errno) << std::endl;
                            status=1;
                            break;
                        }
                        if(r==0) break;
                        size_t take=0;
                        if(bytes){
                            take=(size_t)std::min<long long>(left,r);
                            left-=(long long)take;
                        }else{
                            while(take<(size_t)r && left>0){
                                const char *nl=(const char*)memchr(buf+take,'\n',(size_t)r-take);
                                if(!nl){ take=(size_t)r; break; }
                                take=(size_t)(nl-buf)+1;
                                --left;
                            }
                        }
                        out.write(buf,take);
                        if(take<(size_t)r) lseek(fd,(off_t)take-(off_t)r,SEEK_CUR);
                    }
                    if(fd!=0) close(fd);
                    continue;
                }
                if(!text::readInput(f,data)){
                    out.flush();
                    std::cerr << "head: cannot open '" << f << "' for reading: " << strerror(errno) << std::endl;