使用 fstat() 判斷 File Descriptor 的種類

Beej’s Guide 看到這一句話:select() only works with socket descriptors, not file descriptors (like 0 for stdin),想到我之前曾經把 tun/tap 的 file descriptor 丟進 select 裡面,不曉得我是不是做錯了。於是開始了一連串的搜尋,想要搞清楚 select 到底可以接受哪些 file descriptor…

大約花了快兩天的時間,我把相關的關鍵字都搜尋了一遍,然後把 man 2 select 與 man 2 select_tut 也看完了,接著跑去找出之前的程式,確認 tun/tap 並不是 socket descriptor 但是程式卻正常運作….

最後翻出手邊的 Linux 系統程式設計 這本書,把第二章重新看了一遍,發現書中直接就拿 STDIN_FILENO 丟進 select 來當範例。

嗯…難道是 Beej 亂寫嗎?
跑回去看那一篇文章,才發現他寫的是 Note for Windows Programmers 也就是說其實指的是 Winsock 的情況。

算了,反正看了那堆東西我還是有點收穫的,其中之一就是這個,如何判斷 fd 的種類:

參考:http://pubs.opengroup.org/onlinepubs/009695399/functions/fstat.html

在 Ubuntu Server 12.04 安裝 Redmine

寫這篇主要是簡化了官方的安裝教學
官方教學裡面包含了很多不同的情況,所以看起來複雜了一些。
如果你的 Ubuntu 是剛裝好的新系統,而且只是要將 Redmine 安裝起來,只打算跑 Redmine 一個網站,那只要把下面這些命令跑完就行了:

上面的命令會修改到 /etc/apache2/sites-available/default,讓 Redmine 成為預設網站,修改後的設定檔應該長成這樣:

另外,如果要安裝新版的 Redmine,那需要多一些步驟:

接著就可以用瀏覽器打開 Redmine 網頁了,記得先修改 admin 的密碼。
這篇算是最簡化的作法了,如果這個 Redmine 是放在網路上公開存取的話,建議還要加上 https 與其它安全性設定。

Android ToyVpn by native code

今兒個練習使用 Android 的 VpnService,為了能使用手邊現有的 C++ 程式碼,需要使用 NDK 來寫原生程式。弄一弄覺得在 Java 與 C 之間切換實在有夠麻煩,索性把 Android SDK 裡面附的 ToyVpn 改用 C 語言重寫一次。Java 部份就只負責 UI 的互動,與一些初始化的動作而已,其餘的部份都交給 C 去執行,應該效能也會更好(吧?)。

大致上運作方式都沒有變,傳輸也依然沒有加密,使用者密碼也還是寫死狀態。
只加上了一個 Keep Alive 的功能,讓它閒置一段時間也不會斷線。

完整的程式碼在 GitHub:
https://github.com/weichenlin/NativeToyVpn

2013/12/20 更新:
增加了一個支援多 client 的 server
主要差異在於需要給每個 client 不同的 ip 做區別
另外還需要稍微分析一下封包的位址才能分辨到底是要給誰的
程式碼一樣放在 GitHub

[參考資料]
一篇很好的 tun/tap 入門教學:http://backreference.org/2010/03/26/tuntap-interface-tutorial/
比較詳細的運作原理:http://www.ibm.com/developerworks/cn/linux/l-tuntap/index.html
tcp/ip stack:https://github.com/saminiir/level-ip

JNI Type Signatures

想要從 C 語言呼叫 Java 時會用到這個。
基本上就是用一些代號來表達函式的參數與回傳值。

各個資料型態與對應的代號:

要注意的地方:

  • 物件名稱以L開頭後面接上完整的名稱,並以分號結尾。
  • 除了表示物件以外,其它的資料型態不需要分號,直接連著就可以。

一些參考網站:
http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html
http://87showmin.blogspot.tw/2009/06/java-java-native-interfacejni.html

好用的sshfs

以前要存取遠端主機的檔案時,大部分都採用 NFS 來做。
但是臨時需要存取時,又很懶得設定 NFS。

sshfs 是利用 ssh 連線來將遠端主機的檔案掛載到本機來,用起來很方便,速度也不差。
而且我個人最中意的一點就是透過 ssh 連線,傳輸過程直接是加密的。
這一點在 NFS 就不是那麼方便了,要使用 NFSV4 並且 Client 與 Server 都要設定好才能加密網路傳輸。
閱讀全文

vsftpd 設定共用資料夾

平台是 Linux + vsftpd 3
主要用途是公司部門內同事分享檔案用,所以需要有個共用資料夾讓大家能共同存取。
基本的設定就略過,這邊主要將分享共用資料夾的方法記錄下來。

首先先建立一個群組用來分享檔案

然後建立分享用的資料夾

將權限設定好, 除了給群組完整的權限以外, 還要加上sticky bit, 讓ftp新增或上傳的檔案有相同的群組權限

接著是修改 vsftpd.conf, 加入 umask 的設定

以上準備工作就算完成了, 下面針對每個要存取共享資料的帳號做設定
先是將帳號加進群組裡, 假設帳號是 peter

然後在家目錄內增加共享資料夾

以上, 所有的使用者就可以共享一個資料夾, 也都可以任意刪除檔案
如果希望使用者只能刪除或修改自己上傳的東西也可以
只要將 vsftpd.conf 裡的 umask 改成 027 即可

Windows Server 2012 安裝 IIS PHP MySQL

今天下載了 Windows Server 2012 試用版來玩玩。
第一個感想:不知道怎麼關機…
以下隨性的紀錄一下過程與問題。

安裝 IIS,PHP 與 MySQL
IIS 就從 Server Manager 去新增 Role 就可以了,PHP 跟 MySQL 則是去下載 Web Platform Installer (WebPI) 來安裝。

WebPI 這東西很像 Linux 上的套件管理系統,可以幫你安裝許多東西,還順便弄些初始設定。

MySQL安裝好後,預設是 listen 0.0.0.0 的。所以如果只是本機用,二話不說先去改成 127.0.0.1。
去 Program Files 裡找到 MySQL 的資料夾,修改 my.ini ,加入 bind-address=127.0.0.1 然後重啟服務就可以了。

PHP 的部份沒遇到什麼特殊的問題,基本上直接就可以使用。

接著將一個使用 CodeIgniter 的網站放上去測試看看,第一步先設定 url rewrite:

  • 打開IIS Manager
  • 選擇要編輯的站台
  • 點選 URL Rewrite
  • 點選 Add Rules
  • 點選 Blank rule
  • Name: 隨意取個名字
  • Pattern: 輸入 ^(.*)$
  • 點開 Conditions
  • 新增 rule,選擇 Is Not a File
  • 新增 rule,選擇 Is Not a Directory
  • 最後到底下的 Action,Rewrite URL 填入 index.php

這樣子就設定好了,正常運作。
參考: http://quitedestroyer.blogspot.tw/2012/05/codeigniter-url-rewriting-on-iis-7.html

若是需要上傳檔案,對資料夾要有寫入權限。
安全性比較要求的站可以針對 IIS 來設定權限。
懶一點的就將上傳資料夾直接開放所有權限給 Users 群組即可。

當 php 連往 localhost 的資料庫時,會有延遲。
在我的環境大約是延遲了一秒鐘,簡直慢到想直接放棄…
最後查到這個是普遍問題,在 Server 2012 以及 Windows 8 都會發生。
最佳解法就是在 php 連接資料庫時,不要用 “localhost”,而是改用 127.0.0.1 去連線。
參考: http://forums.iis.net/t/1200661.aspx

Android NDK Eclipse 開發環境自動編譯設定

NDK不太常用,每次要用時都要重新翻資料找設定方法,乾脆寫一篇記錄下來。

環境設定,只需要一開始做一次:
1. 先確認 NDK 有安裝好:http://developer.android.com/sdk/ndk/index.html

2. 安裝 Eclipse 需要的套件:
CDT package
NDK package

3. 設定 NDK 路徑,工具列 Window -> Preferences -> Android -> NDK ,輸入 NDK 的路徑:
ndk path

專案設定,每個要使用 NDK 的專案都要做:
1. 專案上面按右鍵,Android Tools -> Add Native Support :
add_ndk_support
然後設定一個 library 的名稱:
enter library name
這時 Android.mk 與 C++ 原始碼檔案都幫你建立好了。

2. 設定 C++ Include 路徑,進入專案 Properties ,C/C++ General -> Paths and Symbols,加入:

include path
${env_var:ANDROID_NDK} 是我在系統 PATH 裡設定好的 NDK 所在位置。

額外的工具:使用 javah 自動產生 .h 檔
1. 設定 Eclipse External Tools ,工具列 Run -> External Tools -> External Tools Configurations :

  • Name 取一個與專案有關的比較好記。
  • Location 填入 javah 執行檔的路徑。
  • Working Directory 填入

    其中 NdkProject 是專案名稱。
  • Arguments 填入

    external tool 1
    最後的 com.example.ndkproject.MainActivity 是要使用 NDK 的類別的 fully qualified class name 。(若是在 Linux 底下,classpath 要改成 ${workspace_loc:/NdkProject/bin/classes})
  • 切換到 Refresh 分頁,勾選 Refresh resources upon completion ,使用 Specific resources 選項,在右邊選擇 jni 資料夾
    external tool 2

2. 在需要呼叫 NDK 的 Java 原始碼中加入程式,用來載入 library 並定義原生函式:

3. 按下工具列的 Run -> External Tools -> 剛剛設定的 javah ,即會幫你產生 Native 用的 .h 檔案。

可能遇到的問題
1. 出現警告: Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml
解決方法:在 jni 資料夾中新增 Application.mk 檔案,指定 SDK 的版本

以上都設定好,就會看到每次執行 debug 時,會自動使用 ndk 編譯了。