"Fossies" - the Fresh Open Source Software Archive

Member "links-1.03/file.c" (16 Nov 2011, 9689 Bytes) of archive /linux/www/links-1.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "file.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8_vs_1.03.

    1 /* file.c
    2  * (c) 2002 Mikulas Patocka
    3  * This file is a part of the Links program, released under GPL.
    4  */
    5 
    6 #include "links.h"
    7 
    8 #ifdef FS_UNIX_RIGHTS
    9 static void setrwx(int m, unsigned char *p)
   10 {
   11     if(m & S_IRUSR) p[0] = 'r';
   12     if(m & S_IWUSR) p[1] = 'w';
   13     if(m & S_IXUSR) p[2] = 'x';
   14 }
   15 
   16 static void setst(int m, unsigned char *p)
   17 {
   18 #ifdef S_ISUID
   19     if (m & S_ISUID) {
   20         p[2] = 'S';
   21         if (m & S_IXUSR) p[2] = 's';
   22     }
   23 #endif
   24 #ifdef S_ISGID
   25     if (m & S_ISGID) {
   26         p[5] = 'S';
   27         if (m & S_IXGRP) p[5] = 's';
   28     }
   29 #endif
   30 #ifdef S_ISVTX
   31     if (m & S_ISVTX) {
   32         p[8] = 'T';
   33         if (m & S_IXOTH) p[8] = 't';
   34     }
   35 #endif
   36 }
   37 #endif
   38 
   39 static void stat_mode(unsigned char **p, int *l, struct stat *stp)
   40 {
   41     unsigned char c = '?';
   42     if (stp) {
   43         if (0) {}
   44 #ifdef S_ISBLK
   45         else if (S_ISBLK(stp->st_mode)) c = 'b';
   46 #endif
   47 #ifdef S_ISCHR
   48         else if (S_ISCHR(stp->st_mode)) c = 'c';
   49 #endif
   50         else if (S_ISDIR(stp->st_mode)) c = 'd';
   51         else if (S_ISREG(stp->st_mode)) c = '-';
   52 #ifdef S_ISFIFO
   53         else if (S_ISFIFO(stp->st_mode)) c = 'p';
   54 #endif
   55 #ifdef S_ISLNK
   56         else if (S_ISLNK(stp->st_mode)) c = 'l';
   57 #endif
   58 #ifdef S_ISSOCK
   59         else if (S_ISSOCK(stp->st_mode)) c = 's';
   60 #endif
   61 #ifdef S_ISNWK
   62         else if (S_ISNWK(stp->st_mode)) c = 'n';
   63 #endif
   64     }
   65     add_chr_to_str(p, l, c);
   66 #ifdef FS_UNIX_RIGHTS
   67     {
   68         unsigned char rwx[10] = "---------";
   69         if (stp) {
   70             int mode = stp->st_mode;
   71             setrwx(mode << 0, &rwx[0]);
   72             setrwx(mode << 3, &rwx[3]);
   73             setrwx(mode << 6, &rwx[6]);
   74             setst(mode, rwx);
   75         }
   76         add_to_str(p, l, rwx);
   77     }
   78 #endif
   79     add_chr_to_str(p, l, ' ');
   80 }
   81 
   82 
   83 static void stat_links(unsigned char **p, int *l, struct stat *stp)
   84 {
   85 #ifdef FS_UNIX_HARDLINKS
   86     unsigned char lnk[64];
   87     if (!stp) add_to_str(p, l, "    ");
   88     else {
   89         sprintf(lnk, "%3ld ", (unsigned long)stp->st_nlink);
   90         add_to_str(p, l, lnk);
   91     }
   92 #endif
   93 }
   94 
   95 #ifdef FS_UNIX_USERS
   96 static int last_uid = -1;
   97 static unsigned char last_user[64];
   98 
   99 static int last_gid = -1;
  100 static unsigned char last_group[64];
  101 #endif
  102 
  103 static void stat_user(unsigned char **p, int *l, struct stat *stp, int g)
  104 {
  105 #ifdef FS_UNIX_USERS
  106     struct passwd *pwd;
  107     struct group *grp;
  108     int id;
  109     unsigned char *pp;
  110     int i;
  111     if (!stp) {
  112         add_to_str(p, l, "         ");
  113         return;
  114     }
  115     id = !g ? stp->st_uid : stp->st_gid;
  116     pp = !g ? last_user : last_group;
  117     if (!g && id == last_uid && last_uid != -1) goto a;
  118     if (g && id == last_gid && last_gid != -1) goto a;
  119     if (!g) {
  120         if (!(pwd = getpwuid(id)) || !pwd->pw_name) sprintf(pp, "%d", id);
  121         else sprintf(pp, "%.8s", pwd->pw_name);
  122         last_uid = id;
  123     } else {
  124         if (!(grp = getgrgid(id)) || !grp->gr_name) sprintf(pp, "%d", id);
  125         else sprintf(pp, "%.8s", grp->gr_name);
  126         last_gid = id;
  127     }
  128     a:
  129     add_to_str(p, l, pp);
  130     for (i = strlen(pp); i < 8; i++) add_chr_to_str(p, l, ' ');
  131     add_chr_to_str(p, l, ' ');
  132 #endif
  133 }
  134 
  135 static void stat_size(unsigned char **p, int *l, struct stat *stp)
  136 {
  137     unsigned char num[64];
  138     const int digits = 8;
  139     int i;
  140     if (!stp) {
  141         num[0] = 0;
  142     } else {
  143         snprint(num, sizeof num, stp->st_size);
  144     }
  145     for (i = strlen(num); i < digits; i++)
  146         add_chr_to_str(p, l, ' ');
  147     add_to_str(p, l, num);
  148     add_chr_to_str(p, l, ' ');
  149 }
  150 
  151 static void stat_date(unsigned char **p, int *l, struct stat *stp)
  152 {
  153     time_t current_time = time(NULL);
  154     time_t when;
  155     struct tm *when_local;
  156     unsigned char *fmt;
  157     unsigned char str[13];
  158     int wr;
  159     if (!stp) {
  160         add_to_str(p, l, "             ");
  161         return;
  162     }
  163     when = stp->st_mtime;
  164     when_local = localtime(&when);
  165     if (current_time > when + 6L * 30L * 24L * 60L * 60L || 
  166         current_time < when - 60L * 60L) fmt = "%b %e  %Y";
  167     else fmt = "%b %e %H:%M";
  168 #ifdef HAVE_STRFTIME
  169     wr = strftime(str, 13, fmt, when_local);
  170 #else
  171     wr = 0;
  172 #endif
  173     while (wr < 12) str[wr++] = ' ';
  174     str[12] = 0;
  175     add_to_str(p, l, str);
  176     add_chr_to_str(p, l, ' ');
  177 }
  178 
  179 static unsigned char *get_filename(unsigned char *url)
  180 {
  181     unsigned char *p, *m;
  182     int ml;
  183 #ifdef DOS_FS
  184     if (url[7] == '/' && strchr(url + 8, ':')) url++;
  185 #endif
  186     for (p = url + 7; *p && *p != POST_CHAR; p++)
  187         ;
  188     m = init_str(), ml = 0;
  189     add_conv_str(&m, &ml, url + 7, p - url - 7, -2);
  190     return m;
  191 }
  192 
  193 struct dirs {
  194     unsigned char *s;
  195     unsigned char *f;
  196 };
  197 
  198 LIBC_CALLBACK static int comp_de(struct dirs *d1, struct dirs *d2)
  199 {
  200     if (d1->f[0] == '.' && d1->f[1] == '.' && !d1->f[2]) return -1;
  201     if (d2->f[0] == '.' && d2->f[1] == '.' && !d2->f[2]) return 1;
  202     if (d1->s[0] == 'd' && d2->s[0] != 'd') return -1;
  203     if (d1->s[0] != 'd' && d2->s[0] == 'd') return 1;
  204     return strcmp(d1->f, d2->f);
  205 }
  206 
  207 void file_func(struct connection *c)
  208 {
  209     struct cache_entry *e;
  210     unsigned char *file, *name, *head = NULL; /* against warning */
  211     int fl;
  212     DIR *d;
  213     int h, r;
  214     struct stat stt;
  215     if (anonymous) {
  216         setcstate(c, S_BAD_URL);
  217         abort_connection(c);
  218         return;
  219     }
  220     if (!(name = get_filename(c->url))) {
  221         setcstate(c, S_OUT_OF_MEM); abort_connection(c); return;
  222     }
  223     if (stat(name, &stt)) {
  224         mem_free(name);
  225         setcstate(c, get_error_from_errno(errno)); abort_connection(c); return;
  226     }
  227     if (!S_ISDIR(stt.st_mode) && !S_ISREG(stt.st_mode)) {
  228         mem_free(name);
  229         setcstate(c, S_FILE_TYPE); abort_connection(c); return;
  230     }
  231     if ((h = open(name, O_RDONLY | O_NOCTTY)) == -1) {
  232         int er = errno;
  233         if ((d = opendir(name))) goto dir;
  234         mem_free(name);
  235         setcstate(c, get_error_from_errno(er));
  236         abort_connection(c);
  237         return;
  238     }
  239     set_bin(h);
  240     if (S_ISDIR(stt.st_mode)) {
  241         struct dirs *dir;
  242         int dirl;
  243         int i;
  244         struct dirent *de;
  245         d = opendir(name);
  246         close(h);
  247         if (!d) {
  248             mem_free(name);
  249             setcstate(c, get_error_from_errno(errno)); abort_connection(c); return;
  250         }
  251         dir:
  252         dir = DUMMY, dirl = 0;
  253         if (name[0] && !dir_sep(name[strlen(name) - 1])) {
  254             if (get_cache_entry(c->url, &e)) {
  255                 mem_free(name);
  256                 closedir(d);
  257                 setcstate(c, S_OUT_OF_MEM); abort_connection(c); return;
  258             }
  259             c->cache = e;
  260             e->refcount--;
  261             if (e->redirect) mem_free(e->redirect);
  262             e->redirect = stracpy(c->url);
  263             e->redirect_get = 1;
  264             add_to_strn(&e->redirect, "/");
  265             mem_free(name);
  266             closedir(d);
  267             goto end;
  268         }
  269 #ifdef FS_UNIX_USERS
  270         last_uid = -1;
  271         last_gid = -1;
  272 #endif
  273         file = init_str();
  274         fl = 0;
  275         add_to_str(&file, &fl, "<html><head><title>");
  276         add_conv_str(&file, &fl, name, strlen(name), -1);
  277         add_to_str(&file, &fl, "</title></head><body><h2>Directory ");
  278         add_conv_str(&file, &fl, name, strlen(name), -1);
  279         add_to_str(&file, &fl, "</h2><pre>");
  280         while ((de = (void *)readdir(d))) {
  281             struct stat stt, *stp;
  282             unsigned char **p;
  283             int l;
  284             unsigned char *n;
  285             if (!strcmp(de->d_name, ".")) continue;
  286             if ((unsigned)dirl > MAXINT / sizeof(struct dirs) - 1) overalloc();
  287             dir = mem_realloc(dir, (dirl + 1) * sizeof(struct dirs));
  288             dir[dirl].f = stracpy(de->d_name);
  289             *(p = &dir[dirl++].s) = init_str();
  290             l = 0;
  291             n = stracpy(name);
  292             add_to_strn(&n, de->d_name);
  293 #ifdef FS_UNIX_SOFTLINKS
  294             if (lstat(n, &stt))
  295 #else
  296             if (stat(n, &stt))
  297 #endif
  298                  stp = NULL;
  299             else stp = &stt;
  300             mem_free(n);
  301             stat_mode(p, &l, stp);
  302             stat_links(p, &l, stp);
  303             stat_user(p, &l, stp, 0);
  304             stat_user(p, &l, stp, 1);
  305             stat_size(p, &l, stp);
  306             stat_date(p, &l, stp);
  307         }
  308         closedir(d);
  309         if (dirl) qsort(dir, dirl, sizeof(struct dirs), (int(*)(const void *, const void *))comp_de);
  310         for (i = 0; i < dirl; i++) {
  311             unsigned char *lnk = NULL;
  312 #ifdef FS_UNIX_SOFTLINKS
  313             if (dir[i].s[0] == 'l') {
  314                 unsigned char *buf = NULL;
  315                 int size = 0;
  316                 int r;
  317                 unsigned char *n = stracpy(name);
  318                 add_to_strn(&n, dir[i].f);
  319                 do {
  320                     if (buf) mem_free(buf);
  321                     size += ALLOC_GR;
  322                     if ((unsigned)size > MAXINT) overalloc();
  323                     buf = mem_alloc(size);
  324                     r = readlink(n, buf, size);
  325                 } while (r == size);
  326                 if (r == -1) goto yyy;
  327                 buf[r] = 0;
  328                 lnk = buf;
  329                 goto xxx;
  330                 yyy:
  331                 mem_free(buf);
  332                 xxx:
  333                 mem_free(n);
  334             }
  335 #endif
  336             /*add_to_str(&file, &fl, "   ");*/
  337             add_to_str(&file, &fl, dir[i].s);
  338             add_to_str(&file, &fl, "<a href=\"./");
  339             add_conv_str(&file, &fl, dir[i].f, strlen(dir[i].f), 1);
  340             if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "/");
  341             else if (lnk) {
  342                 struct stat st;
  343                 unsigned char *n = stracpy(name);
  344                 add_to_strn(&n, dir[i].f);
  345                 if (!stat(n, &st)) if (S_ISDIR(st.st_mode)) add_to_str(&file, &fl, "/");
  346                 mem_free(n);
  347             }
  348             add_to_str(&file, &fl, "\">");
  349             /*if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "<font color=\"yellow\">");*/
  350             add_conv_str(&file, &fl, dir[i].f, strlen(dir[i].f), 0);
  351             /*if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "</font>");*/
  352             add_to_str(&file, &fl, "</a>");
  353             if (lnk) {
  354                 add_to_str(&file, &fl, " -> ");
  355                 add_to_str(&file, &fl, lnk);
  356                 mem_free(lnk);
  357             }
  358             add_to_str(&file, &fl, "\n");
  359         }
  360         mem_free(name);
  361         for (i = 0; i < dirl; i++) mem_free(dir[i].s), mem_free(dir[i].f);
  362         mem_free(dir);
  363         add_to_str(&file, &fl, "</pre></body></html>\n");
  364         head = stracpy("\r\nContent-Type: text/html\r\n");
  365     } else {
  366         mem_free(name);
  367         if (stt.st_size > MAXINT) {
  368             close(h);
  369             setcstate(c, S_LARGE_FILE); abort_connection(c);
  370             return;
  371         }
  372         /* + !stt.st_size is there because of bug in Linux. Read returns
  373            -EACCES when reading 0 bytes to invalid address */
  374         file = mem_alloc(stt.st_size + !stt.st_size);
  375         if ((r = read(h, file, stt.st_size)) != stt.st_size) {
  376             mem_free(file); close(h);
  377             setcstate(c, r == -1 ? get_error_from_errno(errno) : S_FILE_ERROR);
  378             abort_connection(c); return;
  379         }
  380         close(h);
  381         fl = stt.st_size;
  382         head = stracpy("");
  383     }
  384     if (get_cache_entry(c->url, &e)) {
  385         mem_free(file);
  386         setcstate(c, S_OUT_OF_MEM); abort_connection(c); return;
  387     }
  388     c->cache = e;
  389     e->refcount--;
  390     if (e->head) mem_free(e->head);
  391     e->head = head;
  392     add_fragment(e, 0, file, fl);
  393     truncate_entry(e, fl, 1);
  394     mem_free(file);
  395     end:
  396     c->cache->incomplete = 0;
  397     setcstate(c, S_OK);
  398     abort_connection(c);
  399 }